GNU/Linux >> Belajar Linux >  >> Linux

Bagaimana cara membongkar biner yang dapat dieksekusi di Linux untuk mendapatkan kode perakitan?

Jawaban ini khusus untuk x86. Alat portabel yang dapat membongkar AArch64, MIPS, atau kode mesin apa pun termasuk objdump dan llvm-objdump .

Pembongkar Agner Fog, objconv , cukup bagus. Ini akan menambahkan komentar ke output pembongkaran untuk masalah kinerja (seperti kios LCP yang ditakuti dari instruksi dengan konstanta langsung 16bit, misalnya).

objconv  -fyasm a.out /dev/stdout | less

(Itu tidak mengenali - sebagai singkatan untuk stdout, dan secara default menghasilkan file dengan nama yang mirip dengan file input, dengan .asm ditempel.)

Itu juga menambahkan target cabang ke kode. Disassembler lain biasanya membongkar instruksi lompatan hanya dengan tujuan numerik, dan tidak meletakkan penanda apa pun di target cabang untuk membantu Anda menemukan bagian atas loop dan seterusnya.

Ini juga menunjukkan NOP lebih jelas daripada disassembler lainnya (menjelaskan saat ada padding, daripada membongkarnya hanya sebagai instruksi lain.)

Ini open source, dan mudah dikompilasi untuk Linux. Itu dapat dibongkar menjadi sintaks NASM, YASM, MASM, atau GNU (AT&T).

Keluaran sampel:

; 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
...

Perhatikan bahwa output ini siap untuk dirakit kembali menjadi file objek, sehingga Anda dapat men-tweak kode di tingkat sumber asm, bukan dengan hex-editor pada kode mesin. (Jadi Anda tidak dibatasi untuk menjaga ukuran tetap sama.) Tanpa perubahan, hasilnya harus hampir identik. Namun, mungkin bukan karena pembongkaran hal-hal seperti

  (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

tidak memiliki apa pun di sumber untuk memastikannya dirangkai menjadi penyandian yang lebih panjang yang menyisakan ruang untuk relokasi untuk menulis ulang dengan offset 32 ​​bit.

Jika Anda tidak ingin menginstalnya objconv, GNU binutils objdump -Mintel -d sangat berguna, dan sudah terpasang jika Anda memiliki penyiapan gcc Linux normal.


Alternatif yang menarik untuk objdump adalah gdb. Anda tidak perlu menjalankan biner atau memiliki info debug.

$ 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  [email protected]
0x00000000004003f0  [email protected]
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)

Dengan info debug lengkap, ini bahkan lebih baik.

(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 memiliki opsi serupa (-S)


Saya tidak berpikir gcc memiliki bendera untuk itu, karena ini terutama merupakan kompiler, tetapi alat pengembangan GNU lainnya memilikinya. objdump mengambil -d /--disassemble bendera:

$ objdump -d /path/to/binary

Pembongkaran terlihat seperti ini:

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

Linux
  1. Linux – Bagaimana Cara Mendapatkan Nama Sistem Operasi yang Andal?

  2. Linux – Bagaimana Cara Membuat Patch Mengabaikan Perbedaan Indentasi Dalam Kode?

  3. Linux – Bagaimana Menguji Apakah Biner Linux Dikompilasi Sebagai Kode Independen Posisi?

  1. Bagaimana cara membongkar, memodifikasi, dan kemudian memasang kembali executable Linux?

  2. Bagaimana cara mendapatkan jumlah CPU di Linux menggunakan C?

  3. Bagaimana Anda menentukan lokasi perpustakaan ke biner? (linux)

  1. Bagaimana Mendapatkan Informasi Lebih Lanjut Tentang Asal Usul Kode Keluar?

  2. Bagaimana saya bisa mendapatkan status keyboard di Linux?

  3. Bagaimana cara mendapatkan nama pengguna di C/C++ di Linux?