卸载DLL会引发访问冲突错误

时间:2020-04-19 23:15:17

标签: c++ multithreading winapi dll

所以我有这个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;
}

说明

在加载dll时,我们正在创建一个myhModule变量,以便能够为其分配dll的基址,然后我们创建一个主线程,该主线程将创建一个调用弹出线程的线程,该线程应卸载按下myhModule键时,使用FreeLibraryAndExitThreadVK_DELETE方法使用dll。

遇到的步骤和错误

因此,我将使用注入器将dll注入到进程内,然后如果按Delete键,它将卸载dll,但是出现访问冲突错误,告诉我无法在内存位置访问该进程。 / p>

错误

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

我在这里做错了什么,为什么会引发access violation错误?

谢谢。

1 个答案:

答案 0 :(得分:1)

从DLL创建线程时-当然,在线程运行时一定不能卸载DLL。您需要在创建线程之前添加对DLL的引用。这可以通过调用GetModuleHandleExW函数来完成。当线程退出时-我们必须自由引用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,而是使用MainThreadFreeLibraryAndExitThread((HMODUE)&__ImageBase,0);退出并且不调用GetModuleHandleExW(如果创建,则CreateThreadInDLL几个其他线程,可以从主线程退出(使用DLL卸载),而无需等待该线程终止)

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;
}