簡體   English   中英

卸載 dll 會引發訪問沖突錯誤

[英]Unloading dll throws an Access violation error

所以我有這個 dll:

#include <Windows.h>
#include <iostream>

HMODULE myhModule;

DWORD __stdcall EjectThread(LPVOID lpParameter) {
    Sleep(100);
    FreeLibraryAndExitThread(myhModule,0);
}

DWORD WINAPI MainThread(LPVOID param) // our main thread
{
    AllocConsole(); // enables the console
    freopen("CONIN$", "r", stdin); // makes it possible to output to output to console with cout.
    freopen("CONOUT$", "w", stdout);
    while (true) {
        Sleep(100);
        if (GetAsyncKeyState(VK_DELETE) & 1) {
            cout << "[+] Attempting dll unload" << endl;
            Sleep(800);
            break;
        }
    }
    FreeConsole();
    CreateThread(NULL, 0, EjectThread, NULL, 0, 0);
    return false;
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    if(ul_reason_for_call == DLL_PROCESS_ATTACH) {// gets runned when injected
        myhModule = hModule;
        CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MainThread, NULL, 0, 0); // creates our main thread 
        return TRUE;
    }
    return FALSE;
}

說明

When the dll is loaded we are creating an myhModule variable to be able to assign to it the base address of our dll, then we Create a mainthread which will create a thread calling the ejectThread function which should unload the dll using myhModule and the FreeLibraryAndExitThread method當按下VK_DELETE鍵時。

經歷的步驟和錯誤

所以我將我的 dll 注入到一個帶有注入器的進程中,然后如果按下 Delete 鍵,它會卸載 dll,但是我收到一個訪問沖突錯誤,告訴我我無法在 ZCD69B4957F0918080229 位置訪問該進程。

錯誤

Exception thrown at 0x1CD62194 in process.exe: 0xC0000005: Access violation executing location 0x1CD62194.

我在這里做錯了什么,為什么會引發access violation錯誤?

提前致謝。

當您從 DLL 創建線程時 - 當然,在線程運行時不得卸載 DLL。 您需要在創建線程之前添加對 DLL 的引用。 這可以通過調用GetModuleHandleExW function 來完成。 當線程退出時——我們必須自由引用 DLL——這是通過FreeLibraryAndExitThread完成的。 這需要為每個dll 線程做。

所以創建線程的代碼通常必須是下一個

ULONG CreateThreadInDLL(PTHREAD_START_ROUTINE StartAddress, PVOID Parameter, PHANDLE phThread = 0, PDWORD pThreadId = 0)
{
    HMODULE hModule;
    if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (PCWSTR)StartAddress, &hModule))
    {
        if (HANDLE hThread = CreateThread(0, 0, StartAddress, Parameter, 0, pThreadId))
        {
            if (phThread) *phThread = hThread; else CloseHandle(hThread);
            return NOERROR;
        }
        ULONG dwError = GetLastError();
        FreeLibrary(hModule);
        return dwError;
    }

    return GetLastError();
}

並且在線程結束時必須調用

FreeLibraryAndExitThread((HMODULE)&__ImageBase,0);

如果您想自行卸載 DLL - 通過CreateThread直接創建線程,而不在它之前調用GetModuleHandleExW並在線程結束時調用FreeLibraryAndExitThread

使用您的具體代碼,您根本不需要EjectThread ,而是使用FreeLibraryAndExitThread((HMODUE)&__ImageBase,0);MainThread退出並且不調用GetModuleHandleExW (如果您創建幾個額外的線程並且可以從主線程退出(使用 DLL 卸載)而無需等待此線程終止,則需要CreateThreadInDLL

DWORD WINAPI MainThread(LPVOID param) // our main thread
{
    // do something...
    FreeLibraryAndExitThread((HMODULE)&__ImageBase,0);
    return 0; //never executed really
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    if(ul_reason_for_call == DLL_PROCESS_ATTACH) {// gets runned when injected
        myhModule = hModule;
        CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MainThread, NULL, 0, 0); // creates our main thread 
        return TRUE;
    }
    return FALSE;
}

引用 RbMm 的回答:

當線程退出時——我們必須自由引用 DLL——這是通過 FreeLibraryAndExitThread 完成的。 這需要為每個 dll 線程做。

我認為發生的事情是,您的EjectThread實際上成功卸載 DLL 並退出。 但是,此時您的MainThread仍在運行,所以接下來會發生什么,它嘗試執行其中一個 function 調用並使用 DLL 中的 memory 不再存在。 這會導致訪問沖突。 我在自己的程序中遇到了同樣的錯誤。 您需要做的是WaitForSingleObject而不是使用 100 毫秒的超時。 不知何故(我不確定如何)它沒有足夠的時間讓MainThread退出。 也許是因為控制台?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM