CheatEngineでCrackMeを解いてみた【方法解説】

珍しくちょっとした技術系の記事になります。

eagle0wlさん(@eagle0wl)のcrackmeを使用させていただきました。

技術向上を目的とした記事になります。

クラックする方法は様々ありますが、Cheat Engineという動的デバッガを使用してクラックしてみます。

スポンサーリンク

Cheat EngineでCrackMeしてみた

CrackMeで自分の技術力を確かめたり、向上が可能です。

パズルを解くような感覚で楽しいのでやってみました。

注意:記事の内容はすべて自己責任でお願いします。

 

この記事に書いてある内容は、CrackMeの答えなのでネタバレ注意です。

殴り書き感ありますが、わからない場合C言語の勉強などをしてから見ると理解ができると思います。

 

crackmeのダウンロード

下記のHPからダウンロードしました。

http://www.mysys.org/eagle0wl/

「eagle0wl’s crackme VOL.01 ver1.02」というリンクですね。

 

crkme01.exeを解く

まずはデバッガを使わずに動作確認します。

入力欄にテキトーな文字を入力したり空にした状態で登録ボタンを押すと、「不正解です!」というメッセージが表示されました。

私は「入力欄の文字列何かの文字列比較しているんだな」と考えました。

 

とりあえず、該当の比較処理を探します。

WindowsAPIの「MessageBoxA関数」に移動します。これはメッセージボックスを表示する関数です。

 

returnのところにブレークポイントを設置します。具体的には「ret 0010」の「MessageBoxA+1B」のアドレスです。

設置したら、登録ボタンを押してメッセージボックスを表示させます。そして閉じます。すると引っかかります。F7のStepで返ります。どうやら、アドレス: 0040121C でメッセージボックスの関数を呼び出していたようです。

この関数呼出は「不正解です!」の場合のものです。つまり、「正解です!」のようなメッセージボックスを呼出すアドレスもあるはずです。(予想)

というか、予想していた「比較」の処理があるはずです。

ありました。je crkme01.exe+1226 ってやつですね。(ちなみにcrkme01.exeは 00400000 から始まってます。)

 

あとは、この処理をjmp とか jneに書き換えれば、「正解です!」と表示されます。

 

入力欄に入力する正しい文字列を知りたいのなら、比較命令の上を見れば良いです。

lstrcmp関数を使っている場所がありますね。その上にpushがありますが、これが引数です。

というか、右のCommentに答えが書いてありますね…。Cheat Engine便利。

Ctrl + V で表示・非表示の切り替えができます。

 

 

crkme02.exe

crkme01.exeと同じ方法です。

ただ、01とは比較処理が異なっています。

lstrcmp関数が見当たりません。ブレークポイント設置しても引っかかりませんでした。

 

MessageBoxAのretから呼び出し元を特定して解析してみると、

004011FD の jne 00401221 という命令で 00401221 にジャンプしていたようです。

つまり「cmp eax,08」という命令でFalseだったということです。Falseという表現はよくない気もしますが。

 

「cmp eax,08」は何かな?と考えましたが、感覚で文字数チェックかなと思いました。確認すべくcmp命令のところでブレークポイント設置。入力欄には、5文字を入れて登録ボタンを押します。するとEAXは00000005になっていました。

 

「cmp eax,08」の上には『GetWindowText』という関数を呼び出しているようです。なんだろこれ?

戻り値
関数が成功すると、コピーされた文字列の文字数が返ります( 終端の NULL 文字は含められません)。タイトルバーやテキストがない場合、タイトルバーが空の場合、および hWnd パラメータに指定したウィンドウハンドルまたはコントロールハンドルが無効な場合は 0 が返ります。拡張エラー情報を取得するには、 関数を使います。

https://msdn.microsoft.com/ja-jp/library/cc364815.aspx

 

つまり、まず1つめの比較処理は「文字数チェック」です。

ふるいをかけたイメージですね。

文字数チェックしたあとは、文字列の比較をすると予想がつきます。

しかし、先ほど書いたようにlstrcmpなどの文字列比較関数を使ってません。どういうチェックをしているのでしょうか。

8文字入力した場合はjneでジャンプせずに「0040123A」をCallしています。なので「0040123A」を見てみると、cmp→jneの命令が繰り返されています。もう1文字ずつ比較しているんだなとわかります。

「mov esi,0040302C」この命令で、esiに入力した文字列が入ります。

esi = 1文字目
esi+1 = 2文字目…

となってます。

 

下のcmp命令の第2オペランドの16進数が答えになります。

mov esi,crkme02.exe+302C
cmp byte ptr [esi],35
jne crkme02.exe+1271
cmp byte ptr [esi+01],45
jne crkme02.exe+1271
cmp byte ptr [esi+02],48
jne crkme02.exe+1271
cmp byte ptr [esi+03],39
jne crkme02.exe+1271
cmp byte ptr [esi+04],56
jne crkme02.exe+1271
cmp byte ptr [esi+05],33
jne crkme02.exe+1271
cmp byte ptr [esi+06],51
jne crkme02.exe+1271
cmp byte ptr [esi+07],57
jne crkme02.exe+1271
inc eax
ret

 

つまり、答えは 5EH9V3QW になります。(ドラッグして選択してください。)

 

改ざん方法は色々ありますが、どこかの命令を「call 00401208」とでもすれば良いでしょう。なにを入力しても正解ですと表示されます。

 

 

また、気が向いたら続きをかくかも。

コメント

  1. 匿名 より:

    え..えーと… は…はっかー…はんたーい

タイトルとURLをコピーしました