어셈블리 코드를 얻기 위해 Linux에서 바이너리 실행 파일을 분해하는 방법은 무엇입니까? 사용하라고 들었습니다. 합니까는 gcc아무것도

디스어셈블러를 사용하라고 들었습니다. 합니까는 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 또는 모든 기계어 코드에 objdumpllvm-objdump.


Agner Fog의 디스어셈블러 , objconv는 꽤 좋습니다. 성능 문제에 대한 디스 어셈블리 출력에 주석을 추가합니다 (예 : 16 비트 즉시 상수를 사용하는 명령에서 LCP 중단과 같은).

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

( -표준 출력의 약자로 인식되지 않으며 기본적으로 입력 파일과 유사한 이름의 파일로 출력하는 것으로 .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 설정이있는 경우 이미 설치됩니다.


답변

몇 가지 단점이 있지만 nasm을 사용하면 더 유용 할 수있는 ndisasm도 있습니다. 나는 objdump가 아마도 최고라는 Michael Mrozek의 의견에 동의합니다.

[나중에] Albert van der Horst의 ciasdis : http://home.hccnet.nl/awmvan.der.horst/forthassembler.html 을 확인하고 싶을 수도 있습니다 . 이해하기 어려울 수 있지만 다른 곳에서는 찾을 수없는 흥미로운 기능이 있습니다.


답변

IDA ProDecompiler를 사용하십시오 .


답변

ODA가 유용 할 수 있습니다. 수많은 아키텍처를 지원하는 웹 기반 디스어셈블러입니다.

http://onlinedisassembler.com/


답변

재 조립할 어셈블리를 생성하는 데 아주 가까이 다가 갈 수 있습니다. bash.S 출력을 보낼 대상) :

objdump --no-show-raw-insn -Matt,att-mnemonic -Dz /bin/bash | grep -v "file format" | grep -v "(bad)" | sed '1,4d' | cut -d' ' -f2- | cut -d '<' -f2 | tr -d '>' | cut -f2- | sed -e "s/of\ section/#Disassembly\ of\ section/" | grep -v "\.\.\." > bash.S

그러나 이것이 얼마나 긴지 주목하십시오. 더 나은 방법 (또는 어셈블러가 인식 할 수있는 코드를 출력 할 수있는 디스어셈블러)이 있었으면 좋겠지 만 안타깝게도 그렇지 않습니다.