Мне сказали использовать дизассемблер. У gcc
есть что-то встроенное? Каков самый простой способ сделать это?
Как разобрать бинарный исполняемый файл в Linux, чтобы получить код сборки?
Ответ 1
Я не думаю, что 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
Ответ 2
Интересной альтернативой 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 [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)
С полной информацией об отладке это еще лучше.
(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)
Ответ 3
Разборчик Agner Fog, objconv
, довольно приятный. Он добавит комментарии к выходу дизассемблера для проблем с производительностью (например, ужасный LCP-стойло из инструкций с 16-битными непосредственными константами, например).
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
...
Обратите внимание, что этот вывод готов к сборке обратно в объектный файл, поэтому вы можете настроить код на уровне источника 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
очень удобен и уже будет установлен, если у вас есть обычная установка gcc Linux.
Ответ 4
Используйте IDA Pro и Decompiler.
Ответ 5
там также ndisasm, у которого есть некоторые причуды, но может быть более полезным, если вы используете nasm. Я согласен с Майклом Мрозеком в том, что objdump, вероятно, лучше всего.
[позже] вы также можете проверить Albert van der Horst ciasdis: http://home.hccnet.nl/a.w.m.van.der.horst/forthassembler.html. это может быть трудно понять, но есть некоторые интересные функции, которые вы вряд ли найдете где-нибудь еще.
Ответ 6
Вы можете найти ODA полезной. Это веб-дизассемблер, который поддерживает множество архитектур.
Ответ 7
ht editor может дизассемблировать двоичные файлы во многих форматах. Он похож на Hiew, но с открытым исходным кодом.
Чтобы разобрать, откройте двоичный файл, затем нажмите F6, а затем выберите эльф/изображение.