chouett0's note

掃きだめ的なsomething

Crackme Writeup

はじめに

Crackmeという名前の問題というのはやたらといろいろありますが、今回僕が挑戦したのは「Crackme doomo」という問題。

Crackme doomo : http://doomo.main.jp/crack/

全部で20問くらいあるらしいですが、その中でようやく10問目まで終わったのでその備忘録。
一応これから始める方のために一部を除いて最終的な答えは見えにくくしてあります。
また、今回解析に用いたツールはは主にOllydbgですが、たまにx32dbg使ったりPEiDとか使ったりしました。 あと一応パッキングも施されていたのでupxでアンパックを行いました。

問題を配布しているサイトのほうにちゃんとした解答があるので間違いだったり説明が足りない場合はそちらを参考にしてください。

0x1

まず、Ollyの場合はCtrl+Nでこのプログラムで使われている関数を列挙し、その中からMessageBox関数を見つけだして
ブレイクポイント(以下BP)を仕掛けると、以下のような処理があることがわかります。

f:id:chouett0:20170711110742p:plain

この処理は、おそらくlstrcmp関数がわかる人なら察しが付くと思いますが、まずGetWindowText関数をcallして
入力された文字列を取得し、比較用文字列と入力文字列をpushしてlstrcmp関数で比較し、その結果に応じてメッセージボックスを
表示しているようです。なので、この問題の答えは「doomo」となります。 おそらくPE解析入門者向けの問題だったのかなと思うくらいそのままの問題でした。

0x2

この問題でも0x1と同じように、まずはMessageBox関数にBreakPointを仕掛けると、以下のようになっています。
ちなみに、本家(?)様のWriteupにはGetWindowTest関数にBPを設定していますが、この関数が呼ばれている
プログラムしかないということはないので、MessageBox関数に仕掛ける方が確実に目的の関数に近づけると思ったからです。

f:id:chouett0:20170711112333p:plain

話を戻しまして、どうやら前回のようにそのまま答えがあるわけではないようです。 GetWindowText関数直下にEAXレジスタと「8」をcmpしている処理がありますが、
EAXレジスタにはGetWindowText関数で 取得した文字列の文字数が格納されているため、
8文字である必要があるようです。
004011FF番地のcall命令が怪しいのでステップインで潜ってみると、
次のような処理が行われていました。

f:id:chouett0:20170711134858p:plain

0040123A番地でmov命令によりESIレジスタにコピーされているのは今回ダミーとして入力した文字列(abcdefgh)です。
そしてESI、つまりは入力した文字列のなかから一文字ずつ取り出し、数値と比較しているのが見て取れます。
ここが文字列比較の処理であり、オンラインのASCII変換器に投げると、
5EH9V3QW という文字列が現れます。つまり、これが答えとなります。

0x2a

この問題は今までとは違い、BPを仕掛けたことを検知する機能があるため、
ただセットしただけでは f:id:chouett0:20170711150938p:plain

このように、BPがセットされていることを警告するメッセージを表示して強制終了してしまいます。
そこで、文字列を実際に比較するルーチンのある部分へBPを仕掛けました。 f:id:chouett0:20170720112059p:plain

ここなら検知されないようです。そして、文字列を一文字ずつDLというレジスタ(正確にはEDXレジスタの下位部分)と比較しているようですので、実際にFLAGを操作しながら
中身を調べていけば答えとなる文字列がわかります。
また、DLに格納される値は疑似乱数を使っているらしく内部処理を追ってみると、Data Segmentに値を保持してxorなどの命令を用いて数値を算出したものをASCIIに変換して使っているようです。(あくまで個人的な見解なので合っている確証はありません)

0x3

この問題は、0x2aと違ってデバッグ検知ルーチンは存在しませんがGetWindowText関数は利用されていないようです。
f:id:chouett0:20170925233724p:plain

そこでまずは比較ルーチンがMessageBox関数の上に存在しているという仮定でBPを仕掛けると、以下のようになっていることがわかります。
f:id:chouett0:20170925233809p:plain
仮定通りMessageBox関数の真上に比較ルーチンらしきループ処理とその文字列、GetDlgItemTextという関数があることがわかります。
このGetDlgItemTextという関数が今までのGetWindowText関数の代わりをしているようです。
そして、その下の文字列を利用してルーチンを回すことで比較を行っていました。
比較ルーチンはいたって単純で「(0から始めて)カウンタが奇数回の時に比較文字列に+1したものを比較に用いる」という処理を行っていました。 ということで、コード内のvP12NGgoQaを先ほどのルーチンに当てはめてあげるとvQ13NHgpQbとなります。

この続きは随時更新していきます