자동차 해킹과 관련된(혹은 관련되지 않은..) CTF 문제들입니다.
Rev 2문제, Pwn 4문제, Misc 2문제로 이루어져 있었고 이후에 문제가 추가된 것 같긴 한데 그 전에 가버려서.. 제가 푼 문제들만 Write Up 적어봅니다.

1. locked not safely(rev)
- 여러 센서 값이 동시에 올라오는 차량 시스템에서, 일부 센서가 의도적으로 통신 잠금을 무시해 잘못된 값을 보내는 상황을 가정한 문제
- 센서 값(Counter)이 정확히 누적되지 않는 이유를 분석하고, 이를 수정해 정상적으로 데이터가 반영되도록 바이너리를 패치
- 정상적으로 고치는 것 보다는 그냥 조건문을 우회하는게 더 쉬울 것 같아 방향을 그렇게 잡고 분석 진행
- IDA를 통해
locked_not_safely.exe분석, main 함수 내부에서 다음과 같은 조건문을 확인cmp eax, 0x4C4B40 ; 5000000 jnz short loc_xxxxxx ; 같지 않으면 flag 출력 X - 바이너리에서 해당 부분의 코드를 확인해보면
3D 40 4B 4C 00:cmp eax, 0x4C4B40,75 30:jnz +0x30임을 알 수 있음 - HxD를 활용해 조건 분기(
75 30)을 NOP(90 90)으로 덮어씌움으로써 jnz 조건 분기를 제거한 이후 실행시키면 counter 값과 무관하게 항상 플래그가 출력됨└─$ ./locked_not_safely Final counter value^^: 1681834 Counter has reached the target value! flag: 4b1d61g932 - flag:
AH{4b1d61g932}
2. can u canlog can0(misc)
- 진짜 무슨 문젠지 기억이 안난다
- 어떻게 찍어놓은 것도 없고 남겨놓은 기록도 없는
- 1분만에 푼거 보면 엄청 쉬운 문제였던 것 같은데 진짜로 기억이 안난다...
3. unreal logic(rev)
chall이라는 바이너리 파일이 주어지고 프로그램 실행 시 Welcome to the challenge!! 출력 후 플래그 입력을 받음- 입력된 문자열은 내부에 있는 세 가지 배열과 여러 변환 함수를 거쳐 검증, 검증에 실패하면 "It's not real~ find real flag lol" 또는 "it's wrong maybe..?" 메시지 출력
- 첫 번째 검증 (입력 바이트 0~16)
v1 = ((rol8(byte_40E0[i], 3) ^ 0x1F) + 7) ^ 0x2B; if (v1 != byte_4030[i]) fail;- 입력 바이트 1바이트를 왼쪽으로 3비트 회전한 후 XOR, 덧셈, XOR 연산을 수행해
byte_4030와 비교
- 입력 바이트 1바이트를 왼쪽으로 3비트 회전한 후 XOR, 덧셈, XOR 연산을 수행해
- 두 번째 검증 (입력 바이트 17~33)
t1 = ror8((byte_40E0[i+17] + 12) ^ 0x2E, 2) ^ 0x47; if (t1 != byte_4050[i]) fail;- 입력 바이트에 12를 더하고 XOR 후 오른쪽 2비트 회전, XOR를 수행해
byte_4050와 비교
- 입력 바이트에 12를 더하고 XOR 후 오른쪽 2비트 회전, XOR를 수행해
- 메인 검증 (입력 전체 49바이트)
for (i = 0; i < 49; i++) { if (i % 2 == 1) v4 = (((byte_40E0[i] ^ 0x77) + 28) ^ 0x4D) - 9; else v4 = (((byte_40E0[i] + 16) ^ 0xAA) - 5) ^ 0x33; if (v4 != byte_4080[i]) fail; }- 홀수, 짝수 인덱스에 따라 각각 XOR, 덧셈, XOR, 뺄셈, XOR 연산 수행해
byte_4080배열과 비교
- 홀수, 짝수 인덱스에 따라 각각 XOR, 덧셈, XOR, 뺄셈, XOR 연산 수행해
- 역산을 통해 flag를 복원하는 코드를 Python으로 작성
def rol8(val, n): return ((val << n) | (val >> (8 - n))) & 0xFF def ror8(val, n): return ((val >> n) | (val << (8 - n))) & 0xFF byte_4030 = [0xE0, 0x18, 0xB6, 0x58, 0x68, 0xC7, 0xA6, 0x58, 0xE8, 0xBF, 0xF0, 0xC7, 0x88, 0x8E, 0xB6, 0x58, 0xEF] byte_4050 = [0x16, 0x92, 0xDC, 0x11, 0x03, 0x13, 0x16, 0xAD, 0xC3, 0xAC, 0x16, 0xD1, 0xDC, 0xD3, 0xD3, 0x95, 0xAE] byte_4080 = [ 0xEA, 0x24, 0xE9, 0x65, 0xD7, 0x63, 0xF3, 0x26, 0xFC, 0x49, 0xD6, 0x00, 0x1A, 0x6D, 0xD7, 0x00, 0xDA, 0x73, 0x2D, 0x0A, 0x17, 0x00, 0xFA, 0x70, 0xF3, 0x64, 0xD5, 0x72, 0x16, 0x26, 0x8D, 0x00, 0x17, 0x09, 0x2D, 0x6E, 0xFC, 0x58, 0xF3, 0x26, 0x1A, 0x00, 0xD5, 0x0A, 0xF3, 0x57, 0xDA, 0x6C, 0xE9 ] # 0~16 역산 part1 = [] for i in range(17): val = byte_4030[i] t = ((val ^ 0x2B) - 7) & 0xFF t ^= 0x1F b = ror8(t, 3) part1.append(b) # 17~33 역산 part2 = [] for i in range(17): val = byte_4050[i] t1 = val ^ 0x47 t0 = rol8(t1, 2) b = (t0 ^ 0x2E) - 12 b &= 0xFF part2.append(b) # 34~48 역산 part3 = [] for i in range(34, 49): v4 = byte_4080[i] if i & 1: val = ((v4 + 9) ^ 0x4D) - 28 b = val ^ 0x77 else: val = ((v4 ^ 0x33) + 5) ^ 0xAA b = val - 16 b &= 0xFF part3.append(b) flag_bytes = part1 + part2 + part3 print("Flag as ASCII:") print(bytes(flag_bytes).decode())└─$ ./chall Welcome to the challenge!! {f1nd_3ntRy_p01nT_m4k3s_y0u_h4ppY} correct~!! I lost, you win - flag:
AH{f1nd_3ntRy_p01nT_m4k3s_y0u_h4ppY}
후기

친구가 misc 한문제를 해결하여 총 4문제를 풀었고 중간에 나가서 최종 점수와 순위는 확인하지 못했지만 4등, 1240점 정도로 마무리 지었습니다.
팀으로 참가할 수 있어서 동아리 친구들과 재미있게 풀었습니다.