有没有什么工具可以在调试时直观地查看linux中的程序堆栈?

逆向工程 调试 x86 调试器
2021-06-27 06:22:47

堆栈是指存储局部变量、返回地址等的位置。这是由 esp 和 ebp 指向的。

3个回答

您可以使用radare2 中的Visual Panels 轻松查看它这是一个预告片:

在此处输入图片说明

安装

首先,从 git 存储库安装radare2:

$ git clone https://github.com/radare/radare2.git
$ cd radare2
$ ./sys/install.sh

调试

要使用radare2 调试程序,请使用调试标志调用它-d
$ r2 -d /bin/ls

现在程序以调试模式打开。
使用v!以显示可视面板模式。现在您可以看到左侧的组件和右侧的堆栈面板。您可以使用sS相应地进入并跳过使用?查看更多在Visual面板模式命令。

显示堆栈的更多方法

  • pxa @ rsp - 显示带注释的 hexdump
  • pxw @ rsp - 显示十六进制字转储(32位)
  • pxq @ rsp - 显示十六进制四字转储(64 位)
  • ad@r:SP - 分析堆栈数据

要阅读有关radare2 调试的更多信息,建议阅读radare2 书籍,尤其是Basic Debugger Session章节。

您可以使用 gdb,例如让我们看看这个简单的程序

#include <stdio.h>

int main(){
  printf("hello world\n");
  return 0;
}

编译它

gcc -o simple simple.c -g

使用 gdb 运行

gdb ./simple

在主函数中设置断点并运行

(gdb) b main
(gdb) r

现在我们可以查看寄存器内容

(gdb) i r 
rax            0x400526 0x400526
rbx            0x0  0x0
rcx            0x0  0x0
rdx            0x7fffffffe518   0x7fffffffe518
rsi            0x7fffffffe508   0x7fffffffe508
rdi            0x1  0x1
rbp            0x7fffffffe420   0x7fffffffe420
rsp            0x7fffffffe420   0x7fffffffe420
r8             0x4005b0 0x4005b0
r9             0x7ffff7de78e0   0x7ffff7de78e0
r10            0x846    0x846
r11            0x7ffff7a2e740   0x7ffff7a2e740
r12            0x400430 0x400430
r13            0x7fffffffe500   0x7fffffffe500
r14            0x0  0x0
r15            0x0  0x0
rip            0x40052a 0x40052a <main+4>
eflags         0x246    [ PF ZF IF ]
cs             0x33 0x33
ss             0x2b 0x2b
ds             0x0  0x0
es             0x0  0x0
fs             0x0  0x0
gs             0x0  0x0

转储堆栈

    (gdb) x/20x $sp
    0x7fffffffe420: 0x00400540  0x00000000  0xf7a2e830  0x00007fff
    0x7fffffffe430: 0x00000000  0x00000000  0xffffe508  0x00007fff
    0x7fffffffe440: 0xf7ffcca0  0x00000001  0x00400526  0x00000000
    0x7fffffffe450: 0x00000000  0x00000000  0xbbbdddd1  0xdfdea768
    0x7fffffffe460: 0x00400430  0x00000000  0xffffe500  0x00007fff

显示说明

(gdb)  list
1   #include <stdio.h>
2   
3   int main(){
4     printf("hello world\n");
5     return 0;
6   }
7   
8   

(gdb) x/4i $pc
    => 0x40052a <main+4>:   mov    edi,0x4005c4
       0x40052f <main+9>:   call   0x400400 <puts@plt>
       0x400534 <main+14>:  mov    eax,0x0
       0x400539 <main+19>:  pop    rbp

等等 ...

请看一下gef它非常有用并且不断改进。这里有一些来自主要 github 页面的注释:

  1. 完全与操作系统无关,无依赖性:GEF 包含电池,可在 2 秒内安装(与 PwnDBG 不同)。
  2. 快速限制依赖项的数量并优化代码以使命令尽可能快(与 PwnDBG 不同)。
  3. 提供 50 多个命令来彻底改变您在 GDB 中的体验。
  4. 通过为 GDB Python API 提供更易于理解的布局,可轻松扩展以创建其他命令。
  5. 在 Python2 和 Python3 上始终如一地工作。
  6. 围绕架构抽象层构建,因此所有命令都可以在任何 GDB 支持的架构中工作,例如 x86-32/64、ARMv5/6/7、AARCH64、SPARC、MIPS、PowerPC 等(与 PEDA 不同)
  7. 适用于现实生活中的应用程序调试、漏洞利用开发,与 CTF 一样多(与 PEDA 或 PwnDBG 不同)

安装

wget -q -O- https://github.com/hugsy/gef/raw/master/gef.sh | sh