天天看點

Windows Shellcode學習筆記——利用VirtualAlloc繞過DEP

本文講的是<b>Windows Shellcode學習筆記——利用VirtualAlloc繞過DEP</b>,

0x00 前言

接着介紹DEP繞過的另一種方法——利用VirtualAlloc繞過DEP。通過VirtualAlloc函數可以申請一段具有可執行屬性的記憶體,相比于VirtualProtect,傳入VirtualAlloc的四個參數不需要先讀取再指派,可在shellcode中直接指定,結構更簡單。當然,利用Immunity Debugger的mona插件可自動構造利用VirtualAlloc繞過DEP的ROP鍊。

0x01 簡介

本文将要介紹以下内容:

1. 調用VirtualAlloc函數時的Bug及修複

2. 選擇合适的替代指令,修改mona自動生成的rop鍊,實作利用

3. 利用VirtualAlloc繞過DEP時需要考慮的細節,如對shellcode的長度要求

0x02 相關概念

VirtualAlloc:

lpAddress:申請記憶體區域的位址 

dwSize:申請記憶體區域的大小 

flAllocationType:申請記憶體的類型 

flProtect:申請記憶體的通路控制類型

申請成功時函數傳回申請記憶體的起始位址,申請失敗時傳回NULL

0x03 實際測試

測試環境:

項目屬性:

注:

詳細配置方法在上篇文章有說明

同樣是測試memcpy的緩沖器溢出,測試POC如下:

編譯成exe,使用Immunity Debugger打開

使用mona插件自動生成rop鍊,輸入:

檢視rop_chains.txt,會列出可用來關閉DEP的ROP鍊

選擇VirtualAlloc函數,詳情如下:

測試1:

填入上述ROP鍊,接着加上測試的指令:

對應機器碼為0x9059016A

組合後的POC如下:

使用OllyDbg打開,單步跟蹤到VirtualAllocEx()函數入口點

Windows Shellcode學習筆記——利用VirtualAlloc繞過DEP

如圖,檢視傳入的函數參數

按F8單步跟蹤,如圖

Windows Shellcode學習筆記——利用VirtualAlloc繞過DEP

傳回值EAX為0,表示生成失敗

查找原因,根據之前的經驗,猜測是申請記憶體區域過長導緻

測試2:

嘗試修改記憶體大小

申請記憶體區域的起始位址為0x0012FF38,距離目前記憶體頁結束還有200位元組(0x00130000-0x0012FF38)

猜測修改的記憶體長度小于等于200才能滿足條件

Windows Shellcode學習筆記——利用VirtualAlloc繞過DEP

如上圖,将記憶體長度設定為200(0x000000C8)

按F8單步跟蹤,如下圖

Windows Shellcode學習筆記——利用VirtualAlloc繞過DEP

申請成功,函數傳回申請記憶體的起始位址

特别注意的是此處為目前記憶體頁的起始位址:0x0012F000(而不是傳入的記憶體起始位址0x0012FF38)

測試3:

再次測試,将長度設定為201,配置設定記憶體失敗

根據以上測試結果,猜測:VirtualAllocEx()函數無法跨記憶體頁申請記憶體

測試4:

繼續測試, 将長度設定為1,函數傳回目前記憶體頁的起始位址:0x0012F000,并且shellcode成功執行

說明傳入的函數長度對配置設定記憶體沒有影響,但是加上申請記憶體的起始位址後必須小于目前記憶體頁的長度

也就是說,在溢出過程中,通過VirtualAllocEx()函數申請的記憶體大小為固定值

現在,我們通過手動修改棧位址實作了DEP的繞過,下面将尋找合适的替換指令,建構自己的ROP鍊,解決mona自動生成産生的BUG

PUSHAD表示将所有寄存器的值入棧,入棧順序為EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI

跟蹤到PUSHAD,如圖

Windows Shellcode學習筆記——利用VirtualAlloc繞過DEP

EBX存儲記憶體的長度,需要将EBX修改為小于201的值

0x04 查找替代指令,構造ROP鍊

在rop.txt中尋找合适的替代指令

Windows Shellcode學習筆記——利用VirtualAlloc繞過DEP

如上圖,搜尋關鍵詞EBX,找到一條合适的替代指令:

XOR EAX,EAX 會将寄存器EAX的值清零 

POP EBX 會從棧頂取值并指派給EBX

選擇合适的位置,并為EBX指派,需要注意:

該指令将寄存器EAX的值清零,是以需要找到與EAX寄存器值無關的位置

POP EBX會讀取下一條指令的内容,并指派給EBX,是以後面接上EBX的值就好,例如0x00000028, // Set EBX=0x00000028(40)

找到一個合适的位置,放在0x693a7031, // POP EAX // RETN [MSVCR110.dll] 前面

完整shellcode如下:

重新編譯,使用OllyDbg打開,單步跟蹤到VirtualAllocEx()函數入口點

Windows Shellcode學習筆記——利用VirtualAlloc繞過DEP

記憶體長度被修改為0x00000028(40),其他傳入參數正常

繼續運作,進入CALL ESP,shellcode成功執行

0x05 小結

利用VirtualAlloc繞過DEP同利用VirtualProtect繞過DEP一樣,都需要注意記憶體頁長度的限制,無法跨頁修改或者申請記憶體,這就對shellcode的長度提出了要求

當然,正常調用API實作VirtualProtect和VirtualAlloc不會存在跨記憶體頁失敗的問題

mona自動生成的rop鍊可作為參考模闆,結合rop.txt下的替代指令,可構造更合适的ROP鍊

原文釋出時間為:2017年4月2日

本文作者:3gstudent

本文來自雲栖社群合作夥伴嘶吼,了解相關資訊可以關注嘶吼網站。

<a href="http://www.4hou.com/technology/4093.html" target="_blank">原文連結</a>