= x86逆コンパイルのすゝめ = <> = アセンブリ記法 = x86/x86-64アセンブリにはIntel記法とAT&T記法の2つの記法がある。 まずはIntel記法で学ぶことを奨める。AT&T記法はオペランドの順序が複雑であるためである。 == Intel記法 == 広く利用されている形式で、特にWindowsで好んで利用される記法である。 操作対象のレジスタが必ず最初のオペランドになる。 objdumpによる逆アセンブル例 {{{#!highlight nasm 0000000000000000 : 0: 55 push rbp 1: 48 89 e5 mov rbp,rsp 4: 48 83 ec 10 sub rsp,0x10 8: 89 7d fc mov DWORD PTR [rbp-0x4],edi b: 83 7d fc 01 cmp DWORD PTR [rbp-0x4],0x1 f: 75 07 jne 18 11: b8 01 00 00 00 mov eax,0x1 16: eb 11 jmp 29 18: 8b 45 fc mov eax,DWORD PTR [rbp-0x4] 1b: 83 e8 01 sub eax,0x1 1e: 89 c7 mov edi,eax 20: e8 00 00 00 00 call 25 25: 0f af 45 fc imul eax,DWORD PTR [rbp-0x4] 29: c9 leave 2a: c3 ret }}} == AT&T記法 == Unix-likeな環境のスタンダードな形式である。 Intel記法とはオペランドの順序が逆順になる。 objdumpによる逆アセンブル例 {{{#!highlight gas 0000000000000000 : 0: 55 push %rbp 1: 48 89 e5 mov %rsp,%rbp 4: 48 83 ec 10 sub $0x10,%rsp 8: 89 7d fc mov %edi,-0x4(%rbp) b: 83 7d fc 01 cmpl $0x1,-0x4(%rbp) f: 75 07 jne 18 11: b8 01 00 00 00 mov $0x1,%eax 16: eb 11 jmp 29 18: 8b 45 fc mov -0x4(%rbp),%eax 1b: 83 e8 01 sub $0x1,%eax 1e: 89 c7 mov %eax,%edi 20: e8 00 00 00 00 callq 25 25: 0f af 45 fc imul -0x4(%rbp),%eax 29: c9 leaveq 2a: c3 retq }}} = ツール = コマンドラインで利用できる逆アセンブラをいくつか紹介しておく。 まずはobjdumpを試し、手に馴染むものを探すと良い。 実行ファイル全般(elfでもPEでも) * objdump (binutils project) * [[http://www.agner.org/optimize/#objconv|objconv]] コード片(シェルコード)用 * udcli ([[http://udis86.sourceforge.net/|udis86 project]]) * Usage: [[CTF/Toolkit/udis86]] * ndisasm ([[http://www.nasm.us/|nasm project]]) * Intel形式のみ * Usage: [[CTF/Toolkit/ndisasm]] Windowsの実行ファイル(PE)専用 * [[http://hcilab.cju.ac.kr/disasm.html|Win32 Program disassembler]] * Intel形式のみ, 32bitのみ, 文字列埋め込みあり * [[http://kmkz.jp/mtm/?load=dispe|dispe]] * Intel形式のみ, 32bitのみ, フロー解析あり * Windows用は単なる逆アセンブラよりも、インタラクティブなGUIのデバッガ兼逆アセンブラが豊富である。 objdump補助スクリプト * [[CTF/Toolkit]]のobjdumpの欄にobjdumpの使い勝手を改良するスクリプトをいくつか用意してある。 == objdump == objdumpは逆アセンブルに限らず、各種オブジェクトファイルの情報を表示するツールである。 以下はオブジェクトファイルに含まれる情報の例である。 * ターゲットアーキテクチャ * プログラムの開始アドレス(エントリポイント) * セクションの開始位置とマップすべき仮想アドレス * シンボル名 * 機械語 * プログラム中の文字列を含む定数 (objdumpによるオブジェクトファイルの情報抽出は別稿にて) objdumpで逆アセンブルするには`-d`オプションを指定する。 Intel記法で逆アセンブルするには`-M intel`オプションを追加する必要がある。 {{{ $ objdump -d -M intel ./t ./t: file format elf64-x86-64 Disassembly of section .init: (略) Disassembly of section .plt: (略) Disassembly of section .text: (略) 000000000040051f
: 40051f: 55 push rbp 400520: 48 89 e5 mov rbp,rsp 400523: bf 0a 00 00 00 mov edi,0xa 400528: e8 c7 ff ff ff call 4004f4 40052d: 89 c2 mov edx,eax 40052f: b8 3c 06 40 00 mov eax,0x40063c 400534: 89 d6 mov esi,edx 400536: 48 89 c7 mov rdi,rax 400539: b8 00 00 00 00 mov eax,0x0 40053e: e8 ad fe ff ff call 4003f0 400543: 5d pop rbp 400544: c3 ret (略) Disassembly of section .fini: (略) }}} = ABIを理解する = [[http://sunnyone41.blogspot.jp/2012/09/x86x8664.html|x86/x86_64関数呼び出しチートシート]] (以下執筆予定) = 条件分岐命令を読む = = 命令の組み合わせで読む = = 制御構造を読む = == if-else == == ショートサーキット == == ループ == = leaを読む = = 配列操作を読む = = 構造体操作を読む =