Ответ 1
Хорошо, вот большой выпуск моего предыдущего ответа. Я думаю, что нашел путь сейчас.
У вас (все еще) есть эта специфическая проблема:
(gdb) disas main
No symbol table is loaded. Use the "file" command.
Теперь, если вы скомпилируете код (я добавил a return 0
в конце), вы получите gcc -S
:
pushq %rbp
movq %rsp, %rbp
movl $.LC0, %edi
call puts
movl $0, %eax
leave
ret
Теперь вы можете видеть, что ваш двоичный файл дает вам информацию:
Полосатый:
(gdb) info files
Symbols from "/home/beco/Documents/fontes/cpp/teste/stackoverflow/distrip".
Local exec file:
`/home/beco/Documents/fontes/cpp/teste/stackoverflow/distrip', file type elf64-x86-64.
Entry point: 0x400440
0x0000000000400238 - 0x0000000000400254 is .interp
...
0x00000000004003a8 - 0x00000000004003c0 is .rela.dyn
0x00000000004003c0 - 0x00000000004003f0 is .rela.plt
0x00000000004003f0 - 0x0000000000400408 is .init
0x0000000000400408 - 0x0000000000400438 is .plt
0x0000000000400440 - 0x0000000000400618 is .text
...
0x0000000000601010 - 0x0000000000601020 is .data
0x0000000000601020 - 0x0000000000601030 is .bss
Самая важная запись здесь - .text
. Это общее название для начала сборки кода, и из нашего объяснения основного ниже, из его размера, вы можете видеть, что он включает в себя основной. Если вы разберете его, вы увидите вызов __libc_start_main. Самое главное, вы разбираете хорошую точку входа, которая является реальным кодом (вы не вводите в заблуждение, чтобы изменить DATA на CODE).
disas 0x0000000000400440,0x0000000000400618
Dump of assembler code from 0x400440 to 0x400618:
0x0000000000400440: xor %ebp,%ebp
0x0000000000400442: mov %rdx,%r9
0x0000000000400445: pop %rsi
0x0000000000400446: mov %rsp,%rdx
0x0000000000400449: and $0xfffffffffffffff0,%rsp
0x000000000040044d: push %rax
0x000000000040044e: push %rsp
0x000000000040044f: mov $0x400540,%r8
0x0000000000400456: mov $0x400550,%rcx
0x000000000040045d: mov $0x400524,%rdi
0x0000000000400464: callq 0x400428 <[email protected]>
0x0000000000400469: hlt
...
0x000000000040046c: sub $0x8,%rsp
...
0x0000000000400482: retq
0x0000000000400483: nop
...
0x0000000000400490: push %rbp
..
0x00000000004004f2: leaveq
0x00000000004004f3: retq
0x00000000004004f4: data32 data32 nopw %cs:0x0(%rax,%rax,1)
...
0x000000000040051d: leaveq
0x000000000040051e: jmpq *%rax
...
0x0000000000400520: leaveq
0x0000000000400521: retq
0x0000000000400522: nop
0x0000000000400523: nop
0x0000000000400524: push %rbp
0x0000000000400525: mov %rsp,%rbp
0x0000000000400528: mov $0x40062c,%edi
0x000000000040052d: callq 0x400418 <[email protected]>
0x0000000000400532: mov $0x0,%eax
0x0000000000400537: leaveq
0x0000000000400538: retq
Призыв __ libc_start_main получает в качестве первого аргумента указатель на main(). Итак, последний аргумент в стеке непосредственно перед вызовом - ваш основной() адрес.
0x000000000040045d: mov $0x400524,%rdi
0x0000000000400464: callq 0x400428 <[email protected]>
Вот он 0x400524 (как мы уже знаем). Теперь вы установите точку останова, попробуйте это:
(gdb) break *0x400524
Breakpoint 1 at 0x400524
(gdb) run
Starting program: /home/beco/Documents/fontes/cpp/teste/stackoverflow/disassembly/d2
Breakpoint 1, 0x0000000000400524 in main ()
(gdb) n
Single stepping until exit from function main,
which has no line number information.
hello 1
__libc_start_main (main=<value optimized out>, argc=<value optimized out>, ubp_av=<value optimized out>,
init=<value optimized out>, fini=<value optimized out>, rtld_fini=<value optimized out>,
stack_end=0x7fffffffdc38) at libc-start.c:258
258 libc-start.c: No such file or directory.
in libc-start.c
(gdb) n
Program exited normally.
(gdb)
Теперь вы можете разобрать его, используя:
(gdb) disas 0x0000000000400524,0x0000000000400600
Dump of assembler code from 0x400524 to 0x400600:
0x0000000000400524: push %rbp
0x0000000000400525: mov %rsp,%rbp
0x0000000000400528: sub $0x10,%rsp
0x000000000040052c: movl $0x1,-0x4(%rbp)
0x0000000000400533: mov $0x40064c,%eax
0x0000000000400538: mov -0x4(%rbp),%edx
0x000000000040053b: mov %edx,%esi
0x000000000040053d: mov %rax,%rdi
0x0000000000400540: mov $0x0,%eax
0x0000000000400545: callq 0x400418 <[email protected]>
0x000000000040054a: mov $0x0,%eax
0x000000000040054f: leaveq
0x0000000000400550: retq
0x0000000000400551: nop
0x0000000000400552: nop
0x0000000000400553: nop
0x0000000000400554: nop
0x0000000000400555: nop
...
Это прежде всего решение.
Кстати, это другой код, чтобы увидеть, работает ли он. Вот почему сборка выше немного отличается. Код из этого c файла:
#include <stdio.h>
int main(void)
{
int i=1;
printf("hello %d\n", i);
return 0;
}
Но!
Если это не сработает, у вас все еще есть некоторые подсказки:
Теперь вы должны искать, чтобы установить точки останова в начале всех функций. Они находятся непосредственно перед символом ret
или leave
. Первая точка входа - .text
. Это запуск сборки, но не основной.
Проблема заключается в том, что не всегда точка останова будет запускать вашу программу. Подобно этому в самом .text
:
(gdb) break *0x0000000000400440
Breakpoint 2 at 0x400440
(gdb) run
Starting program: /home/beco/Documents/fontes/cpp/teste/stackoverflow/disassembly/d2
Breakpoint 2, 0x0000000000400440 in _start ()
(gdb) n
Single stepping until exit from function _start,
which has no line number information.
0x0000000000400428 in [email protected] ()
(gdb) n
Single stepping until exit from function [email protected],
which has no line number information.
0x0000000000400408 in ?? ()
(gdb) n
Cannot find bounds of current function
Итак, вам нужно продолжать попытки, пока не найдете свой путь, установив точки останова:
0x400440
0x40046c
0x400490
0x4004f4
0x40051e
0x400524
Из другого ответа мы должны сохранить эту информацию:
В нестрочной версии файла мы видим:
(gdb) disas main
Dump of assembler code for function main:
0x0000000000400524 <+0>: push %rbp
0x0000000000400525 <+1>: mov %rsp,%rbp
0x0000000000400528 <+4>: mov $0x40062c,%edi
0x000000000040052d <+9>: callq 0x400418 <[email protected]>
0x0000000000400532 <+14>: mov $0x0,%eax
0x0000000000400537 <+19>: leaveq
0x0000000000400538 <+20>: retq
End of assembler dump.
Теперь мы знаем, что main находится в 0x0000000000400524,0x0000000000400539
. Если мы используем одно и то же смещение, чтобы посмотреть на полосатый бинарный файл, мы получим те же результаты:
(gdb) disas 0x0000000000400524,0x0000000000400539
Dump of assembler code from 0x400524 to 0x400539:
0x0000000000400524: push %rbp
0x0000000000400525: mov %rsp,%rbp
0x0000000000400528: mov $0x40062c,%edi
0x000000000040052d: callq 0x400418 <[email protected]>
0x0000000000400532: mov $0x0,%eax
0x0000000000400537: leaveq
0x0000000000400538: retq
End of assembler dump.
Итак, если вы не можете получить подсказку, где начинается основной запуск (например, с использованием другого кода с символами), другой способ заключается в том, что вы можете получить некоторую информацию о первых инструкциях по сборке, чтобы вы могли разборки в определенных местах и посмотреть, Матчи. Если у вас вообще нет доступа к коду, вы все равно можете прочитать определение ELF, чтобы понять, сколько секций должно появиться в коде и попробовать рассчитанный адрес. Тем не менее, вам нужна информация о разделах в коде!
Это тяжелая работа, мой друг! Удачи!
Беко