
분석 환경
| 파일명 | chall9.exe |
| MD5 | 58f5f02b39f67017beaf7ed3a6f94be7 |
| SHA256 | 8c548aaaefc26e72ae7b964c7c837bf2d56152ae0dd0745fc42c4c6fe9529982 |
| 분석 환경 | Window 10 Pro, 64비트 운영 체제 |
분석
1) 파일 헤더 확인
문제 파일은 Visual Studio 2008로 제작된 PE 파일이며, console 환경에서 64bit로 동작하는 것을 확인할 수 있다.
[ PE 구조 값 확인 ]
- first-bytes-text: MZ
- tooling: Visual Studio 2008
- file-type: executable
- cpu: 64-bit
- subsystem: console

2) 파일 실행
파일을 더블 클릭하여 실행시키면, Input 값을 입력하자마자 종료된다.
cmd 에서 실행시켜, 파일의 결과 값을 확인한다.

3) 바이너리 분석
문제 파일은 64bit에서 동작하는 프로그램이므로, ida64.exe를 통해 분석을 진행하였다.
main 함수에서 Correct와 Wrong 문자열을 출력하는 부분을 결정하는 것으로 추정되는 sub_140001000 함수를 확인해보겠다.

# sub_140001000
해당 함수를 더블 클릭하여 단축키[F5]를 누르면 C언어로 디컴파일된다.

# sub_140001000 > line 6 - 8
디컴파일 한 코드를 보면 strlen 함수로 문자열의 길이를 저장한다.
문자열 길이에 1을 더하여 8로 나누었을 때 나머지가 0이 아니면 함수를 종료한다. (return 0i64 는 return 0을 의미)
(v3 + 1) % 8
# sub_140001000 > line 9 - 11
# sub_1400010A0
for문을 보면 사용자의 입력 값을 한글자씩 sub_1400010A0 함수의 인수로 사용하여 값을 전달하고 있다.
'sub_1400010A0' 함수를 더블 클릭하면 해당 함수의 위치로 이동할 수 있다.

'byte_140004020' 에는 아래와 같이 많은 데이터가 들어가 있었다.
이를 이용하여 flag 값을 구하는 부분을 찾은 것 같다.

__int64 __fastcall sub_1400010A0(unsigned __int8 *a1)
{
__int64 result; // rax
unsigned __int8 v2; // [rsp+0h] [rbp-48h]
int j; // [rsp+4h] [rbp-44h]
int i; // [rsp+8h] [rbp-40h]
char v5[16]; // [rsp+10h] [rbp-38h] BYREF
strcpy(v5, "I_am_KEY");
result = *a1;
v2 = *a1;
for ( i = 0; i < 16; ++i )
{
for ( j = 0; j < 8; ++j )
{
v2 = __ROR1__(a1[((_BYTE)j + 1) & 7] + byte_140004020[(unsigned __int8)v5[j] ^ v2], 5);
a1[((_BYTE)j + 1) & 7] = v2;
}
result = (unsigned int)(i + 1);
}
return result;
}
sub_1400010A0 함수에서 'I_am_KEY' 라는 key 값을 확인할 수 있다.
key는 'byte_140004020'에서 추출하는 위치를 의미하는 것 같다.
입력 값을 구하기 위한 python 코드는 아래와 같다.
def rol(x, n): # 왼쪽 회전
shiftBit = x << n
shiftBit &= 255
carryBit = x >> 8 - n
return shiftBit | carryBit
def ror(x, n): # 오른쪽 회전
shiftBit = x >> n
carryBit = x << (8 - n)
carryBit &= 255
return shiftBit | carryBit
key = 'I_am_KEY'
enc = '7E 7D 9A 8B 25 2D D5 3D 03 2B 38 98 27 9F 4F BC 2A 79 00 7D C4 2A 4F 58' #7FF628904000
#byte_140004020
tmp = '63 7C 77 7B F2 6B 6F C5 30 01 67 2B FE D7 AB 76 CA 82 C9 7D FA 59 47 F0 AD D4 A2 AF 9C A4 72 C0 B7 FD 93 26 36 3F F7 CC 34 A5 E5 F1 71 D8 31 15 04 C7 23 C3 18 96 05 9A 07 12 80 E2 EB 27 B2 75 09 83 2C 1A 1B 6E 5A A0 52 3B D6 B3 29 E3 2F 84 53 D1 00 ED 20 FC B1 5B 6A CB BE 39 4A 4C 58 CF D0 EF AA FB 43 4D 33 85 45 F9 02 7F 50 3C 9F A8 51 A3 40 8F 92 9D 38 F5 BC B6 DA 21 10 FF F3 D2 CD 0C 13 EC 5F 97 44 17 C4 A7 7E 3D 64 5D 19 73 60 81 4F DC 22 2A 90 88 46 EE B8 14 DE 5E 0B DB E0 32 3A 0A 49 06 24 5C C2 D3 AC 62 91 95 E4 79 E7 C8 37 6D 8D D5 4E A9 6C 56 F4 EA 65 7A AE 08 BA 78 25 2E 1C A6 B4 C6 E8 DD 74 1F 4B BD 8B 8A 70 3E B5 66 48 03 F6 0E 61 35 57 B9 86 C1 1D 9E E1 F8 98 11 69 D9 8E 94 9B 1E 87 E9 CE 55 28 DF 8C A1 89 0D BF E6 42 68 41 99 2D 0F B0 54 BB 16 CF 32 25 34 56 3D FF FF 30 CD DA CB A9 C2 00 00'
enc = enc.split(' ')
tmp = tmp.split(' ')
res = []
chars = []
for i in range(len(enc)): # enc 값을 10진수로 변환
res.append(int(enc[i], 16))
for i in range(len(tmp)): # tmp 값을 10진수로 변환
chars.append(int(tmp[i], 16))
for k in reversed(range(3)):
for i in range(16):
for j in reversed(range(8)):
idx = (j + 1) & 7
res[k * 8 + ((j + 1) & 7)] = (rol(res[k * 8 + ((j + 1) & 7)], 5) - chars[ord(key[j]) ^ res[k * 8 + (j & 7)]]) & 0xFF
# v2 = __ROR1__(a1[((_BYTE)j + 1) & 7] + byte_140004020[(unsigned __int8)v5[j] ^ v2], 5);
# a1[((_BYTE)j + 1) & 7] = v2;
flag = ''.join(chr(i) for i in res)
print(flag)
* 출력 결과
python 코드 실행 시, 출력되는 문자열은 'Reverse__your__brain_;)'이다.

# flag 값: DH{Reverse__your__brain_;)}
'CTF > reversing' 카테고리의 다른 글
| [Dreamhack] Reversing Basic Challenge #8 (1) | 2025.07.25 |
|---|---|
| [Dreamhack] Reversing Basic Challenge #7 (0) | 2025.07.25 |
| [Dreamhack] Reversing Basic Challenge #6 (2) | 2025.07.25 |
| [Dreamhack] Reversing Basic Challenge #5 (2) | 2025.07.25 |
| [Dreamhack] Reversing Basic Challenge #4 (2) | 2025.07.24 |














































































