【学习记录】Week2(六):崩溃复盘——Core Dump 分析与精准定位实操

写在前面:在写 Exploit 的过程中,程序崩溃是家常便饭。段错误往往意味着我们覆盖到了关键地址,但到底覆盖了哪个偏移?返回地址跑飞到了哪里?如果只靠肉眼看报错信息,无异于盲人摸象。今天我们就来学习 PWN 界的“黑匣子”——Core Dump 文件,教你如何在程序坠毁的废墟中秒级定位漏洞偏移。

📑 目录

  1. 什么是 Core Dump?为什么它是 PWN 神器?
  2. 第一步:开启 Core Dump 生成
  3. 第二步:手动分析 Core Dump(GDB 基础)
  4. 终极杀器:Pwntools 自动化偏移定位
  5. Week2 完结感言

1. 什么是 Core Dump?为什么它是 PWN 神器?

当程序发生严重错误(如段错误Segmentation Fault)崩溃时,操作系统会将该进程在崩溃瞬间的内存镜像、寄存器状态、栈信息等全部转储到一个文件中,这就是 Core Dump 文件。

在 PWN 中的作用:
当你发送了一大串不可读的 Payload(比如cyclic生成的偏移字符串)导致程序崩溃时,你不需要知道是第几个字符导致了溢出。只需要查看 Core Dump 文件中崩溃瞬间的RIPRSP寄存器值,就能反推出精确的填充长度!

2. 第一步:开启 Core Dump 生成

出于系统性能考虑,大多数 Linux 发行版默认关闭了 Core Dump 的生成。我们需要手动开启。

命令:

ulimit -c unlimited
  • ulimit -c用于设置 Core 文件的最大大小,unlimited表示不限制。

假设性说明(模拟验证环境):
执行完毕后,你可以通过ulimit -c查看当前设置,终端应输出unlimited。此时,如果你运行一个会段错误的程序,当前目录下通常会生成一个名为corecore.<pid>的文件。

3. 第二步:手动分析 Core Dump(GDB 基础)

假设我们用cyclic 200(生成 200 字节的规律字符串)打爆了一个 64 位程序的栈溢出,生成了core文件。

命令:

gdb ./vuln core

GDB 会自动加载二进制文件和崩溃时的内存镜像,并直接停在崩溃的那一行。

假设性说明(模拟 GDB 输出):
GDB 加载后,终端会显示崩溃原因和寄存器状态:

[New LWP 12345] Core was generated by `./vuln'. Program terminated with signal SIGSEGV, Segmentation fault. #0 0x0000616161616162 in ?? ()

看到这里,关键信息来了!程序试图跳转到0x0000616161616162执行,但这并不是一个合法地址,所以崩溃了。这说明我们成功覆盖了返回地址,且返回地址被填充成了baaa(由于小端序,倒序显示为6161...6261)。

我们在 GDB 中查看寄存器:

pwndbg> info registers rsp rsp 0x616161616163 0x616161616163

此时RSP(栈顶指针)指向的值是caaa

手动计算偏移:
我们打开 Python,使用 pwntools 的cyclic_find函数:

from pwn import * print(hex(cyclic_find(0x616161616162))) # 或者用 nfind 视具体覆盖情况

模拟输出:

0x48

秒出结果!偏移量就是 72(0x48 的十进制)。我们只需要在 Payload 前面填充 72 个字节,就能精准控制返回地址。

4. 终极杀器:Pwntools 自动化偏移定位

手动生成 Core 文件再拖进 GDB 还是太慢了。Pwntools 提供了一个极其优雅的模块corefile,可以在脚本运行崩溃后瞬间完成上述所有分析。

实战脚本模板:

from pwn import * context.binary = './vuln' context.log_level = 'debug' # 1. 启动进程并发送导致崩溃的 cyclic pattern p = process('./vuln') p.sendline(cyclic(200)) # 2. 等待进程崩溃并自动加载 corefile p.wait() core = p.corefile # 3. 提取崩溃时的寄存器值 (以 64 位 RIP 为例) # 如果是 32 位,通常看 EIP crash_addr = core.rsp log.success(f"程序崩溃时的栈顶值为: {hex(crash_addr)}") # 4. 自动计算偏移 offset = cyclic_find(core.rsp & 0xffffffffffffffff) log.success(f"计算得出精准偏移量: {offset}")

假设性说明(模拟脚本运行输出):

[DEBUG] Received 0x1 bytes [*] Process './vuln' stopped with exit code -11 (SIGSEGV) [*] './vuln' core dumped [+] 程序崩溃时的栈顶值为: 0x616161616163 [+] 计算得出精准偏移量: 72

不需要打开 GDB,不需要手动敲命令,一行脚本直接把偏移量吐到屏幕上。这就是自动化的力量!

5. Week2 完结感言

至此,Week2 的全部六大模块宣告完成!
从微观的 ELF 节区、汇编指令,到宏观的 Glibc 版本演进;从信息泄露的 Libc 定位,到对抗反调试与崩溃定位。我们补齐了 PWN 学习中所有关键的底层拼图。

如果说 Week1 是学会了“怎么打”,那么 Week2 就是学会了“打哪里”、“为什么这么打”以及“打坏了怎么修”。

如果 Week2 的系列文章对你的 PWN 学习有帮助,请一键三连支持一下!你的鼓励是我持续更新的动力。我们 Week3 见!🙏