我正在使用/bin/true作为示例二进制文件(没有可用的主要方法):

$ lldb /bin/true
(lldb) target create "/bin/true"
Current executable set to '/bin/true' (x86_64).
(lldb) break main
invalid command 'breakpoint main'


是否有任何通用的方法来运行二进制文件并在加载后立即停止调试器,因此可以加载适当的符号?等同于破坏main方法(代码的第一行)吗?还是我需要手动计算入口点?如果可以,怎么办?

评论

对于gdb,请参见:在SO
处停止gdb中的第一条机器代码指令

#1 楼

通常会剥离二进制文件。对于ELF二进制文件,可以使用file命令对其进行检查

$ file /bin/true
/bin/true: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0x73796652ea437df8ac7b3ba1864a7ac177e27600, stripped


在文件结果结尾处注意stripped。这意味着,除其他外,符号已被删除,因此找不到main函数。

为了在加载后立即运行二进制文件并停止调试器,有一种通用方法几乎应该总是起作用(有点通用,而不是100%)

您必须找到通过此命令获取的入口点:

$ readelf -h /bin/true | grep "Entry point"
  Entry point address:               0x401264


,然后将二进制文件加载到您喜欢的调试器(lldb,gdb等)中,然后中断此地址。

lldb:

$ lldb /bin/true
(lldb) target create "/bin/true"
Current executable set to '/bin/true' (x86_64).
(lldb) br s -a 0x401264
Breakpoint 1: address = 0x0000000000401264
(lldb) r
...
(lldb)


gdb:

$ gdb -q /bin/true
Reading symbols from /bin/true...(no debugging symbols found)...done.
gdb$ b *0x401264
Breakpoint 1 at 0x401264
gdb$ r
Breakpoint 1, 0x0000000000401264 in ?? ()
gdb$


一旦加载了二进制文件并触发了断点,就可以显示以下将以这种方式执行的指令:


(lldb) x -s4 -fi -c11 $pc
-> 0x401264:    xor    ebp,ebp
   0x401266:    mov    r9,rdx
   0x401269:    pop    rsi
   0x40126a:    mov    rdx,rsp
   0x40126d:    and    rsp,0xfffffffffffffff0
   0x401271:    push   rax
   0x401272:    push   rsp
   0x401273:    mov    r8,0x403560
   0x40127a:    mov    rcx,0x403570
   0x401281:    mov    rdi,0x4011c0
   0x401288:    call   0x401060 <__libc_start_main@plt>


gdb:

gdb$ x/11i $pc
=> 0x401264:    xor    ebp,ebp
   0x401266:    mov    r9,rdx
   0x401269:    pop    rsi
   0x40126a:    mov    rdx,rsp
   0x40126d:    and    rsp,0xfffffffffffffff0
   0x401271:    push   rax
   0x401272:    push   rsp
   0x401273:    mov    r8,0x403560
   0x40127a:    mov    rcx,0x403570
   0x401281:    mov    rdi,0x4011c0
   0x401288:    call   0x401060 <__libc_start_main@plt>


i标志表示指令,而$pc标志程序计数器(相当于32/64位体系结构的EIP / RIP)。您会看到__libc_start_main将在地址0x401288处被调用。其手册页指示其第一个参数是指向二进制main函数的指针。第一个参数在这里加载到rdi寄存器中,这意味着main函数位于地址0x4011c0处。

您只需要最终在该地址(0x4011c0)处放置一个断点,就可以在您的二进制主函数。

进一步阅读:如何使用GDB处理剥离的二进制文件?没有来源,没有符号,GDB只显示地址吗?

祝你好运,玩得开心!

评论


从GDB 8.1开始的最简单方法是starti命令。无需手动寻找入口点地址。

–俄罗斯
19年1月29日在20:52

#2 楼

来自http://lldb.llvm.org/tutorial.html:

(lldb) process launch --stop-at-entry -- -program_arg value


请注意,您的break maingdb命令; lldb的错误消息不是“没有这样的符号”,它是“无效的命令”。要在lldb中执行相同操作,请使用

(lldb) breakpoint set --name main