使用gdb在指定的可执行文件之外单步执行汇编代码会导致错误“找不到当前函数的边界”


86

我不在gdb的目标可执行文件之外,甚至没有对应于该目标的堆栈。无论如何,我都想单步执行,以便我可以验证汇编代码中发生的事情,因为我不是x86汇编方面的专家。不幸的是,gdb拒绝执行此简单的程序集级调试。它允许我在适当的断点处设置和停止,但是一旦我尝试单步执行,gdb就会报告错误“找不到当前函数的边界”,并且EIP不会更改。

额外细节:

机器代码是由gcc asm语句生成的,我从objdump -d的输出将其复制到了正在执行的内核内存位置。我不介意使用加载程序将目标代码加载到重定位地址的简单方法,但是请记住,加载必须在内核模块中完成。

我想另一种选择是产生一个伪造的内核模块或调试信息文件以提供给gdb,使它相信该区域在程序代码内。gdb在内核可执行文件本身上运行良好。

(对于那些真正想知道的人,我是在运行时将代码插入VMware VM内的Linux内核数据空间中,然后通过gdb调试它,通过VMware Workstation的内置gdb存根对内核进行远程调试。注意,我不是在编写内核漏洞利用;我是写原型的安全研究生。)

(我可以在程序集中的每条指令上设置一个断点。这可以工作,但是一段时间后会变得很费力,因为x86汇编指令的大小各不相同,并且每次重新启动时程序集的位置都会改变。)


聪明的ksplice.com人们通过组装“假”内核模块并加载它们来将数据和代码注入内核。如果他们能做到,为什么不呢?;-)
短暂

Answers:


116

您可以使用stepinexti(可以缩写为sini)逐步浏览您的机器代码。


1
哇。回想起来,我没有忘记Stepi。我想我只是假设是因为gdb没有源代码,因此该步骤将恢复为汇编指令。
保罗

1
注意:对于汇编程序,通常不能输入“ break main”,“ run”。键入“ layout asm”,“ start”。我是通过阅读下面的消息获得此信息的,但其他人对此帖子的了解可能不那么耐心。
德米特里

1
@Dmitrystart等于tbreak main后跟run(note:tbreak而不是break
Ruslan

151

相反gdb,运行gdbtui。或gdb通过-tui开关运行。或C-x C-a输入后按gdb。现在您处于GDB的TUI模式。

输入layout asm以制作上部窗口显示部件-尽管您也可以在调试时更改框架或滚动,但这将自动跟随您的指令指针。按C-x s进入“单键模式”,其中run continue up down finish等等缩写为一个键,使您可以快速浏览程序。

   + ------------------------------------------------- -------------------------- +
B +> | 0x402670 <main>推送%r15 |
   | 0x402672 <main + 2> mov%edi,%r15d |
   | 0x402675 <main + 5>推送%r14 |
   | 0x402677 <main + 7>推送%r13 |
   | 0x402679 <main + 9> mov%rsi,%r13 |
   | 0x40267c <main + 12>推送%r12 |
   | 0x40267e <main + 14>推送%rbp |
   | 0x40267f <main + 15>推送%rbx |
   | 0x402680 <main + 16>子$ 0x438,%rsp |
   | 0x402687 <main + 23> mov(%rsi),%r​​di |
   | 0x40268a <main + 26> movq $ 0x402a10,0x400(%rsp)|
   | 0x402696 <main + 38> movq $ 0x0,0x408(%rsp)|
   | 0x4026a2 <main + 50> movq $ 0x402510,0x410(%rsp)|
   + ------------------------------------------------- -------------------------- +
子进程21518输入:主线:?? 电脑:0x402670
(gdb)文件/ opt / j64-602 / bin / jconsole
从/ opt / j64-602 / bin / jconsole ...中读取符号。
(未找到调试符号)...完成。
(GDB)布局ASM
(gdb)开始
(gdb)

26

display/i $pc在使用stepiR Samuel Klatchko的答案中已经建议的方法之前,您可以在这里执行最有用的操作。这告诉gdb每次在打印提示之前都要反汇编当前指令。那么您只需继续按Enter即可重复该stepi命令。

(有关更多详细信息,请参见我对另一个问题的回答-该问题的背景不同,但原理相同。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.