실행해도 빈 창만 뜬다. 그래서 우선 문제의 crackme3.key라는 key file을 만들고, 미리 CMP문에 breakpoint을 걸어 저 예시로 한번 디버깅해보았다.
저 CMP에서 문자열 개수가 12h(18)인지 검사한다. 그래서 일단 필요한 부분에 주석을 달아보았다.
이후, 길이 조건에 충족하도록 입력한 후 401311에서 어떠한 과정을 거치는지 알아보았다. 대충 주석을 달아보았다.
이를 바탕으로 python 코드를 작성해보았다. 알고리즘을 보자면, 입력한 문자열의 [0]~[13]번까지 14 문자를 0x41, 0x42, …, 0x4E로 각각 XOR 연산하여 각 자리 값을 치환, 각각의 연산 결과를 모두 더해 0x4020F9 주소에 넣는다. 아래는 0x12345678과의 XOR까지 진행한 결과이다. 같은 걸 볼 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 |
def encrypt(string):
if len(str(string)) != 18:
return
BL = 0x41
sum = 0
result = ""
for i in range(len(string)):
result += chr(ord(string[i]) ^ BL)
BL += 1
sum += ord(result[i])
if BL == 0x4F:
result += string[i+1:]
break
XORedSum = sum ^ 0x12345678
print "result: %s\nresult in hex: 0x%s\n*(4020F9) = %d\n*(4020F9) ^ 0x12345678 = %d\n*(402149) = %d\n" \
% (result, result.encode('hex'), sum, XORedSum, i)
return (i, hex(int(str(XORedSum), 0)))
def ToLittleEndian(XORedSum):
XORedSum = XORedSum[2:]
result = ""
for i in range(6, -1, -2):
result += XORedSum[i:i+2]
return ("0x" + result.capitalize()) |
cs |
문자열 암호화 이후에는 0x4020F9 주소에 있는 값과 0x12345678을 XOR 취하고 40133C 함수를 호출한다.
40133C에서는 암호화하고 남은 문자열(입력값의 15~18번째 글자들)을 거꾸로 뒤집는다. (“ABCD” -> “DCBA”)
EAX 값(40133C 함수 결과)과 1~14번째 문자를 암호화한 값을 비교한다. 값이 상당히 다르므로, EAX 값에 저 값이 들어가도록 수정해야 한다. 0x123450E9를 little endian 방식으로, 0xE9503412로 넣을 것이다. 0xE9나 0x12의 글자는 키보드로 입력할 수 없으니 Hex Editor를 이용했다.
이대로 진행하면 다음과 같은 결과가 나온다. 크랙에는 성공했으나 문자열이 원하는 결과가 아니다. 이 문자열의 출처는 바로 암호화한 뒤의 문자열 + “!”이다.
문제에서는 저 부분이 “CodeEngn”임을 원하고 있다. 따라서 아까 만든 Python 코드를 이용하면 된다. 각 문자에 대한 암호화는 XOR만을 이용하기 때문에, 이 함수로 복호화해도 무관하다. 여기에서, 답이 여러 개 나올 수 있다는 문장을 이해할 수 있다. Key 파일에 들어가는 내용으로 [(CodeEngn을 복호화한 값 8자) + 임의의 6자 + (앞의 14자를 암호화한 4자리)] 형태로 들어가기 때문이다.
다시 Hex Editor를 열어, “result in hex”값을 그대로 입력하고 실행해, 끝에서 8글자를 파악한다. 키보드로 입력할 수 없는 글자가 있어, Python 콘솔에선 확인할 수 없다.
0x12345239이어야 하므로, little endian 방식으로 수정해준다.
수정 후, 실행하면, 목표하던 답보다 좀더 긴 문자열로 표시된다. “CodeEngn”만으로 끝내기 위해서는 9번째 글자를 NULL 문자(\x00)로 치환해줘야 한다. 9번째 글자는 암호화 함수에서 0x49와 XOR하므로 Hex Editor로 9번째 글자를 49로 바꿔주면 될 것이다. 중간의 한 문자가 바뀌기 때문에 10, 11번 과정을 다시 해줘야 한다.
완벽히 크랙에 성공한 모습이다.
Auth Key: 0x022D272100282026497F7F7A79797B553412
정리하자면, 이 프로그램의 알고리즘은:
1. crackme3.key 파일 탐색 (없으면 종료)
2. 해당 파일 속 문자열 길이가 18인지 확인 (아니면 종료)
3. 14번째 글자까지 본문의 4번 과정으로 암호화
4. 남은 4글자는 역방향으로 EAX 레지스터에 넣어두고, 3번의 결과값과 같은지 비교 (다르면 종료)
5. 성공한 결과, 창 중앙에 “Cracked by: (3번의 결과 문자열)” 식으로 출력
'[Wargame Write-up] > CodeEngn Challenges' 카테고리의 다른 글
[CodeEngn Challenges] Advance RCE 02 (0) | 2016.09.14 |
---|---|
[CodeEngn Challenges] Advance RCE 01 (0) | 2016.09.14 |
[CodeEngn Challenges] Basic RCE 19 (0) | 2016.08.30 |
[CodeEngn Challenges] Basic RCE 18 (0) | 2016.08.30 |
[CodeEngn Challenges] Basic RCE 17 (데이터 주의...) (0) | 2016.08.30 |