BSides Delhi CTF 2018部分pwn題題解
這個是一個比較基礎的國際賽,做完之後的感覺就是其中有些題目很有價值,可以順便補充一些訊號機制、uaf使用的知識。
canary
這個題目比較簡單,就是一個普通的stack smash並沒有什麼特別的,這裡直接上解題思路了
解題思路
因為開啟了canary,而且flag檔案是載入到了bss段之中,所以可以利用_stackchk_failed函式進行一個flag的洩漏,洩漏方式就是覆蓋arg引數,這個函式就會打印出我們想要的flag了(原始碼的分析可以參考ctfwiki,這裡我就不做過多的分析了)
exp:
from pwn import* p = process('./canary') context.log_level="debug" flag = 0x06010A0 p.recv() payload = 'a'*0x178 + p64(flag) p.sendline(payload) p.interactive()
easypeasy
這是一道利用linux下訊號機制的題目
linux下訊號機制記錄
SIGHUP 1 A 終端掛起或者控制程序終止 SIGINT 2 A 鍵盤中斷(如break鍵被按下) SIGQUIT 3 C 鍵盤的退出鍵被按下 SIGILL 4 C 非法指令 SIGABRT 6 C 由abort(3)發出的退出指令 SIGFPE 8 C 浮點異常 SIGKILL 9 AEF Kill訊號 SIGSEGV 11 C 無效的記憶體引用 SIGPIPE 13 A 管道破裂: 寫一個沒有讀埠的管道 SIGALRM 14 A 由alarm(2)發出的訊號 SIGTERM 15 A 終止訊號 SIGUSR1 30,10,16 A 使用者自定義訊號1 SIGUSR2 31,12,17 A 使用者自定義訊號2 SIGCHLD 20,17,18 B 子程序結束訊號 SIGCONT 19,18,25 程序繼續(曾被停止的程序) SIGSTOP 17,19,23 DEF 終止程序 SIGTSTP 18,20,24 D 控制終端(tty)上按下停止鍵 SIGTTIN 21,21,26 D 後臺程序企圖從控制終端讀 SIGTTOU 22,22,27 D 後臺程序企圖從控制終端寫
這道題要用的就是sigalrm這個機制
signal函式
singal()函式宣告 void (signal(int sig, void (func)(int)))(int) ,第一個引數為要處理的訊號,第二個引數為處理方法
程式功能分析
main函式
其中有一個alarm,設定的時間是30秒,這在後面會用到
child函式
這個函式的第一步先建立啦一個signal訊號函式,在有14訊號的時候就會對其進行返回,並且呼叫hander函式。然後在迴圈中進行賦值,賦給的值會放在bbs段上,如果滿足validatesyscallobj(v0)就會呼叫raise函式給程式返回一個14的訊號,從而呼叫signal函式。接下來我們看一下:validatesyscall
validatesyscallobj函式
可以大概看一眼程式,發現當我們輸入的eax值為: 1,2,3,60時就會退出迴圈,然後進行一個raise函式
hander函式
有一個看起來像是系統呼叫的東西再點進去看看 這裡會把我們的輸入當作引數分別放進暫存器當中,然後執行一個系統呼叫,這裡我們可以利用這個特點,向rax寫入59(sys_execve函式的系統呼叫值),然後佈局一下引數,就可以執行我們的getshell函式啦。
解題思路
一、先佈局bss段的引數,第一個為59(sys_execve函式的系統呼叫值),第一個引數就可以是我們'/bin/sh'這個引數的地址
二、然後等30秒,就會執行alarm然後呼叫hander函式接著坐等shell啦。
exp:
from pwn import *
context.log_level = 'debug'
P = process("./easypeasy")
def set_registers(rax, rdi, rsi, rdx, rcx, r8, r9):
p.sendafter('RAX: ', str(rax) + '\n')
p.sendafter('RDI: ', str(rdi) + '\n')
p.sendafter('RSI: ', str(rsi) + '\n')
p.sendafter('RDX: ', str(rdx) + '\n')
p.sendafter('RCX: ', str(rcx) + '\n')
p.sendafter('R8: ', str(r8) + '\n')
p.sendafter('R9: ', str(r9) + '\n')
set_registers(59,
0x6010A0 + 0x20,0x0,0x0, u64('/bin/ sh\x00'),0,0)
data_bank
題目的名字叫做databank,是一個比較簡單的國際賽的題但是利用這個題可以複習一下uaf關於洩漏地址和改寫mallochook的知識。
程式功能分析
這裡沒有對程式進行去符號的處理還是很舒服的 可以大概知道,有add,edit,delete等常規的操作下面進行一一進行分析
add函式
這裡是讓我們自己輸入index(順序序列),然後自己決定大小,然後對我們的輸入的size有一個check,然後是輸入資料,其中get_inp就只是一個自定義的輸入函式,其中沒有什麼特別這裡就不截圖出來了
edit函式
這是一個對堆內容在次進行編輯的一個函式,其中可能存在uaf的漏洞
delete函式
是一個正常的刪除函式,有一個對Double free的檢查所以並沒有辦法進行Double free但是可以看見也沒有對index的指標進行清空所以存在uaf的漏洞。
view函式
迴圈堆進行輸入
exit函式
正常的退出函式
保護檢視
能開的保護基本是全上了
思路分析
先講幾個主要的保護繞過
pie繞過
首先我們申請一個small bin大小的堆塊,然後free掉,其會自己加入至unsortedbin中,fdnext和fdback都會指向libc,這個時候我們再申請一個合適大小的堆塊再view,就可以打印出地址了。(剛入啃的小白可以自己gdb除錯一下)
RELRO繞過
這個保護導致我們不能成功對got表進行一個寫的操作,但是我們可以利用對mallochook進行一個程式流的控制(ps:mallochook 是一個 libc 上的函式指標,呼叫 malloc 時如果該指標不為空則執行它指向的函式,可以通過寫 malloc_hook 來 getshell)
完整的利用過程
一、先進行資訊洩漏,這個題目比較坑需要申請兩個samll bin然後free掉才能有上圖的效果,但是不論如何可以洩漏就可以啦
二、尋找到malloc_hook位置之上可以利用的一個位置,需要繞過fastbin對size的一個檢查,讀者們可以參考一下2017-0ctf-babyheap對這個的繞過,這裡我就不多寫了。
三、OneGadget的寫入
總結
國際賽裡還是有很多對入坑不久的人很友善的比賽的,不是所有比賽都像hitcon,secon一樣的。。