White Security
abex' crackme 1 분석 본문
가장 유명한 Crackme
abex' crackme 포스팅입니다.
원 출처는 이곳이나
정상적으로 작동하지 않으니
바이너리가 없으신 분들은
첨부한 파일을 사용하시면 되겠습니다.
프로그램을 실행하면
먼저 위와 같은 메시지를 확인하실 수 있습니다.
HD를 CD-ROM으로 생각하게끔 하라고 하네요.
여기서 HD는 HDD를 의미합니다.
창을 종료하면, 두번째 메시지가 나타납니다.
HD가 CD-ROM으로 인식되지 못했다는 의미인데요.
프로그램이 HD를 어떻게 CD-ROM으로
판단하는지 기준을 찾아
문제를 해결하면 되겠습니다.
ollydbg로 바이너리를 열어 확인하면
아주 짧은 어셈블리 소스를 확인할 수 있습니다.
상용 컴파일러 특유의
stub code가 존재하지 않는 것으로 보아
처음부터 어셈블리어로 작성했다는 것을
알 수 있는데요.
덕분에 8KB의 작은 용량을 가집니다
MessageBoxA 함수를 호출하기 전에
PUSH 명령어를 호출하고 있는데요.
PUSH 명령어에 사용된 값은
호출되는 함수의 인자값으로 사용됩니다.
더하여, 0x401024 에서 CMP 명령어로
EAX와 ESI 레지스터의 값이 동일한지 검증한 후
JE 명령어를 통해
0x40103D 주소로 이동하는 것을 확인할 수 있습니다.
만약 동일하지 못하다면
실패 메시지를 출력한 후
0x40103B 에서 JMP 명령어를 통해
즉시 프로그램을 종료합니다.
그럼 EAX와 ESI 레지스터의 값은 어디서 오는 것일까요?
답은 GetDriveTypeA 함수에 있는데요.
WINAPI 의 함수는 EAX 레지스터에 리턴값을 저장합니다.
따라서 EAX 의 값은 바로 직전에 실행되었던
GetDriveTypeA 함수의 리턴값이 되는 것입니다.
GetDriveTypeA 함수의 리턴값입니다.
일반적인 하드디스크라면 DRIVE_FIXED(3)이 되며
CD-ROM이라면 DRIVE_CDROM(5)을 돌려주겠군요.
ESI 값은 프로그램 실행시에
0으로 초기화 된 상태 그대로입니다.
MessageBoxA(NULL, "Make me think your HD is a CD-Rom.", "abex' first crackme", MB_OK|MB_APPLMODAL) $EAX = GetDriveTypeA('C:\\') $ESI++ $EAX-- $ESI++ $ESI++ $EAX-- if ($EAX == $ESI) { MessageBoxA(NULL, "Nah... This is not a CD-ROM Drive!", "Error", MB_OK|MB_APPLMODAL) } else { MessageBoxA(NULL, "Ok, I really think that your HD is a CD-ROM! :p", "YEAH!", MB_OK|MB_APPLMODAL) }
어셈블리를 보고 작성한 의사코드입니다.
특이상황이 아니라면 GetDriveTypeA는3을 반환할 것이고
DEC 명령어를 두번 수행했으니 EAX 값은 1이 되겠군요.
ESI는 초기 0에서 INC 명령어를 세번 수행했으니 3입니다.
따라서 조건식을 만족하지 못하고
에러메시지만 출력한 채로 종료합니다.
저는 CMP 의 인자를 수정해
참이 나오도록 하여 문제를 해결했는데요.
이를 수정하는 방법은 참 많습니다.
쓸모없는 0x40101F 의 코드를 수정하여
EAX의 값을 바꾸어도 좋고
0x401026 을 JMP로 수정하여 무조건으로
성공메시지를 보일 수도 있을 것입니다.
하지만, 최선의 방법은
최소한의 수정으로 프로그램 내부 루틴에
영향을 줄이는 것이겠지요?
'Reversing' 카테고리의 다른 글
Lena's Reversing 10강 분석 (0) | 2019.02.14 |
---|---|
abex' crackme 2 분석 (0) | 2019.02.13 |