CTF中做Linux下漏洞利用的一些心得

Ox9A82發表於2016-06-04

其實不是很愛搞Linux,但是因為CTF必須要接觸一些,漏洞利用方面也是因為CTF基本都是linux的pwn題目。

基本的題目分類,我認為就下面這三種,這也是常見的型別。

下面就分類來說說

 

0x0.棧溢位

  棧溢位一般都是CTF中,PWN類別的第一題。基本思想就是覆蓋棧中返回地址啦,這個誰都知道。這種題一定會有NX保護,怎麼跳是問題。常見的是leak出一個函式的got表,leak方法題中一定會給出的,然後看看有沒有給出libc。如果有libc就能算system()和/libc/sh的地址了,直接溢位就OK了。如果沒有libc的話,如果能構造一個無限次迴圈的漏洞函式的話,可以使用pwn庫的DynELF函式找出system地址,再想方設法的往一個地方寫個/libc/sh就可以了(因為DynELF沒法洩漏字串的地址)。如果這道題比較簡單的話,出題人會在程式裡呼叫system()函式,這樣你直接跳過去用就可以了。

  基本的思路就是這些,如果不能(不樂意)使用DynELF函式就可以使用ret2dl_resolve方法了,這兩者是差不多的。之前寫過的www.Ox9A82.com/Ox9A82/p/5487275.html

  還有一種就是x64下的棧溢位,因為x64並不是通常的使用棧傳遞引數,而是把引數放在暫存器中傳遞所以不能直接的去佈置引數了。但是,可以有通用的gadgets來用。http://www.Ox9A82.com/Ox9A82/p/5487725.html這個是用來佈置引數加執行,而且可以構成rop鏈。

  另外的是,如果有canary保護的話,可能就不是棧溢位(或者不是要去覆蓋返回地址了),因為canary對於直接的覆蓋返回地址來說是沒辦法繞過的。

總體思路如下:

 

0x1.格式化字串

  格式化字串的題,一般都比棧溢位分值高一檔。格式化字串漏洞找起來應該還是相當的容易的,主要格式化串是否可控即可。對於傳統的格式化字串漏洞來說,只要在格式化串中帶有要進行寫入的目標地址即可,使用%1000x來形成1000字元,使用%4$n來指定棧中的引數即可達到目的。而現在很多人不這麼玩了,很多出題人把格式化串放到堆或是bss段中,這樣你就不能像傳統的那樣去讀取格式化串中的目標地址了,不在棧中你是不可能讀到的。對於這種題目的做法就是要進行兩次漏洞利用,第一次在棧中構造跳板。第二次利用跳板去進行任意地址寫。具體的說就是:第一次:在棧中找一個指向棧裡面的指標(這種指標肯定會有,因為堆疊框架就是這樣的),往這個棧的地方寫入第二次要寫入的地址。第二次:就跟正常利用一樣了,使用前面輸入的那個進行任意地址寫。

  然後要明確的一點是,格式化字串漏洞的本質是任意地址寫。所以引數構造也是一個問題,因為不像棧溢位,棧溢位了引數就構造出來了。任意地址寫引數可能沒地方搞。另外注意一點是:要注意開沒開nx、要注意開沒開nx、要注意開沒開nx。重要的事情說三遍。因為沒開nx的話,幾乎就是明晃晃的說,往我的堆/bss寫shellcode吧,我可以執行。

總體思路:

 

0x2.堆

  對於堆進行考察的題一般都處於壓軸的位置。我個人認為堆的應該分為兩種,即堆的漏洞和模擬堆的漏洞。先說模擬堆的漏洞,這種題並不是真的在考堆的漏洞利用。而且出題人自己利用連結串列去模擬出一個堆來,更恰當的說我認為應該叫連結串列漏洞。這類題的一大特徵就是給出了一個記憶體塊的詳細構造,比如有一個前向指標、一個後向指標(雙連結串列)、有一個放使用者名稱的域、有一個放編號的域等等。這個是在模擬一種堆的管理機制,所以最大的區別在於這個東西它沒有check機制,不像堆一樣有溢位保護機制。這種出法或者有溢位有unlink導致任意地址寫等玩法。

  再來說真正的考察堆漏洞的,因為堆是有溢位保護的,unlink的宏在進行unlink之前會檢查當前的指標合不合法,這個在題中的體現就是有的題會在bss段中存放每個塊的指標,利用這個指標就可以bypass保護機制。然後就是利用方法,這個在之前也寫過,就是去偽造兩個堆塊,利用堆的空塊合併機制。當然了,首先得有堆溢位,沒有溢位你拿什麼去偽造堆塊。偽造的目的是構造如下情況:

在灰色的原堆塊中搞了個新的偽空堆塊出來(注意,是透過堆溢位,溢位下一堆塊頭部實現的構造偽空堆塊)。然後,我們再想辦法去釋放橙色堆塊,就引發了空塊合併機制。

最後談談經驗,不一定對,就是做了幾個題總結出來的。首先堆的題很多情況下不只是一個漏洞,往往有個什麼整數溢位啊棧溢位啊什麼的做輔助利用。然後就是堆的題一般都是標準的選單程式,就是給你個類似於記事本的功能選單,有什麼新建筆記、編輯筆記、刪除筆記、檢視筆記之類的。一般都是先看新建的功能,因為透過新建功能可以看出分配的結構是什麼樣的,和怎麼分配的。而刪除功能往往都是用來進行free的。編輯筆記是經常設定漏洞的出題點。檢視筆記可能會用於leak東西。

 

0x3.End

最後說下除錯,因為用python庫寫exp(如pwn庫和zio庫)時都是打本地的,而且都是自動的,所以除錯起來就很難辦。可以在py中加入raw_input("wait input");來中斷一下,然後用gdb附加。附加方法是gdb attch pid,pid可以用看pid的命令得到,也可以gdb attch `pidof elf檔名`來實現附加到程式上。而且還有一個好處就是脫離偵錯程式後程式不會終止,這是和windows不一樣的地方。但是注意調exp的時候如果python指令碼退出了是會殺掉程式的,所以要保證python指令碼不能提前退出,比如可以在最後加上.interact()函式來防止退出。

個人實在不是太喜歡Linux,所以也都是因為做比賽才來接觸。感覺PWN這個東西積累很重要,套路也很重要。

相關文章