lea eax,dword ptr ss:[esp+40]
add eax,B
mov dword ptr ss:[esp+8],9
mov dword ptr ss:[esp+4],eax
lea eax,dword ptr ss:[esp+20]
mov dword ptr ss:[esp],eax
call <JMP.&strncpy>
[esp+4]=入力した文字列の11文字目以降
[esp]=[esp+20]
[esp+8]=9
入力した文字列から9文字[esp+20]にコピー。
004016EE | mov dword ptr ss:[esp+7C],1
004016F6 | mov dword ptr ss:[esp+78],0
004016FE | jmp keygen.401725
00401700 | lea edx,dword ptr ss:[esp+20]
00401704 | mov eax,dword ptr ss:[esp+78]
00401708 | add eax,edx
0040170A | movzx eax,byte ptr ds:[eax]
0040170D | movsx eax,al
00401710 | sub eax,30
00401713 | cmp eax,9
00401716 | jbe keygen.401720
00401718 | mov dword ptr ss:[esp+7C],0
00401720 | add dword ptr ss:[esp+78],1
00401725 | lea eax,dword ptr ss:[esp+20]
00401729 | mov dword ptr ss:[esp],eax
0040172C | call <JMP.&strlen>
00401731 | mov edx,eax
00401733 | mov eax,dword ptr ss:[esp+78]
00401737 | cmp edx,eax
00401739 | ja keygen.401700
0040173B | cmp dword ptr ss:[esp+7C],0
00401740 | je keygen.4017BB | go "Wrong Key!"
[esp+7C]=1
[esp+78]=0
上から読んでjmpしてstrlenまでで入力した文字列から11文字目以降が何文字か確認している。
その後おそらくstrlenの戻り値が入ったedxと[esp+78]を比較している。
[esp+78]は1が代入されていた。
jaでedxが1より大きければjmpするらしい。
(ja: jump if above. cmp edx,eaxのあとのjaはif edx>eax, jmp)
eaxから0x30=48を引いてeaxが9以下だったら401720にjmp.
[esp+7C]は0じゃダメで、eaxが9以下ではないと[esp+7C]に0が代入されます。
そのためeaxが9以下になるようにしないといけないみたいです。
どんどんさかのぼってみると、eaxから0x30が引かれていて、0x30は"0"のことだから文字列の数字を数値に変換しています。
add edx, eaxで入力した文字列の11文字以降から9文字分が入ったアドレスに対して[esp+78]を足していて、あとを見ると[esp+78]はadd 1されて1ずつ増えています。
その後[esp+78]が文字数を超えるとja keygen.401700のループが止まる。
[esp+7C]が0になるのは入力した文字列の11文字以降の9文字が0~9の文字以外、すなわち数字以外のとき。
長くなりましたが入力した文字列の11文字以降の9文字が数字がどうかただ判定してるだけでしたね。
理解するのにすごい時間がかかってしまった。
00401742 | lea eax,dword ptr ss:[esp+20]
00401746 | mov dword ptr ss:[esp],eax
00401749 | call keygen.40158D
0040174E | mov dword ptr ss:[esp+70],eax
00401752 | cmp dword ptr ss:[esp+70],F9B9B765
0040175A | jne keygen.4017BB
9文字を関数 keygen.40158Dに渡して、その戻り値がF9B9B765でなかったら”Wrong Key!”に飛ばすみたいです。
call 40158Dの中身をみてみます。
今気づいたんですけど、x64dbgの逆アセンブリをメモ帳にコピペするときれいに表示されるんですね。
bloggerだと右側のレジスタの中身を表示してくれる部分の|がずれてちゃうんですよね。
なんでなんだろう。
スペースの設定がおかしいとか?
0040158D | push ebp
0040158E | mov ebp,esp
00401590 | sub esp,10
00401593 | mov dword ptr ss:[ebp-C],1000193
0040159A | mov dword ptr ss:[ebp-10],811C9DC5
004015A1 | mov eax,dword ptr ss:[ebp-10]
004015A4 | mov dword ptr ss:[ebp-4],eax
004015A7 | mov eax,dword ptr ss:[ebp+8]
004015AA | mov dword ptr ss:[ebp-8],eax
004015AD | jmp keygen.4015C9
関数といえばpush ebp, mov ebp,espですよね。
リバースエンジニアリングバイブルの本も最初は関数のアセンブリの説明でした。
でもこの部分が本当に理解できなくて本に書き込みながら頑張って理解しようとした記憶があります。
おかげで今では何となくはわかるようになりました。
まあ関数の呼び出し規約のページは読み飛ばしちゃったんですけどね。
スタックをまとめると、
[ebp-10]=811C9DC5
[ebp-C]=1000193
[ebp-8]=[ebp+8]=入力した文字列9文字へのアドレス
[ebp-4]=[ebp-10]=811C9DC5
[ebp]=もとのebp
[ebp+4]=リターンアドレス
[ebp+8]=入力した文字列9文字へのアドレス
次に4015C9にジャンプします。
004015AF | mov eax,dword ptr ss:[ebp-8]
004015B2 | movzx eax,byte ptr ds:[eax]
004015B5 | movsx eax,al
004015B8 | xor dword ptr ss:[ebp-4],eax
004015BB | mov eax,dword ptr ss:[ebp-4]
004015BE | imul eax,dword ptr ss:[ebp-C]
004015C2 | mov dword ptr ss:[ebp-4],eax
004015C5 | add dword ptr ss:[ebp-8],1
004015C9 | mov eax,dword ptr ss:[ebp-8]
004015CC | movzx eax,byte ptr ds:[eax]
004015CF | test al,al
004015D1 | jne keygen.4015AF
9文字から一文字だけ文字列のまま取り出して811C9DC5とxorする。
その値と1000193を掛ける。
次の文字を取り出して終端文字の0でなければ繰り返す。
なんか計算めんどくさそう。
004015D3 | mov eax,dword ptr ss:[ebp-4]
004015D6 | leave
004015D7 | ret
xorと掛け算をした値を戻り値として渡してもどる。
この値がF9B9B765になればいいということですね。
よくわからないので実際の計算を見てみます。
9文字は”123456789”としてみます。
xor 811C9DC5,31("1")
=811C 9DF4
imul 811C9DF4,1000193
=81 1D69 340C A71C
eaxは32ビットだから4バイト分の 340C A71C
xor 340CA71C,32("2")
=340CA72E
imul 340CA72E,1000193
=34 0CF9 1DEB 2D6A
=1DEB 2D6A
あと繰り返し。
(811C9DC5 xor "n")*1000193を繰り返してF9B9B765になる。。
逆の計算にして割り算してxorすればいいと思ったけれど32ビットで切り捨てるから割り算ができない。
どうやってやるんや。
考えても逆算はできなさそう。
むりやり当てはめるのか?
やり方がわからなかったのでここであきらめた。
てかまだ何もしてないじゃん・・・
コメントを見るとz3というpythonのライブラリを使うらしい。
これで総当たりするらしい。
solutionを軽く見るとこれはFNVハッシュ関数らしい。
しかもこの9文字の後も暗号化がまだ残っていたらしい。
いやもうこれむりやん。
もっと勉強してまたいつか思い出したら解きなおそう。
ちなみに5か月前はqualityが4.7だったのに今は5.0に上がっていた。
みんなこれ解けるんだなー。
difficulty 3.6でこの難しさかー。
もっと簡単なやつ今度やってみよ。
0040175C | lea eax,dword ptr ss:[esp+40]
00401760 | add eax,14
00401763 | mov dword ptr ss:[esp+8],C
0040176B | mov dword ptr ss:[esp+4],eax
0040176F | lea eax,dword ptr ss:[esp+10]
00401773 | mov dword ptr ss:[esp],eax
00401776 | call <JMP.&strncpy>
0040177B | mov dword ptr ss:[esp+4],6
00401783 | lea eax,dword ptr ss:[esp+10]
00401787 | mov dword ptr ss:[esp],eax
0040178A | call keygen.401460
0040178F | mov dword ptr ss:[esp+4],keygen.405070 | 405070:"_Q3eM3tT1t6}}"
00401797 | mov dword ptr ss:[esp],eax
0040179A | call <JMP.&strcmp>
0040179F | test eax,eax
004017A1 | jne keygen.4017BB
004017A3 | mov dword ptr ss:[esp],keygen.405080 | 405080:"Congrats! You cracked this shit!"
004017AA | call <JMP.&puts>
004017AF | mov dword ptr ss:[esp],0
004017B6 | call <JMP.&exit>
004017BB | mov dword ptr ss:[esp],keygen.4050A1 | 4050A1:"Wrong Key!"
004017C2 | call <JMP.&puts>
004017C7 | jmp keygen.4017D5
004017C9 | mov dword ptr ss:[esp],keygen.4050AC | 4050AC:"Wrong Length!"
004017D0 | call <JMP.&puts>
004017D5 | mov eax,0
004017DA | leave
004017DB | ret
コメント
0 件のコメント :
コメントを投稿