调试器不是答案生成器;它的价值是让关于程序状态的每个假设都可以被验证。
第一次看到程序因为长输入崩溃,很容易直接搜索偏移量工具。更有价值的练习是慢下来:在函数入口、复制前后与返回前分别停住,观察栈指针、基址与内存内容如何变化。
01先画一个最小栈帧
局部缓冲区、保存的基址和返回地址在概念上相邻,但真实布局会受到架构、编译器与优化影响。图只是猜想,反汇编和调试输出才是当前二进制的证据。
break vulnerable
run < input.txt
info registers
disassemble /m vulnerable
x/32gx $rsp02把保护机制也纳入模型
- Stack Canary 在返回前检查关键位置是否被覆盖。
- NX 让数据页默认不可执行。
- ASLR 让关键地址在运行间变化。
- PIE 让主程序本身也能随机化装载。