패킹 여부를 확인해보자. 언팩 과정은 무시해도 되겠다.
우선 실행해보자. Check it! 버튼을 누르면 더 입력하라고 한다. 분명 2글자라고 했는데 말이다.
Name의 길이가 3 이상이어야 이 분기문을 통과할 수 있는데
답은 2글자라고 했으므로 패치해준다. 편의를 위해 수정 사항을 따로 바이너리로 저장하자.
45BB9B의 함수 호출 결과, LOCAL.5라는 지역변수에 Serial 같은 것이 생성되었다.
이 정도 길이라면 상당한 코드량이 예상되므로, 첫 번째 Serial만을 중점적으로 보자.
위의 함수 내부로 들어와서 처음 만나는 반복문을 통과하면 ESI와 EDX가 0x656A2F00으로 설정되는데,
상위 2바이트가 첫 번째 Serial과 같은 것을 알 수 있다.
실제 45B9D0에서 호출한 함수로 상위 2바이트만 추출한 것을 알 수 있다. (함수명은 IDA의 도움을 받았다.)
이것으로 첫 번째 반복문에서 Serial의 첫 부분을 생성하는 것을 알 수 있다.
pseudo code로 주석을 달아본다면 다음과 같을 것이다.
분석한 결과를 토대로, Brute Force를 시행한다. 알고리즘은 다음과 같다.
1. 0-9, A-Z, a-z 문자 총 62개로 2자리 name 후보(00 ~ zz)를 생성
2. 한 글자씩 위의 알고리즘을 돌려 그 hex 값을 구한다.
3. long 타입 정수가 되는데, 필요한 부분([-9:-5])만 추출하여 출력한다.
4. 그 결과가 "5D88"과 같으면 끝낸다.
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 |
import os, string, hashlib, time
def showTitle():
title = '######################################################\n'
title += '# #\n'
title += '# .dP"Y8 88 888888 88 88 88 db 88""Yb #\n'
title += '# `Ybo." 88 88 88 88 88 dPYb 88__dP #\n'
title += '# o.`Y8b 88 88 888888 88 .o dP__Yb 88""Yb #\n'
title += '# 8bodP\' 88 88 88 88 88ood8 dP""""Yb 88oodP #\n'
title += '# #\n'
title += '# CodeEngn Advance 08 #\n'
title += '# keygen #\n'
title += '# #\n'
title += '######################################################'
print title
def bruteforceFirstSerial():
names = []
charCandidate = list(string.digits) + list(string.ascii_uppercase) + list(string.ascii_lowercase)
print "\n[*] Starting Brute Force"
# generate name candidates
for i in charCandidate:
for j in charCandidate:
names.append(i + j)
for name in names: # in 62*62 cases
esi = edx = 0
for c in name:
esi = (ord(c) + edx) * 0x772
esi += esi ** 2
esi *= 0x474 * 2
edx = esi
firstSerial = hex(esi).upper()[-9:-5]
if firstSerial == "5D88":
print "\n [!] Found NAME: %s\n\n[*] Finish Brute Force" % name
print "\n[*] Auth Key: md5(\"%s\") = %s" % (name, hashlib.md5(name).hexdigest().upper())
return
else:
print " [+] Analyzing Name [%s] - generated 1st serial text [%s]" % (name, firstSerial)
def main():
os.system("cls")
showTitle()
time.sleep(2)
bruteforceFirstSerial()
if __name__ == '__main__':
main() |
cs |
Title을 보여주고 ^___^
답이 나왔지만, 여태 그랬듯이 유추 가능한 부분과 함께 모두 가렸다.
Clear!
'[Wargame Write-up] > CodeEngn Challenges' 카테고리의 다른 글
[CodeEngn Challenges] Advance RCE 09 (0) | 2016.10.05 |
---|---|
[CodeEngn Challenges] Malware Analysis 02 (0) | 2016.10.05 |
[CodeEngn Challenges] Advance RCE 07 (0) | 2016.10.04 |
[CodeEngn Challenges] Malware Analysis 01 (0) | 2016.10.04 |
[CodeEngn Challenges] Advance RCE 06 (0) | 2016.10.03 |