You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在GDB中可执行栈上代码,外部运行段错误的原因及排查方法

栈代码执行问题排查与无GDB调试方案

为什么GDB里能跑,直接运行就Segfault?

这大概率是两个核心因素在搞鬼:地址空间布局随机化(ASLR) 和 栈执行权限(NX位),给你拆解清楚:

1. ASLR是最常见的元凶

Ubuntu 16.04默认开启ASLR,每次启动程序时,栈、堆、动态库的加载地址都会随机变化。但GDB默认会禁用ASLR(set disable-randomization默认是on),所以你调试时栈地址是固定的,计算的跳转地址完全匹配栈上代码的位置。但直接运行时,栈地址变了,你输入的跳转地址指向了无效内存,自然触发Segmentation Fault。

你可以先临时关闭ASLR验证这个猜想:

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

再运行二进制文件,如果能成功执行栈上代码,那ASLR就是罪魁祸首。

2. 栈执行权限的验证

你用了execstack -s但没效果?先检查二进制的栈权限是否真的被修改:

readelf -l your_binary | grep GNU_STACK

如果输出里的Flags是RWE(Read-Write-Execute),说明栈已设为可执行;如果是RW,那execstack可能没生效(比如二进制本身没有PT_GNU_STACK段,需要重新编译或用底层工具修改)。

Ubuntu 16.04默认没开PaX这类会覆盖execstack设置的安全机制,所以这个概率较低。

无需依赖GDB的调试方法

给你几个实用的工具和技巧,不用GDB也能排查问题:

  • 用strace追踪系统调用:
    运行strace ./your_binary,可以看到程序崩溃前的所有系统调用,重点看最后几条——如果是内存访问错误,会显示SIGSEGV对应的地址,对比你预期的栈地址,就能判断是不是跳转地址错了。

  • 生成核心转储分析崩溃点:
    先开启核心转储:

    ulimit -c unlimited
    

    程序崩溃后会生成core文件,再用gdb ./your_binary core加载转储文件,直接查看崩溃时的寄存器状态(比如$pc指向的地址),不用重新跑程序就能定位问题。

  • 用objdump/readelf分析二进制:

    • objdump -d your_binary:反汇编程序,确认你要覆盖的返回地址位置、漏洞函数的栈布局是否和分析一致。
    • readelf -l your_binary:检查ELF段信息,确认栈权限、加载地址等关键参数。
  • 手动获取运行时栈地址:
    如果程序有输入输出功能,可以构造简单payload,让程序输出栈上某个变量的地址(比如通过格式化字符串漏洞,或漏洞函数里的局部变量地址),拿到当前运行时的栈地址后,就能计算出正确的跳转偏移,避开ASLR的影响。

  • 用ltrace追踪库函数调用:
    如果你的payload涉及调用库函数,ltrace ./your_binary可以看到库函数的调用情况,帮助排查是不是函数参数传递错误导致的崩溃。


内容的提问来源于stack exchange,提问作者Larry B.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:52:35