crkme04 + 04a
http://doomo.xyz/crack/crkme04.exe
いつも通りGetWindowText関数が呼び出された直後の処理を見ていく。
004011FA . 68 2C304000 PUSH crkme04.0040302C
004011FF . E8 20000000 CALL crkme04.00401224
入力した文字列を引数としてアドレス401224に飛んでいる。
0040122C |> AC /LODS BYTE PTR DS:[ESI]
LODS命令はESIレジスタに格納されているアドレスを参照してEAXレジスタに格納する命令だ。
ここでは「BYTE PTR DS」と指定されているので1バイト(入力文字列の先頭1文字分)だけをEAXにロードしている。
ロードしたEAXの値に対して3つの比較を行い、ループを抜けるかの条件分岐をしている。
ループを抜ける条件は
①EAXが0であること
②EAXが30より小さいこと
③EAXが39より大きいこと
なので入力文字列は0x30~0x39(ASCIIコードで0~9)でなければならない。
EAXが0x30~0x39のとき、以下の処理が行われる。
EAXから0x30引いてEBXと交換する。EAXをx0A倍してそれをEBXと足し合わせる。
...
入力文字列が12345678なら
1 + 0*10
2 + 1*10
3 + 12*10
4 + 123*10
.
.
.
という風な感じになる。ただ入力文字列を10進数とみなして16進数に直してるだけだった。この関数を呼び出した直後に
00401204 . 3D F9602E2C CMP EAX,2C2E60F9
とあり、EAXの値は最終的に0x2C2E60F9でなければならない。
EAXを0x2C2E60F9にしたいならこれを10進数に直した741236985を入力として与えればよい。
crkme04a
00401222 |. E8 21000000 CALL crkme04a.00401248
関数0x401248はcrkme04でやったのと同じで入力した数字を16進数にしてEAXに格納する関数だった。
その後上位16ビットをEAXに、下位16ビットEBXに分けて格納して、EAX×EBXが0x99BA4A95なら正解処理に進む。ただしEAX < EBXでなければならない。
0x99BA4A95は10進数で2579122837。この約数をプログラムで求めると、
2579122837 = 42197 × 61121 であることが分かった。
42197 = 0xA4D5
61121 = 0xEEC1
0xA4D5EEC1 = 2765483713