katagaitai勉強会#6-関西easyに参加しました記事の続きです.
私が初めて知ったこと等を中心にWriteUp書いてみます.
Reversing
@shironooさんの資料は・・・公開されていないかな?
CSAW CTF 2013: crackme
問題文: nc 45.32.49.214 54321
バイナリ: bin
crackme問題
バイナリが与えられ,正しい入力を入れるとFLAGが得られる. 入力値をどこかで検証しているはず.
解法の流れ
- バイナリを読む
入力値の検証部分を理解すれば十分なことが多い. - 検証をパスする入力をもとめる
逆演算を行う関数を求める
or
ブルートフォース -> 今回はこれ
表層解析
色々見てみる.
$ file crackme crackme: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=3ec5ee1f1d99fc4878737c38eec4468eff371802, stripped
$ strings crackme ... crackme Enter registration code: Thank you, valued customer! Your key is: %s Invalid registration code. ;*2$" GCC: (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3 ...
$ readelf -r crackme
htons, accept, bind, listenを使っているので自前のネットワークサーバっぽい.
静的解析
IDA ProのFree版を使う.
投げ込むとさっきのstringsの結果的なものがある.
Enter registration code:
につづいて入力したあと,正解してコード表示or失敗に分岐するような感じがする.
stringsのEnter registration code:
をダブクリするとコードのその部分に飛べる.
さらにその部分から図に飛ぶ.
こんな感じに入力させて,なんかして,分岐する,という処理が見える.
なんかしてる部分を読み解く
関数sub_8048EA0
の返り値で分岐判断している.その関数を見てみる.
ちょっとまだ読み慣れないけどがんばって読む.
- Intel記法
[eax]
のようにカッコがあるとアドレスal
はeax
の最下位8bit- 変数を選択してダブクリで変数名を書き換えられる
- 行を選択して";"でコメントを付けられる
読み解いた関数の内容がこれ.
def sub_8048EA0(arg): c = 1337 for s in arg: c += s + c*32 return c
この結果が0EF2E3558h
つまり0xEF2E3558
と一致すればよい.
逆関数は作れず推測も無理なため,解くためにはブルートフォース.
Brute Force
ちょっと書くの疲れたので,どんなことをやったかのみ.
自前実装
適切な入力の長さが不明,文字種も不明.少なめの文字数から順に総当りしていく.
今回は勉強会中ということで,ASCIIの表示可能文字(0x20' ' ~ 0x7e'~')だけでいいよーということでやってみる. C言語じゃないと遅すぎるということだが,とりあえず,というだけでpythonで書いちゃった.とても遅かった.klee
シンボリック実行ツール. 入力値を与えた時のプログラムの実行経路をシミュレートするプログラム,と理解した.
入力値の範囲を指定すると制約を満たす入力を自動生成して試す. 元々テストツールっぽいのでassertを使い,当たりを引いたら終了するようにする. C言語のコードが必要なため,入力値検証部分は書く必要がある.
たしか10秒もせず結果が出たような.Z3
SMTソルバ.
制約式をちょっと特殊な感じで記述し,実行する.
kleeよりは遅いみたい.
おみやげ
メモリのアドレスとかを考えやすい目盛り入りのメモ帳です.わーい.
所感
要勉強!
あとブログを書くのに毎回ものすごく時間をかけているのでもうちょっとどうにかしたいです.以上!