2017. 8. 20. 01:18ㆍ0x02 Reverse Engineer/0x01. CodeEngn
문제 :
What value must GetDriveTypeA return in order to make the computer recognize the HDD as a CD-Rom ?
바이너리 동적 실행:
|
[그림 1] 바이너리 실행 |
음.. CD-Rom인지에 대해서 생각을 해봐라고 주문하고 있다.
|
[그림 2] 바이너리 실행 |
지금 현재의 상황은 CD-Rom 드라이브가 아닌가보다.
OllyDbg Let's get it!
OllyDbg라는 프로그램으로 바이너리를 개봉해보면 엔트리포인트가 바로 휙 하고 보인다. 메인의 시작 주소는 00401000인것을 우선 파악하고 넘어가자.
아까전에 봤던 메시지 박스 구문이 4개의 매개변수로 묶여 있는 MessageBoxA API함수에 의해 나열이 되어 있다.
그 후, GetDriveTypeA라는 함수의 매개변수가 c:\로 되어 있다.
그 말인 즉슨, 현재는 CD-Rom이 아니라는 것을 확실히 알 수가 있다.
|
[그림 3] 메인 함수의 첫 부분에 두가지의 API함수가 나열되어 있음 |
GetDriveTypeA함수는 MSDN을 참고하지 않으면 감을 잡을 수가 없다.
링크와 함께 자료를 수집해왔다.
|
[그림 4] GetDriveTypeA 함수의 반환 값들... |
funcA는 멀티바이트 함수 또는 변수를 의미합니다.
funcL은 문자열 앞에 L 을 붙이는 이유는 멀티바이트에서 유니코드를 사용하기 위해서 입니다.
funcW는 W는 유니코드 함수 또는 변수를 의미 합니다
https://msdn.microsoft.com/ko-kr/library/windows/desktop/aa364939(v=vs.85).aspx
우선 루틴을 F8(Step Over)로 트레이싱 해본다. GetDriveTypeA 함수가 끝나고 어떠한 반환값이 나타나는지 보기 위해서 이다.
|
[그림 5] GetDriveTypeA 함수에서 반환 받은 값 |
0040101D |. 46 inc esi
0040101E |. 48 dec eax
0040101F |. EB 00 jmp short Reverse_.00401021
00401021 |> 46 inc esi
00401022 |. 46 inc esi
00401023 |. 48 dec eax
00401024 |. 3BC6 cmp eax,esi
00401026 |. 74 15 je short Reverse_.0040103D
현재 eax값은 3, esi는 0이었는데, dec eax를 만나서 2가 될 것이고, inc esi를 만나 1이 되며 jmp 명령어를 만나서 00401021주소로 점프하고, esi +2 시켜서 3이 되고, eax는 1이 되면서 cmp명령어를 만나서 뒤-앞 공식이 적용되게 된다.
현재는 je가 성립하지 않기 때문에 00401026 밑의 주소에 접근하게 된다.
|
[그림 6] cmp에서 je가 만족하지 않는 루틴 |
자 je가 만족하지 않았기 때문에 이 메시지를 뿜어낸다.
|
[그림 7] 정답이 아닌 루틴에 접근했을 시 화면 |
자 그렇다면 이제 고민에 한번 빠져봐야한다. 아까 msdn의 문서를 떠올려보면 반환값 eax레지스터의 값이 5가 되어야 한다. 레지스터를 강제로 조작해보는 방법부터 해보자.
Stage1. 레지스터를 조작하라!
순조롭게 401018주소까진 쭉쭉 트레이싱하자.
00401000 >/$ 6A 00 push 0x0 ; /Style = MB_OK|MB_APPLMODAL
00401002 |. 68 00204000 push Reverse_.00402000 ; |Title = "abex' 1st crackme"
00401007 |. 68 12204000 push Reverse_.00402012 ; |Text = "Make me think your HD is a CD-Rom."
0040100C |. 6A 00 push 0x0 ; |hOwner = NULL
0040100E |. E8 4E000000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
00401013 |. 68 94204000 push Reverse_.00402094 ; /RootPathName = "c:\"
00401018 |. E8 38000000 call <jmp.&KERNEL32.GetDriveTypeA> ; \GetDriveTypeA
아니다.. cmp eax, esi까지 과감하게 트레이싱 하자!
0040101D |. 46 inc esi
0040101E |. 48 dec eax
0040101F |. EB 00 jmp short Reverse_.00401021
00401021 |> 46 inc esi
00401022 |. 46 inc esi
00401023 |. 48 dec eax
00401024 |. 3BC6 cmp eax,esi
그 후에 이쁜 사진을 한 장 가져오겠다.
|
[그림 8] EAX와 ESI를 같게 해버렸다. |
|
[그림 9] 올바른 위치로 점프가 되었다. |
|
[그림 10] 올바른 결과 값 도출 !! |
Stage 2. GetDriveTypeA 함수의 반환 값을 조작해볼까? (정석)
|
[그림 11] 레지스터 값 조작 (feat. GetDriveType의 흐름에 맡겨) |
0040101D |. 46 inc esi
0040101E |. 48 dec eax
0040101F |. EB 00 jmp short Reverse_.00401021
00401021 |> 46 inc esi
00401022 |. 46 inc esi
00401023 |. 48 dec eax
00401024 |. 3BC6 cmp eax,esi
이 루틴을 다시 거치면 eax=3, esi=3 이 되어
00401026 |. /74 15 je short Reverse_.0040103D가 만족된다.
Stage 3. 왠만하면 하지말았으면 하는 je -> jmp 우회
이런 유형에서부터 이렇게 익숙해져버리면 크랙미나 키젠 문제에서 정확한 플래그 값을 찾을 수가 없긴 하지만, 점프를 꼭 우회해야 하는 문제나 실제 프로그램도 있기 때문에 설명한다.
레지스터를 조작하지 않았다면, cmp eax,esi를 만났을 때 eax는 1, esi는 3으로 같지 않다. 그러면, 00401026 |. /74 15 je short Reverse_.0040103D
불 만족하기 때문에
00401028 |. 6A 00 push 0x0 ; /Style = MB_OK|MB_APPLMODAL
0040102A |. 68 35204000 push Reverse_.00402035 ; |Title = "Error"
0040102F |. 68 3B204000 push Reverse_.0040203B ; |Text = "Nah... This is not a CD-ROM Drive!"
00401034 |. 6A 00 push 0x0 ; |hOwner = NULL
00401036 |. E8 26000000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
여기로 갈 수 밖에 없다. 그런데 만약 je를 jmp로 고친다면?
00401026 |. /74 15 jmp short Reverse_.0040103D
00401028 |. |6A 00 push 0x0 ; /Style = MB_OK|MB_APPLMODAL
0040102A |. |68 35204000 push Reverse_.00402035 ; |Title = "Error"
0040102F |. |68 3B204000 push Reverse_.0040203B ; |Text = "Nah... This is not a CD-ROM Drive!"
00401034 |. |6A 00 push 0x0 ; |hOwner = NULL
00401036 |. |E8 26000000 call <jmp.&USER32.MessageBoxA> ; \MessageBoxA
0040103B |. |EB 13 jmp short Reverse_.00401050
0040103D |> \6A 00 push 0x0 ; |/Style = MB_OK|MB_APPLMODAL
0040103F |. 68 5E204000 push Reverse_.0040205E ; ||Title = "YEAH!"
00401044 |. 68 64204000 push Reverse_.00402064 ; ||Text = "Ok, I really think that your HD is a CD-ROM! :p"
00401049 |. 6A 00 push 0x0 ; ||hOwner = NULL
0040104B |. E8 11000000 call <jmp.&USER32.MessageBoxA> ; |\MessageBoxA
레지스터 두개 비교 할 필요 없이 성공을 뜻하는 메시지로 점프하게 된다.
'0x02 Reverse Engineer > 0x01. CodeEngn' 카테고리의 다른 글
[CodeEngn Basic 7] WHAT ABOUT THE CHANGE BY 'CodeEngn' (0) | 2017.08.20 |
---|---|
[CodeEngn Basic 6] You Find OEP (0) | 2017.08.20 |
[CodeEngn Basic 4] Do you know antiDebug? (0) | 2017.08.20 |
[CodeEngn Basic 3] Do you know VB in Function? (0) | 2017.08.20 |
[CodeEngn Basic 2] Do you know recovery to EXE? (0) | 2017.08.20 |