AutoHotkey1

An AutoHotkey-compiled binary: recovering the DecryptKey and the EXE key, then combining them into the AuthKey.

2026.08.18 Reversing original post

이번 문제 AutoHotkey 는 DecryptKey 및 EXE Key 를 추출하여 최종 AuthKey 를 도출하는 과정을 정리한다. 이 문제의 최종 인증 키(AuthKey)는 다음 수식으로 구성된다.

AuthKey = un_md5(DecryptKey) + " " + un_md5(EXE's Key)

먼저 EXEInfo 를 통해 파일의 타입을 봐주었다.

Figure 1

분석 대상 EXE 는 UPX 로 패킹되어 있었다. 언패킹 이후 실행하면 exe corrupted 문자열이 확인된다.

해당 메시지는 EXE 파일이 실제로 손상되었다는 의미가 아니다. 이는 AutoHotkey 런타임이 내부 스크립트를 (키) 정상적으로 로드 또는 복호화하지 못했을 때 출력하는 오류 메시지다. 그러니 디버거에서 exe corrupted 문자열을 따라가면 근처에서 AUTOHOTKEY SCRIPT 문자열을 확인할 수 있다.

(참고로 exe corrupted 라는 문자열이 나타났기에, 나는 다시 패킹된 상태의 파일에서 분석을 해주었다.)

Figure 2

코드를 자세히 살펴보자. 나는 코드를 분석하며 450C9F 함수에 들어가 분석을 했으며, EXE Key 를 계산·조립한 뒤 이를 문자열 객체 형태로 넘겨주는 함수라는 걸 알아냈다. 즉 함수 반환 직후가 EXE Key 를 확인하기 가장 적절한 지점이라는 걸 알 수 있다.

나는 AUTOHOTKEY SCRIPT 다음에 450C9F 호출 부분에 하드웨어 BP 를 걸어준 후, 도착 후에 Step Into 대신 Step Over(F8) 를 사용하여 함수 호출이 끝난 직후의 레지스터 상태를 확인했다. 그 후 ECX 값이 바뀌는 걸 알 수 있었으며, 이 시점에서 ECX 는 AHK 문자열 객체를 가리킨다는 걸 알았다. ECX 가 가리키는 내부 포인터를 따라가면 ASCII/Unicode 영역에서 MD5 형태의 문자열(EXE Key) 이 확인된다.

EXE Key: 54593f6b9413fc4ff2b4dec2da337806

Figure 3

그 후 DecryptKey 를 알아내기 위해 주변 어셈블리어를 보다, AUTOHOTKEY SCRIPT 분기로 진입하기 직전에 호출되는 마지막 함수인 4508C7 를 보았다. 이 함수를 살펴보면, 이 함수가 AUTOHOTKEY SCRIPT 분기로 갈 수 있는지 여부를 확인하는 함수라는 걸 알 수 있었다. 이는 sub_4508C7 의 리턴값(EAX)에 의해 결정됐고, 이곳이 DecryptKey 를 알 수 있는 부분이라는 걸 알 수 있었다 (왜냐하면 AUTOHOTKEY SCRIPT 로 진입 = 복호화 또는 검증 과정이 성공).

내부를 살펴본 결과, 4508C7 함수는 다음과 같은 역할을 수행한다.

  1. 실행 중인 자기 자신의 EXE 파일 경로를 획득
  2. 내부에 포함된 고정 상수 테이블 2개를 조합
  3. 실행 파일 기반으로 검증용 값(Decrypt 판단용 값)을 계산
  4. 계산 결과를 기준으로 성공 또는 실패를 리턴

즉, 이 함수는 DecryptKey 를 문자열 형태로 보관하는 함수가 아니라, DecryptKey 를 만들어내는 재료와 검증 로직을 포함한 함수이다.

DecryptKey 를 직접 획득하기 위해서는 “버퍼 조립이 끝나는 순간”을 찾아야 한다. 이 문제에서 버퍼 조립 완료 여부는 다음 비교 루프를 통해 확인할 수 있다.

Figure 4

  • 비교 범위: 0 ~ 15 바이트
  • 모든 바이트가 일치해야 루프가 정상 종료됨

이 루프가 깨지지 않고 끝났다는 것은 계산된 버퍼 B 와 기대값 버퍼 A 가 완전히 동일함을 의미하며, 즉 “버퍼 조립 + 키 계산 + 검증” 과정이 모두 완료된 상태이다.

비교 루프 이후 코드를 계속 따라가면 0x00450A7F 에서 EBX 레지스터 창에 키가 뜬다. 이 시점의 아스키코드를 확인하면, 검증이 완료된 상태의 DecryptKey 를 확인할 수 있다.

DecryptKey: 220226394582d7117410e3c021748c2a

그 후 답을 얻기 위해 https://md5.gromweb.com/ 라는 MD5 역산 사이트를 사용했다.

최종 결과: isolated pawn