티스토리 뷰

이 블로그는 제가 공부한 것을 바탕으로 정리 목적으로 사용되고 있습니다.

작성 내용중 부족한 부분이나 잘못된 부분을 지적해주시면 감사하겠습니다 (꾸벅)



crackme라는 프로그램은 크랙 연습 목적으로 작성되어 공개된 프로그램이다. crackme를 분석해보면 실제로 디스커버리와

디스어셈 코드에 익숙해지는 효과가 있다고 한다. 이 프로그램은 아주 유명하기 때문에 해외에는 물론 국내에도 abex’crackme를

설명한 사이트가 많다고 한다.

이제 OllyDbg로 프로그램을 실행시키기 전에 abex’crackme 파일을 실행시켜보자.





프로그램을 실행시키면 위와 같은 메세지 박스가 나오는데, 의미로 HD를 CD-Rom으로 인식시켜라. 라고 한다. 무슨 의미인지..

한번 확인을 눌러 보자.

 



새로운 메세지 박스가 떴는데, CD-Rom이 아니라란다. 어떻게 해결해야 하는지… 이제 코드를 직접 보면서 해결하도록 하겠다.

OllyDbg로 실행시키면 아래와 같은 화면이 나온다.

코드가 매우 짧다. 코드를 한번 살펴보겠다. 

MessageBoxA는 Make me think your HD is a CD-ROM을 출력한다. 그리고 GetDriveTypeA이란 함수가 있다. 이 함수에 대해 자세히 알아보자.
GetDrvieType 함수는 RootPathName이 가리키는 드라이브가 어떤 종류의 드라이브인지 알려주는 함수이다. 그리고 GetDriveType의 Return 값을 확인해보자.

 상수  값 설명
 DRIVE_UNKNOWN  0  알 수 없음
 DRIVE_NO_ROOT_DIR  1  최상위 경로가 없음
 DRIVE_REMOVABLE  2  이동형 저장장치
 DRIVE_FIXED  3  고정형 저장장치
 DRIVE_REMOTE  4  네트워크 Drive
 DRIVE_COROM  5  DVD/CD-ROM 휴형
 DRIVE_RAMDISK  6  Ram Disk

즉 여기서는 RootPathName이 가리키는 드라이브 C드라이브의 타입을 반환한다. 여기서는 HDD를 반환된다. 




이 RootPathName을 조작하여 CD-ROM 타입으로 인식하도록 만들어 우리가 원하는 메세지를 출력하면 된다.
이번에는 라인을 상세하게 분석하도록 하겠다.

00401000  >/$  6A 00                PUSH 0                                             ; /Style = MB_OK|MB_APPLMODAL
00401002  |.  68 00204000        PUSH abexcm1-.00402000              ; |Title = "abex' 1st crackme"
00401007  |.  68 12204000        PUSH abexcm1-.00402012              ; |Text = "Make me think your HD is a CD-Rom."
0040100C |.  6A 00                    PUSH 0                                             ; |hOwner = NULL
0040100E  |.  E8 4E000000       CALL <JMP.&USER32.MessageBoxA>      ; \MessageBoxA
                                                                                                                       ; 함수 내부에서 ESI값이 FFFFFFFF로 세팅 (아래의 사진 참고)

00401013  |.  68 94204000        PUSH abexcm1-.00402094              ; /RootPathName = "c:\"
00401018  |.  E8 38000000       CALL <JMP.&KERNEL32.GetDriveTypeA>  ; \GetDriveTypeA 리턴값인 EAX은 3(DRIVE_FIXED)로 된다.
                                                                                                                              
0040101D  |.  46                        INC ESI                                             ; ESI = 0 (왜 0으로 변하나??? FFFFFFFF에 INC는 값을 1을 증가시키므로 계산기(프로그래머용)로 이용하면 0이 나온다.)
0040101E  |.  48                        DEC EAX                                           ; EAX = 2
0040101F  |.  EB 00                  JMP SHORT abexcm1-.00401021    ; 의미 없는 명령어 - 존재하는 이유는 디버깅을 방해하고 리버서를 혼란시키기 위해 일부러 추가한것
00401021  |>  46                       INC ESI                                              ; ESI = 1
00401022  |.  46                        INC ESI                                              ; ESI = 2
00401023  |.  48                        DEC EAX                                            ; EAX = 1

조건 분기 401028 또는 40103D
00401024  |.  3BC6                   CMP EAX,ESI                                   ; EAX(1)와 ESI(2)를 비교
00401026  |.  74 15                   JE SHORT abexcm1-.0040103D     ; JE(Jump if Equal) 명령 즉 두값이 같으면 40103D로 점프,
                                                                                                             두 값이 서로 다르면 401028로 점프한다. 

실패 메세지
00401028  |.  6A 00                  PUSH 0                                             ; /Style = MB_OK|MB_APPLMODAL
0040102A  |.  68 35204000      PUSH abexcm1-.00402035              ; |Title = "Error"
0040102F  |.  68 3B204000      PUSH abexcm1-.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 abexcm1-.00401050

성공 메세지
0040103D  |>  6A 00                PUSH 0                                             ; |/Style = MB_OK|MB_APPLMODAL
0040103F  |.  68 5E204000      PUSH abexcm1-.0040205E             ; ||Title = "YEAH!"
00401044  |.  68 64204000      PUSH abexcm1-.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



이제 코드를 패치해서 크랙하도록 하겠다. 여기서 "패치시킨다”는 기존의 코드를 의도적으로 다른 코드로 덮어 쓰는 행위를 말한다.

단순 패치가 목적이면 401026 주소 명령어 JE SHORT abexcm1-.0040103D를 ‘Assemble’ 기능[Space]을 이용하여 JMP 0040103D로 변경하면 된다.



<출처 : 리버싱 핵심원리 ; 저자 : 이승원>




'Reversing > Reverse Engineering' 카테고리의 다른 글

Huffman Algorithm에 대해서  (0) 2016.04.23
PE File Format에 대해서  (0) 2015.12.29
OllyDbg를 이용한 스택 공부하기  (0) 2015.12.23
PACKING  (0) 2015.12.21
함수의 호출 규약  (0) 2015.12.21
댓글