Abex Crack-Me 1번문제.
Abex Crack-Me 1번문제는 Immunity Debugger를 사용하여 풀었습니다.
우선 위의 apexcrackme를 다운받고 실행해봅시다.
'나를 CD-ROM으로 생각하게 만들어라'
그리고 확인을 누르게되면,
'아냐... 이것은 CD-ROM 드라이브가 아니다!'
아마도 CD-ROM인지 아닌지에 따라 각각 성공했을 때와 실패했을때의 메세지 박스가 뜰것이며, 이것을 우회하여 성공 메세지 박스를 띄우게 만들어야 하는 문제 같습니다. 그럼 이제 디버거를 실행하여 파일을 열어봅시다.
디버거를 실행하면, 주소 창, 옵코드 창, 디스어셈블리 창, 레지스터 창, 스택 창, 메모리 덤프창 등이 보이죠.
우선 F8(Step over)키를 이용해서 한줄 한줄 실행해보도록 하겠습니다.
(F7(Step info)키와 차이점은 함수 내부로 진입하느냐 마느냐에 있습니다.)
실행하자마자, 바로 우리가 방금 보았던 내용들이 보입니다.
00401007 |. 68 12204000 PUSH abexcrac.00402012 ; |Text = "Make me think your HD is a CD-Rom."
0040102F |. 68 3B204000 PUSH abexcrac.0040203B ; |Text = "Nah... This is not a CD-ROM Drive!"
EAX 레지스터에 담겨있는 값이 3이네요.
0040101D |. 46 INC ESI
0040101E |. 48 DEC EAX
0040101F |. EB 00 JMP SHORT abexcrac.00401021
00401021 |> 46 INC ESI
00401022 |. 46 INC ESI
00401023 |. 48 DEC EAX
00401024 |. 3BC6 CMP EAX,ESI
여기서 INC(인크리먼트, increment)는 1을 증가시키는 역할을 합니다. 그리고 DEC(디크리먼트, decrement)는 1을 감소시키는 역할을 하구요. 즉 ESI를 증가시키고 EAX를 감소 시킨뒤에, ESI를 두번 증가시키고 EAX를 한번 감소시킵니다. 그리고 CMP는 비교 연산으로 두 개의 오퍼랜드를 가지며 비교 결과는 프로세스의 플래그에 기록합니다.
CMP 명령은 - 연산으로 비교를 하며, 같을 경우엔 CF(캐리 플래그, Carry Flag)는 0이 되며 제로 플래그(ZF, Zero Flag) 값이 1으로 설정됩니다. 다를 경우에는 제로 플래그가 0으로 설정되죠.
0040101D |. 46 INC ESI ; ESI = 1, EAX = 3
0040101E |. 48 DEC EAX ; ESI = 1, EAX = 2
0040101F |. EB 00 JMP SHORT abexcrac.00401021
00401021 |> 46 INC ESI ; ESI = 2, EAX = 2
00401022 |. 46 INC ESI ; ESI = 3, EAX = 2
00401023 |. 48 DEC EAX ; ESI = 3, EAX = 1
00401024 |. 3BC6 CMP EAX,ESI ; ESI > EAX, ZF = 0
그 아래부분도 봅시다.
00401026 |. 74 15 JE SHORT abexcrac.0040103D
00401028 |. 6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
0040102A |. 68 35204000 PUSH abexcrac.00402035 ; |Title = "Error"
0040102F |. 68 3B204000 PUSH abexcrac.0040203B ; |Text = "Nah... This is not a CD-ROM Drive!"
00401034 |. 6A 00 PUSH 0 ; |hOwner = NULL
00401036 |. E8 26000000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
0040103B |. EB 13 JMP SHORT abexcrac.00401050
0040103D |> 6A 00 PUSH 0 ; |/Style = MB_OK|MB_APPLMODAL
0040103F |. 68 5E204000 PUSH abexcrac.0040205E ; ||Title = "YEAH!"
00401044 |. 68 64204000 PUSH abexcrac.00402064 ; ||Text = "Ok, I really think that your HD is a CD-ROM! :p"
00401049 |. 6A 00 PUSH 0 ; ||hOwner = NULL
0040104B |. E8 11000000 CALL <JMP.&USER32.MessageBoxA> ; |\MessageBoxA
00401050 \> E8 06000000 CALL <JMP.&KERNEL32.ExitProcess> ; \ExitProcess
00401055 $-FF25 50304000 JMP DWORD PTR DS:[<&KERNEL32.GetDriveTyp>; kernel32.GetDriveTypeA
0040105B .-FF25 54304000 JMP DWORD PTR DS:[<&KERNEL32.ExitProcess>; kernel32.ExitProcess
401026 부분의 JE 라는 명령어는 제로 플래그가 1일때 점프합니다. 즉 같을 경우에는 40103D로 넘어가겠다는 말입니다. 만약에 같지 않을 경우에는 어떻게 될까요? PUSH 명령으로 스택에 데이터를 넣고, 메세지 박스가 나온 뒤에 401050으로 점프하여 ExitProcess API를 만나 프로그램이 종료됩니다. 만약 40103D로 점프를 시켜준다면 강제로 메세지 박스를 띄울수 있겠죠. 즉, JE 부분에 JMP 명령을 넣어 40103D로 점프하면 끝납니다.
그렇지만 문제에서 의도한 것은 아니므로, 다시 위로 돌아갑니다. 40101D에 브레이크 포인트를 걸어줍니다. 그리고 리턴값이 담긴 EAX 레지스터의 값을 바꿉니다. 5로 바꿔주면 ESI 레지스터의 값과 일치하겠죠.
OK를 누른 후 F8을 눌러 계속 진행하게 되면, 값이 서로 일치해서 맞아 떨어지므로 40103D로 점프됩니다.
그리고, CD-ROM 인식에 성공했다는 메세지와 함께 문제는 끝이납니다.
'정리 > Reverse Engineering' 카테고리의 다른 글
리버스 엔지니어링 스터디 3편. 인라인 코드 패치(Inline Code Patch) (8) | 2014.05.11 |
---|---|
리버스 엔지니어링 스터디 2편. 스택 프레임(Stack Frame) (4) | 2014.05.05 |
Babylon Keygenme(바빌론 키젠미)를 크랙해보자. (3) | 2014.03.03 |
리버스 엔지니어링 스터디 1편. PE(Portable Executable) 구조 (21) | 2013.08.11 |