web-dev-qa-db-ja.com

Linuxでバイナリ実行ファイルを逆アセンブルしてアセンブリコードを取得する方法は?

私は逆アセンブラーを使うように言われました。 gccには何かが組み込まれていますか?これを行う最も簡単な方法は何ですか?

60
Syntax_Error

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
97
Michael Mrozek

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)

31
Miroslav Franc

この回答は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セットアップがあればインストール済みです。

10
Peter Cordes

ndisasmもありますが、これにはいくつかの癖がありますが、nasmを使用するとより便利になります。 Michael Mrozekには、objdumpがおそらく最高だと思います。

[あとで] Albert van der Horstのciasdisもチェックしてみてください: http://home.hccnet.nl/a.w.m.van.der.horst/forthassembler.html 。理解するのは難しいかもしれませんが、他には見られない興味深い機能がいくつかあります。

5
jcomeau_ictx

IDA Pro および Decompiler を使用します。

3
ta.speot.is

ODAが役立つかもしれません。これは、大量のアーキテクチャをサポートするWebベースの逆アセンブラーです。

http://onlinedisassembler.com/

3
Anthony DeRosa

ht editor は、多くの形式のバイナリを逆アセンブルできます。 Hiewに似ていますが、オープンソースです。

分解するには、バイナリを開き、F6を押してからelf/imageを選択します。

1
arboreal84