如何利用Buffer Overflow修改函数指针以调用secret_function?
嘿,这题我熟!这是个非常经典的栈溢出修改函数指针的练习,刚好踩中了你遇到的场景——咱们一步步来拆解怎么做:
首先得搞懂你给出的代码里的栈布局逻辑,这是核心:
在monitor_radiation_levels函数里,你先声明了char buffer[10],接着是void (* function_ptr) () = NULL。在x86架构的栈上(这类练习基本都是32位x86环境),局部变量的布局是:buffer占10字节,紧接着在栈的低地址方向(也就是buffer的“后面”)就是4字节的function_ptr指针变量。而gets(buffer)这个函数完全不检查输入长度,只要你输入的内容超过10字节,多余的字节就会直接覆盖栈上的后续数据——刚好就是咱们要修改的function_ptr!
接下来咱们分步骤操作:
1. 获取secret_function的内存地址
你需要先拿到secret_function在程序里的具体地址,最简单的方法是用调试器(比如gdb):
- 先编译你的程序(记得关闭栈保护,练习环境一般默认关着,或者加编译参数
-fno-stack-protector -z execstack) - 启动gdb加载程序:
gdb ./你的程序名 - 输入命令
print secret_function,会得到类似$1 = {void ()} 0x8048420 <secret_function>的输出,这里的0x8048420就是咱们要的目标地址(每个人的地址可能略有不同,以你调试得到的为准)
2. 构造溢出的输入内容
咱们的目标是:先用10字节的填充数据把buffer填满,接下来的字节刚好覆盖function_ptr为secret_function的地址。
- 填充数据:随便什么字节都行,比如10个'A'(也就是ASCII码0x41),刚好占满10字节的buffer。
- 地址字节:因为x86是小端序(低字节存低地址),所以要把目标地址的字节倒过来写。比如刚才的地址是
0x8048420,拆成4字节就是0x20 0x84 0x04 0x80,所以要按这个顺序放在填充数据后面。
你可以用Python快速生成这个输入,比如:
python -c "print 'A'*10 + '\x20\x84\x04\x80'"
把这个命令的输出直接喂给你的程序就行,或者手动输入(手动的话要注意转义,不如用脚本方便)。
3. 验证效果
当你把构造好的输入传给程序,gets会把10个'A'塞进buffer,然后把后面的4字节写到function_ptr的位置,把它从NULL改成secret_function的地址。接下来程序判断function_ptr不为空,就会调用它,你就能看到那个flag输出了!
一些要注意的细节
- 如果你输入超过10字节但没精准覆盖
function_ptr,就会栈溢出导致段错误(就是你之前遇到的情况),所以一定要算准填充的字节数——10字节刚好填满buffer,多一个都不行,少一个也到不了function_ptr。 - 如果是64位系统,指针是8字节,你需要调整填充后的地址长度,但原理完全一样。
- 要是程序开了栈金丝雀(Stack Canary)这类保护,这个方法就失效了,但既然是 cybersecurity 练习,肯定是关了这些保护的,放心搞。
内容来源于stack exchange

