crackme#07 解析手引き

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

OllyDBGを、起動して「crkme07.exe」を読込んでください。
「検索」→「ラベル一覧」(「Search for」→「Name(Label)」)で、ラベル一覧の一覧を、表示します。


Names in crkme07
Address Section Type ( Name Comment
00401000 .text Export <ModuleEntryPoint>
00402000 .rdata Import ( KERNEL32.GetModuleHandleA
00402004 .rdata Import ( KERNEL32.ExitProcess
0040200C .rdata Import ( USER32.GetDlgItemInt
00402010 .rdata Import ( USER32.GetWindowTextA
00402014 .rdata Import ( USER32.LoadIconA
00402018 .rdata Import ( USER32.GetDlgItem
0040201C .rdata Import ( USER32.DialogBoxParamA
00402020 .rdata Import ( USER32.EndDialog
00402024 .rdata Import ( USER32.SetWindowLongA
00402028 .rdata Import ( USER32.SetWindowTextA
0040202C .rdata Import ( USER32.ShowWindow
00402030 .rdata Import ( USER32.CallWindowProcA
00402034 .rdata Import ( USER32.MessageBoxA
00402038 .rdata Import ( USER32.SendMessageA


GetWindowTextAにブレークポイントを仕掛けて適当にパスを打ち込んでから
登録ボタンを押します。

0040104Bに行きましたが、結論からいいますとGetWindowTextAはパスチェックとは関係ありません。
今回文字列取得に使っているのはGetDlgItemIntです。
GetWindowTextAはテキストボックス入力フィルタとして使われてます。


それではGetDlgItemIntにブレークポイントを仕掛けなおして
もう一度登録ボタンを押して下さい。
GetDlgItemIntを抜けると戻り値(eaxレジスタに入る)として、
入力した文字列を数値に変換したものが返ります。


004012B5 . 6A 7E PUSH 7E ; /IsSigned = TRUE
004012B7 . 68 48304000 PUSH CRKME07.00403048 ; |pSuccess = CRKME07.00403048
004012BC . 52 PUSH EDX ; |ControlID
004012BD . FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
004012C0 . E8 19010000 CALL <JMP.&USER32.GetDlgItemInt> ; \GetDlgItemInt   ←ココ
004012C5 . 66:8903 MOV WORD PTR DS:[EBX],AX
004012C8 . 5B POP EBX
004012C9 . 5A POP EDX
004012CA . 59 POP ECX
004012CB . 43 INC EBX
004012CC . 43 INC EBX
004012CD . 41 INC ECX
004012CE . 42 INC EDX
004012CF . 83F9 04 CMP ECX,4
004012D2 .^7C DE JL SHORT CRKME07.004012B2
004012D4 . 8B35 1D314000 MOV ESI,DWORD PTR DS:[40311D]
004012DA . B8 67666666 MOV EAX,66666667
004012DF . 81E6 FFFF0000 AND ESI,0FFFF
004012E5 . F7EE IMUL ESI
004012E7 . C1FA 02 SAR EDX,2
004012EA . 8BCA MOV ECX,EDX
004012EC . C1E9 1F SHR ECX,1F
004012EF . 03D1 ADD EDX,ECX
004012F1 . 81FA E7030000 CMP EDX,3E7
004012F7 . 0F85 C1000000 JNZ CRKME07.004013BE


004012C0に行きました。
今回は処理がややこしいので全体をざっとトレースしていきます。
全部のCALLに引っ掛けたとしたら、「F8」2回で4013DEに進み、4012C5に出ます。

GetDlgItemIntに引っかかったらF8を連打して流れを見ていきましょう。
ループして同じGetDlgItemIntを計4回呼び出しています。


004012F1 . 81FA E7030000 CMP EDX,3E7
004012F7 . 0F85 C1000000 JNZ CRKME07.004013BE
004012FD . 8B2D 23314000 MOV EBP,DWORD PTR DS:[403123]
00401303 . B8 0F270000 MOV EAX,270F
00401308 . 66:3905 1F3140>CMP WORD PTR DS:[40311F],AX
0040130F . 66:C705 233140>MOV WORD PTR DS:[403123],0
00401318 . 0F87 A0000000 JA CRKME07.004013BE
0040131E . 66:3905 213140>CMP WORD PTR DS:[403121],AX
00401325 . 0F87 93000000 JA CRKME07.004013BE
0040132B . 8B0D 21314000 MOV ECX,DWORD PTR DS:[403121]
00401331 . B8 1F85EB51 MOV EAX,51EB851F
00401336 . 81E1 FFFF0000 AND ECX,0FFFF
0040133C . 8B3D 1F314000 MOV EDI,DWORD PTR DS:[40311F]
00401342 . F7E9 IMUL ECX


次はループを抜けると、004012F1にcmp、比較命令が見えます。
そこまで進めてみましょう。

004012F1 . 81FA E7030000 CMP EDX,3E7

edxの中身はなんでしょう。フェイクパスとして9988-7766-5544-3322と入れた場合、
edx=3E6となっているはずです。
画面右のedxレジスタの3E6をクリックすると10進表示できます。
値は998です。

つまり、最初のボックスの先頭3文字分が取り出されたことになります。
cmp edx,3E7 で次のジャンプ命令でジャンプしなければチェック続行。
即ち、edx=3E7(=999)になればよいわけです。
パスの最初3文字は999で確定です。

ここのジャンプ命令でジャンプしてはまずいので、レジスタのゼロフラグをいじって
ジャンプしないようにしてあげましょう。Z=1です。

若しくはEDXの値を変更します。
変更はゼロフラグの場所をダブルクリックで出来ます。

それでは全てを確認しては大変な労力を要するので、比較命令のみに注目してみます。

00401308 に cmp word ptr[40311F], ax があります。
逆アセリストの下に、ax=270F ds:[0040311F]=1E56 と表示されるはずです。
270Fは9999, 1E56は7766、すなわち9999とボックス2番目の値7766とを比較しています。
mov命令を挟んで、分岐です。普通ジャンプしないはずです。
なぜならば、4桁までしか入力できないからです。
ja ということは、 入力ボックス2番目の値 > 9999 ならジャンプします。


再び比較・分岐処理です。

0040131E . 66:3905 213140>CMP WORD PTR DS:[403121],AX

ax=270F(9999) , ds:[00403121]=15A8(5544)と表示されます。
次は入力ボックス3番目の値について調べています。
これも上記と同じです。

分岐を抜けて、0040132B からは入力パスから値を生成しています。
第2、第3ボックスの値で、第4ボックスに入れるべき値が決まります。
キー生成ではテーブル引きを行ったり、乗算したり除算したりしてます。

今回は入力パスから値を設定している箇所(0040132B~004013B3)は私には解説できません。
トレースしながら追っていきましょう。

それでは、比較命令が出るまでF8連打です。
押しっぱなしでもOKです。

004013B0 . 66:3BE8 CMP BP,AX
004013B3 . BE 10314000 MOV ESI,CRKME07.00403110 ; ASCII "未登録"E07
004013B8 .^0F84 3AFDFFFF JE CRKME07.004010F8
004013BE > 5D POP EBP
004013BF . 5F POP EDI
004013C0 .^E9 2CFDFFFF JMP CRKME07.004010F1
004013C5 CC INT3


004013B0に cmp bp, ax がありました。
それでは各値を参照しましょう。ax=1606(5638) bp=0CFA(3322)

bpに見える値は、ボックス4番目に入力した値のようです。
それを比較して、正しければOKなはずです。
ここでの分岐は無理矢理曲げないで下さい。

これで正解は出ました。先頭3文字は999で固定。
最後の4文字は0x1606=5638です。

最初に入力したフェイクパスを変更します。
9988-7766-5544-3322 → 9998-7766-5544-5638 に変えて、登録ボタンを押して下さい。
登録済と表示されるはずです。

1122-3344-5566-7788 → 9992-3344-5566-5638でも出来ました。