PEview로 볼 수도 있지만, 복사 및 붙여넣기가 안된다는 치명적인 단점이 있어, IAT 정보를 추출하는 코드를 직접 짰다.
그 결과는 다음과 같다. 역시 이번에도 GetDlgItemTextA 함수를 이용하고 있다.

GetDlgItemTextA 함수를 이용해 입력값을 가져와 0x401090 함수의 parameter로 사용하는데, 호출 후 함수의 반환값과 0xB79E763E와 비교한다.

암호화 루틴에 주석을 달았다. shift 연산이 있으므로 역으로 연산하는 것은 불가능해 보이므로, 조건부 Brute Forcing을 사용하자.
Sleep과 GetTickCount을 이용해 암호화 처리 시간을 계산하고, 반복 루틴 이후에 이 시간에 제한을 둔다.
아래 이미지의 주석에 의하면, return 0이 되도록 하려면 반복 루틴 처리 시간은 0x15e(350 ms) 이상 0x2ee (750 ms) 이하가 되어야 한다.

글자 수로 제어할 수 있을 것 같아서 aaaaaaa로 7글자 입력 시 처리 시간을 측정했는데, 1156 ms가 나왔다.

aaa를 입력값으로 줬을 때, 암호화 시간이다. 100ms가 나온다.
이런 식으로 최대 및 최소 글자 수를 알아보고 코드를 짜는 데 반영하면 된다.

통으로 Brute Forcing을 돌리기엔 시간과 메모리가 많이 소모되므로, 특정 조건이 아니면 버리도록 구현했다.
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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | # -*- coding: utf-8 -*- import sys import os import string import time if sys.platform == 'win32': os.system("cls") else: os.system("clear") case = string.letters + string.digits def encrypt(string): edi = 0x5eed for c in string: eax = edi << 5 edx = ord(c) eax ^= edx edi = eax ^ 0x1d0b1eed return hex(edi).replace('0x', '').replace('L', '')[-8:] candidates = list() target = "b79e763e" print "\n\n [*] After 3 seconds, Brute forcing starts......\n\n" time.sleep(3) # Brute forcing for first byte for idx1 in case: for idx2 in case: if target[:2] == encrypt(idx1 + idx2 + "____")[:2]: print " [*] Found first byte: %s (%s)" % (idx1 + idx2, encrypt(idx1 + idx2 + "____")[-8:]) # Brute forcing for second byte for idx3 in case: if target[2:4] == encrypt(idx1 + idx2 + idx3 + "___")[2:4]: print " [*] Found first byte: %s (%s)" % (idx1 + idx2 + idx3, encrypt(idx1 + idx2 + idx3 + "___")[-8:]) # Brute forcing for third byte for idx4 in case: for idx5 in case: if target[4:6] == encrypt(idx1 + idx2 + idx3 + idx4 + idx5 + "_")[4:6]: print " [*] Found first byte: %s (%s)" % (idx1 + idx2 + idx3 + idx4 + idx5, encrypt(idx1 + idx2 + idx3 + idx4 + idx5 + "_")[-8:]) # Brute forcing for forth byte for idx6 in case: if target[6:] == encrypt(idx1 + idx2 + idx3 + idx4 + idx5 + idx6)[6:8]: print " [*] Found first byte: %s (%s)" % (idx1 + idx2 + idx3 + idx4 + idx5 + idx6, encrypt(idx1 + idx2 + idx3 + idx4 + idx5 + idx6)[-8:]) # Finally apeend candidates in list if target == encrypt(idx1 + idx2 + idx3 + idx4 + idx5 + idx6)[-8:]: candidates.append(idx1 + idx2 + idx3 + idx4 + idx5 + idx6) print "\n\n [*] After 5 seconds, clear this screen and the candidates for answer'll be printed......" time.sleep(5) if sys.platform == 'win32': os.system("cls") else: os.system("clear") # print all candidates print "\n [*] Found candidates for answer: %s\n\n" % ', '.join(candidates) | |
실행 시 for문 내부에 걸어둔, 부분적으로 조건에 맞는 후보들이 먼저 출력된다.

이 과정이 끝나면 5초 후 최종 필터링 결과가 나타나도록 작성했다.

최종적으로, 아래처럼 최종 암호화 결과가 비교값과 같은 것만 필터링해서 답 후보를 출력해준다. 영단어 같이 생긴 단어가 답이다.
