私は逆アセンブラーを使うように言われました。 gcc
には何かが組み込まれていますか?これを行う最も簡単な方法は何ですか?
gcc
は主にコンパイラーであるため、フラグはないと思いますが、別のGNU開発ツールにはあります。objdump
は-d
/--disassemble
を取ります国旗:
$ objdump -d /path/to/binary
分解は次のようになります。
080483b4 <main>:
80483b4: 8d 4c 24 04 lea 0x4(%esp),%ecx
80483b8: 83 e4 f0 and $0xfffffff0,%esp
80483bb: ff 71 fc pushl -0x4(%ecx)
80483be: 55 Push %ebp
80483bf: 89 e5 mov %esp,%ebp
80483c1: 51 Push %ecx
80483c2: b8 00 00 00 00 mov $0x0,%eax
80483c7: 59 pop %ecx
80483c8: 5d pop %ebp
80483c9: 8d 61 fc lea -0x4(%ecx),%esp
80483cc: c3 ret
80483cd: 90 nop
80483ce: 90 nop
80483cf: 90 nop
Objdumpの興味深い代替手段はgdbです。バイナリを実行したり、debuginfoを持っている必要はありません。
$ gdb -q ./a.out
Reading symbols from ./a.out...(no debugging symbols found)...done.
(gdb) info functions
All defined functions:
Non-debugging symbols:
0x00000000004003a8 _init
0x00000000004003e0 __libc_start_main@plt
0x00000000004003f0 __gmon_start__@plt
0x0000000000400400 _start
0x0000000000400430 deregister_tm_clones
0x0000000000400460 register_tm_clones
0x00000000004004a0 __do_global_dtors_aux
0x00000000004004c0 frame_dummy
0x00000000004004f0 fce
0x00000000004004fb main
0x0000000000400510 __libc_csu_init
0x0000000000400580 __libc_csu_fini
0x0000000000400584 _fini
(gdb) disassemble main
Dump of assembler code for function main:
0x00000000004004fb <+0>: Push %rbp
0x00000000004004fc <+1>: mov %rsp,%rbp
0x00000000004004ff <+4>: sub $0x10,%rsp
0x0000000000400503 <+8>: callq 0x4004f0 <fce>
0x0000000000400508 <+13>: mov %eax,-0x4(%rbp)
0x000000000040050b <+16>: mov -0x4(%rbp),%eax
0x000000000040050e <+19>: leaveq
0x000000000040050f <+20>: retq
End of assembler dump.
(gdb) disassemble fce
Dump of assembler code for function fce:
0x00000000004004f0 <+0>: Push %rbp
0x00000000004004f1 <+1>: mov %rsp,%rbp
0x00000000004004f4 <+4>: mov $0x2a,%eax
0x00000000004004f9 <+9>: pop %rbp
0x00000000004004fa <+10>: retq
End of assembler dump.
(gdb)
完全なデバッグ情報があればさらに良いです。
(gdb) disassemble /m main
Dump of assembler code for function main:
9 {
0x00000000004004fb <+0>: Push %rbp
0x00000000004004fc <+1>: mov %rsp,%rbp
0x00000000004004ff <+4>: sub $0x10,%rsp
10 int x = fce ();
0x0000000000400503 <+8>: callq 0x4004f0 <fce>
0x0000000000400508 <+13>: mov %eax,-0x4(%rbp)
11 return x;
0x000000000040050b <+16>: mov -0x4(%rbp),%eax
12 }
0x000000000040050e <+19>: leaveq
0x000000000040050f <+20>: retq
End of assembler dump.
(gdb)
objdumpには同様のオプションがあります(-S)
この回答はx86に固有のものです。 AArch64、MIPS、またはobjdump
およびllvm-objdump
を含むあらゆるマシンコードを逆アセンブルできるポータブルツール。
Agner Fogの逆アセンブラー 、objconv
は非常に素晴らしいです。パフォーマンスの問題(たとえば、16ビットのイミディエート定数を持つ命令からの恐ろしいLCPストールなど)の逆アセンブリ出力にコメントを追加します。
objconv -fyasm a.out /dev/stdout | less
(-
はstdoutの省略形として認識されません。デフォルトでは、.asm
が付加された状態で、入力ファイルと同様の名前のファイルに出力されます。)
また、分岐ターゲットをコードに追加します。他の逆アセンブラーは通常、ジャンプ先の命令を数値の宛先のみで逆アセンブルします。また、ループの先頭を見つけやすくするために、分岐ターゲットにマーカーを配置しないでください。
また、他の逆アセンブラーよりも明確にNOPを示します(別の命令として分解するのではなく、パディングがある場合にそれを明確にします)。
オープンソースであり、Linux向けに簡単にコンパイルできます。 NASM、YASM、MASM、またはGNU(AT&T)構文に分解できます。
サンプル出力:
; Filling space: 0FH
; Filler type: Multi-byte NOP
; db 0FH, 1FH, 44H, 00H, 00H, 66H, 2EH, 0FH
; db 1FH, 84H, 00H, 00H, 00H, 00H, 00H
ALIGN 16
foo: ; Function begin
cmp rdi, 1 ; 00400620 _ 48: 83. FF, 01
jbe ?_026 ; 00400624 _ 0F 86, 00000084
mov r11d, 1 ; 0040062A _ 41: BB, 00000001
?_020: mov r8, r11 ; 00400630 _ 4D: 89. D8
imul r8, r11 ; 00400633 _ 4D: 0F AF. C3
add r8, rdi ; 00400637 _ 49: 01. F8
cmp r8, 3 ; 0040063A _ 49: 83. F8, 03
jbe ?_029 ; 0040063E _ 0F 86, 00000097
mov esi, 1 ; 00400644 _ BE, 00000001
; Filling space: 7H
; Filler type: Multi-byte NOP
; db 0FH, 1FH, 80H, 00H, 00H, 00H, 00H
ALIGN 8
?_021: add rsi, rsi ; 00400650 _ 48: 01. F6
mov rax, rsi ; 00400653 _ 48: 89. F0
imul rax, rsi ; 00400656 _ 48: 0F AF. C6
shl rax, 2 ; 0040065A _ 48: C1. E0, 02
cmp r8, rax ; 0040065E _ 49: 39. C0
jnc ?_021 ; 00400661 _ 73, ED
lea rcx, [rsi+rsi] ; 00400663 _ 48: 8D. 0C 36
...
この出力はオブジェクトファイルにアセンブルする準備ができているため、マシンコードの16進エディタではなく、asmソースレベルでコードを微調整できます。 (つまり、同じサイズを維持することに限定されません。)変更がなければ、結果はほぼ同じになるはずです。しかし、そうではないかもしれません
(from /lib/x86_64-linux-gnu/libc.so.6)
SECTION .plt align=16 execute ; section number 11, code
?_00001:; Local function
Push qword [rel ?_37996] ; 0001F420 _ FF. 35, 003A4BE2(rel)
jmp near [rel ?_37997] ; 0001F426 _ FF. 25, 003A4BE4(rel)
...
ALIGN 8
?_00002:jmp near [rel ?_37998] ; 0001F430 _ FF. 25, 003A4BE2(rel)
; Note: Immediate operand could be made smaller by sign extension
Push 11 ; 0001F436 _ 68, 0000000B
; Note: Immediate operand could be made smaller by sign extension
jmp ?_00001 ; 0001F43B _ E9, FFFFFFE0
ソースには、32ビットオフセットで書き直すための再配置の余地を残して、より長いエンコーディングにアセンブルすることを確認するものは何もありません。
Objconvをインストールしたくない場合は、GNU binutils objdump -Mintel -d
は非常に使いやすく、通常のLinux gccセットアップがあればインストール済みです。
ndisasmもありますが、これにはいくつかの癖がありますが、nasmを使用するとより便利になります。 Michael Mrozekには、objdumpがおそらく最高だと思います。
[あとで] Albert van der Horstのciasdisもチェックしてみてください: http://home.hccnet.nl/a.w.m.van.der.horst/forthassembler.html 。理解するのは難しいかもしれませんが、他には見られない興味深い機能がいくつかあります。
IDA Pro および Decompiler を使用します。
ODAが役立つかもしれません。これは、大量のアーキテクチャをサポートするWebベースの逆アセンブラーです。
ht editor は、多くの形式のバイナリを逆アセンブルできます。 Hiewに似ていますが、オープンソースです。
分解するには、バイナリを開き、F6を押してからelf/imageを選択します。