利用Buffer Overflow调用未触发函数的可行性及地址查找技术咨询
缓冲区溢出POC相关问题
我计划出于演示/教育目的编写一个简单的概念验证(POC)程序,利用缓冲区溢出执行程序中未被正常调用的代码。初始代码如下:
#include <iostream> #include <cstring> void vulnerableFunction(const char* input) { char buffer[10]; strcpy(buffer, input); } void printSomething(){ std::cout << "This should not be executed" << std::endl; } int main() { const char* input = "This is a long string that will cause a buffer overflow"; vulnerableFunction(input); return 0; }
我希望通过输入字符串覆盖EIP寄存器,将其指向printSomething()函数的内存地址以执行该函数。现咨询两个问题:
- 这种实现方式是否可行?
- 我已使用Immunity Debugger分析程序,能够构造字符串精确覆盖EIP且已知偏移量,但尚未找到
printSomething()函数的精确内存地址,请问有哪些方法可以获取该地址?
一、实现方式是否可行
这种实现可行,但需要满足几个前提条件:
- 关闭地址空间布局随机化(ASLR):如果系统开启了ASLR,函数地址会每次运行随机变化,无法固定指向
printSomething。 - 禁用栈保护(Stack Canary):现代编译器默认会开启栈保护机制,检测到栈溢出时会终止程序,编译时需关闭该选项(比如GCC用
-fno-stack-protector参数)。 - 使用32位编译:EIP是32位x86架构的指令指针寄存器,64位架构对应的是RIP,若用64位编译,溢出逻辑和寄存器操作会完全不同。
- 关闭编译器优化:避免编译器将未被调用的
printSomething函数优化掉(比如GCC用-O0参数),同时确保栈布局符合预期。 - 允许栈执行(可选):部分系统默认禁止栈上代码执行,编译时添加
-z execstack参数可避免意外问题(本场景是跳转到已存在的函数,并非执行栈上代码,这一步非强制)。
满足以上条件后,构造足够长的输入字符串覆盖栈上的EIP值为printSomething的地址,即可让程序执行该函数。
二、获取printSomething函数内存地址的方法
1. 在Immunity Debugger中直接查找
- 打开程序后按下
Ctrl+G,在弹出窗口中输入printSomething,直接跳转到函数起始地址; - 如果函数名无法直接搜索,可在反汇编窗口中查找x86函数的特征开头指令(比如
push ebp; mov ebp, esp),结合函数内的cout调用特征定位地址。
2. 利用编译工具的符号表
- 编译时添加调试信息(GCC用
-g参数),用GDB调试:启动GDB后输入info functions,在列表中找到printSomething对应的地址; - 用
nm命令查看可执行文件符号表:执行nm <你的程序文件名> | grep printSomething,直接输出函数地址。
3. 反汇编工具分析
- 使用IDA Pro、Ghidra等反汇编工具打开程序,在函数列表中直接找到
printSomething,查看其起始地址; - 这类工具会自动识别函数边界和符号,定位过程更直观。
4. 临时修改代码打印地址
- 在
main函数中添加一行代码:std::cout << (void*)&printSomething << std::endl;; - 编译运行程序,直接输出
printSomething的内存地址,之后删除该行代码重新编译用于溢出测试。
内容的提问来源于stack exchange,提问作者Flavio
相关产品推荐
相关产品推荐

