ChatGPT解决这个技术问题 Extra ChatGPT

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

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

额外细节:

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

我想另一种选择是生成一个假的内核模块或调试信息文件给 gdb,让它相信这个区域在程序代码中。 gdb 在内核可执行文件本身上运行良好。

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

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

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

e
ephemient

运行 gdbtui 而不是 gdb。或使用 -tui 开关运行 gdb。或者在输入 gdb 后按 Cx Ca。现在您处于 GDB 的 TUI 模式。

输入 layout asm 以创建上部窗口显示组件 - 这将自动跟随您的指令指针,但您也可以在调试时更改框架或滚动。按 Cx s 进入 SingleKey 模式,其中 run continue up down finish 等缩写为单个键,让您可以非常快速地浏览您的程序。

+---------------------------------------------------------------------------+
B+>|0x402670 <main>         push   %r15                                        |
   |0x402672 <main+2>       mov    %edi,%r15d                                  |
   |0x402675 <main+5>       push   %r14                                        |
   |0x402677 <main+7>       push   %r13                                        |
   |0x402679 <main+9>       mov    %rsi,%r13                                   |
   |0x40267c <main+12>      push   %r12                                        |
   |0x40267e <main+14>      push   %rbp                                        |
   |0x40267f <main+15>      push   %rbx                                        |
   |0x402680 <main+16>      sub    $0x438,%rsp                                 |
   |0x402687 <main+23>      mov    (%rsi),%rdi                                 |
   |0x40268a <main+26>      movq   $0x402a10,0x400(%rsp)                       |
   |0x402696 <main+38>      movq   $0x0,0x408(%rsp)                            |
   |0x4026a2 <main+50>      movq   $0x402510,0x410(%rsp)                       |
   +---------------------------------------------------------------------------+
child process 21518 In: main                            Line: ??   PC: 0x402670
(gdb) file /opt/j64-602/bin/jconsole
Reading symbols from /opt/j64-602/bin/jconsole...done.
(no debugging symbols found)...done.
(gdb) layout asm
(gdb) start
(gdb)

R
R Samuel Klatchko

您可以使用 stepinexti(可以缩写为 sini)单步执行您的机器代码。


哇。回想起来,我并没有忘记 stepi。我想我只是假设因为 gdb 没有源代码,所以该步骤将恢复为汇编指令。
注意:您通常不能为汇编程序键入“break main”、“run”。键入“layout asm”、“start”。我是通过阅读下面的消息得到的,但阅读这篇文章的其他人可能没有那么耐心。
@Dmitry start 相当于 tbreak main 后跟 run(注意:tbreak 而不是 break
C
Community

您可以在这里做的最有用的事情是 display/i $pc,然后使用 R Samuel Klatchko 的回答中已经建议的 stepi。这告诉 gdb 在每次打印提示之前反汇编当前指令;然后您可以继续按 Enter 重复 stepi 命令。

(有关详细信息,请参阅 my answer to another question - 该问题的上下文不同,但原理相同。)


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅