crackme#11 解析手引き

この解析環境はWindows98 OllyDBG1.07(日本語化)で行っています。

パッチの方法に関しては、人それぞれなので、今回のは一例として見て下さい。


Ollyを立ち上げてcrkme11.exeを開いてください。
それではまず、全てを見てみましょう。
そして怪しい所を探します。


1つ目の怪しい場所は、


004010AA . 55 PUSH EBP
004010AB . 8BEC MOV EBP,ESP
004010AD . 53 PUSH EBX
004010AE . 56 PUSH ESI
004010AF . 57 PUSH EDI
004010B0 . 817D 0C 100100>CMP DWORD PTR SS:[EBP+C],110
004010B7 . 0F85 B2000000 JNZ crkme11.0040116F
004010BD . 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
004010C0 . 6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
004010C2 . 68 5E304000 PUSH crkme11.0040305E ; |Title = "Nag(1/3)"
004010C7 . 68 67304000 PUSH crkme11.00403067 ; |Text = "本ソフトウェアは体験版のようです。このナグを潰して下さい。"
004010CC . FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hOwner
004010CF . E8 58050000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
004010D4 . EB 0C JMP SHORT crkme11.004010E2

Address 004010B0のあたりです。
ウィンドウプロシージャが解る方なら、ルーチンを読むことが出来ます。
cmp [ebp+C], 110 が、msg == WM_INITDIALOG で、違ったら、msg == WM_COMMAND の確認に飛んでます。
msg == WM_INITDIALOGというメッセージはウィンドウズが送ってきます。
110がそういう意味を持っています。
ウィンドウメッセージも、値を覚えておくと良いようです。
winuser.hの中で、 #define WM_INITDIALOG 0x110 と定義されてます。
それが、ウィンドウメッセージの値です。
あんまり詳しく読む必要はないですが、.hファイルを読むといろいろわかります。

 
cmpの下の

004010B7 /0F85 B2000000 jnz crkme11.0040116F

にjnzがあります。
このJNZは、メッセージが WM_INITDIALOG じゃなかったらジャンプです。
ここで、ジャンプしない時に、ナグ(1/3)のMessageBox出力が実行されます。
例として変更する場所は、

004010C0 . 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL

の部分を

004010C0 EB 20 JMP SHORT crkme11.004010E2 ; /

にします。
変更方法は Ctrl + E (右クリック→バイナリ→編集)で、コード編集画面を出します。
HEX +00 の欄を 6A 00 から EB 20 に書き換えます。
そうすると無条件ジャンプで、MessageBox処理を回避します。
ここはNOP埋めでもいけるようですが、NOP埋めをする場合は引数PUSHを考慮しないと
あとのPOPと整合性取れなくなったりしてダメのようですので気をつけましょう。


2つ目の場所は、

00401156 . 6A 00 PUSH 0 ; /lParam = NULL
00401158 . 68 72124000 PUSH crkme11.00401272 ; |DlgProc = crkme11.00401272
0040115D . FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hOwner
00401160 . 6A 02 PUSH 2 ; |pTemplate = 2
00401162 . FF35 00304000 PUSH DWORD PTR DS:[403000] ; |hInst = NULL
00401168 . E8 7D040000 CALL <JMP.&USER32.DialogBoxParamA> ; \DialogBoxParamA
0040116D . EB 7B JMP SHORT crkme11.004011EA
0040116F > 817D 0C 110100>CMP DWORD PTR SS:[EBP+C],111
00401176 . 75 58 JNZ SHORT crkme11.004011D0
00401178 . 66:837D 10 64 CMP WORD PTR SS:[EBP+10],64
0040117D . 75 1D JNZ SHORT crkme11.0040119C

DialogBoxParamAの付近です。
2個めの表示は、↓の部分です。

00401156 . 6A 00 PUSH 0 ; /lParam = NULL

ここは、HEX +00 の欄を 6A 00 から EB 15に書き換えます。
変更方法は上記と同様です。

00401156 EB 15 JMP SHORT crkme11.0040116D ; /

と変更して、DialogBoxParamを回避します。

この場所を見つけるのは、参照文字列からも判断できるそうです。
BPを仕掛ける場合は 、DialogBoxParamAで引っかかります。
引数(call前のpush)とかからも判断できるようです。


3個目のナグは、本体の終了処理です。
Address 0040139E の辺りから下の部分になります。


0040139E |. EB 09 JMP SHORT crkme11.004013A9
004013A0 |. 4E 61 67 28 33>ASCII "Nag(3/3)",0
004013A9 |> 6A 00 PUSH 0 ; /lParam = NULL
004013AB |. FF35 00304000 PUSH DWORD PTR DS:[403000] ; |hInst = NULL
004013B1 |. 6A 00 PUSH 0 ; |hMenu = NULL
004013B3 |. FF75 0C PUSH DWORD PTR SS:[EBP+C] ; |hParent
004013B6 |. FF75 AC PUSH DWORD PTR SS:[EBP-54] ; |Height
004013B9 |. FF75 B0 PUSH DWORD PTR SS:[EBP-50] ; |Width
004013BC |. FF75 A4 PUSH DWORD PTR SS:[EBP-5C] ; |Y
004013BF |. FF75 A8 PUSH DWORD PTR SS:[EBP-58] ; |X
004013C2 |. 68 0408C810 PUSH 10C80804 ; |Style = WS_OVERLAPPED|WS_VISIBLE|WS_SYSMENU|WS_CAPTION|804
004013C7 |. 68 A0134000 PUSH crkme11.004013A0 ; |WindowName = "Nag(3/3)"
004013CC |. 68 A0134000 PUSH crkme11.004013A0 ; |Class = "Nag(3/3)"
004013D1 |. 6A 00 PUSH 0 ; |ExtStyle = 0
004013D3 |. E8 06020000 CALL <JMP.&USER32.CreateWindowExA> ; \CreateWindowExA
004013D8 |. A3 18304000 MOV DWORD PTR DS:[403018],EAX
004013DD |. 6A 01 PUSH 1 ; /ShowState = SW_SHOWNORMAL
004013DF |. FF35 18304000 PUSH DWORD PTR DS:[403018] ; |hWnd = NULL
004013E5 |. E8 6C020000 CALL <JMP.&USER32.ShowWindow> ; \ShowWindow
004013EA |. FF35 18304000 PUSH DWORD PTR DS:[403018] ; /hWnd = NULL
004013F0 |. E8 6D020000 CALL <JMP.&USER32.UpdateWindow> ; \UpdateWindow
004013F5 |> 6A 00 /PUSH 0 ; /MsgFilterMax = 0
004013F7 |. 6A 00 |PUSH 0 ; |MsgFilterMin = 0
004013F9 |. 6A 00 |PUSH 0 ; |hWnd = NULL
004013FB |. 8D45 B4 |LEA EAX,DWORD PTR SS:[EBP-4C] ; |
004013FE |. 50 |PUSH EAX ; |pMsg
004013FF |. E8 04020000 |CALL <JMP.&USER32.GetMessageA> ; \GetMessageA
00401404 |. 83F8 00 |CMP EAX,0
00401407 |. 74 14 |JE SHORT crkme11.0040141D
00401409 |. 8D45 B4 |LEA EAX,DWORD PTR SS:[EBP-4C]
0040140C |. 50 |PUSH EAX ; /pMsg
0040140D |. E8 4A020000 |CALL <JMP.&USER32.TranslateMessage> ; \TranslateMessage
00401412 |. 8D45 B4 |LEA EAX,DWORD PTR SS:[EBP-4C]
00401415 |. 50 |PUSH EAX ; /pMsg
00401416 |. E8 D5010000 |CALL <JMP.&USER32.DispatchMessageA> ; \DispatchMessageA
0040141B |.^EB D8 \JMP SHORT crkme11.004013F5
0040141D |> 8B45 BC MOV EAX,DWORD PTR SS:[EBP-44]
00401420 |. C9 LEAVE
00401421 \. C2 0800 RETN 8

CreateWindowExa以下の処理です。

00401416 |. E8 D5010000 |call <jmp.&USER32.DispatchMessageA> ; \DispatchMessageA

ここで、ナグ表示の終了です。
その後は、leaveとretn 8 となっています。
そこで、

0040139E |. EB 09 JMP SHORT crkme11.004013A9

ここを C9 C2 08 00 に書き換えます。
変更方法は、まず Ctrl + E (右クリック→バイナリ→編集)で、でコード編集の画面を出します。
HEX +00 の欄を C9 C2 に書き換えます。
そうすると、

004013A9 C9 LEAVE ; /
004013AA C2 FF35 RETN 35FF

のように2行になります。
その後この2行を再選択し、もう一度 Ctrl + E (右クリック→バイナリ→編集)でコード編集の画面を出します。
そうするとHEX +00 の欄が C9 C2 FF 35 となっていますので、FF 35 の部分を 08 00 に書き換えます。
「サイズを保つ」のチェックをはずせば続けて書けます。
これで、

004013A9 C9 LEAVE ; /
004013AA C2 0800 RETN 8

と変更されました。
この状態で、「F9」で実行してみてください。
ナグが消えていれば成功です。

今回の解析結果をバイナリーエディタ等で反映させる場合、変更する箇所は次の通りです。

*== TARGET_FILE ================
FILENAME crkme11.exe
* FileSize: 13824 bytes
* LastMod.: 2002/08/09 00:00:00
*===============================
000004C0: 6A EB
000004C1: 00 20
00000556: 6A EB
00000557: 00 15
0000079E: EB C9
0000079F: 09 C2
000007A0: 4E 08
000007A1: 61 00