简体   繁体   English

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

[英]Unloading dll throws an Access violation error

So I have this 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;
}

Explanation :说明

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 when the VK_DELETE key is pressed. 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键时。

Steps and error experienced :经历的步骤和错误

So I'm injecting my dll inside a process with an injector, then if the Delete key is pressed it unloads the dll, however I get an access violation error telling me that I cannot access the process at a memory location.所以我将我的 dll 注入到一个带有注入器的进程中,然后如果按下 Delete 键,它会卸载 dll,但是我收到一个访问冲突错误,告诉我我无法在 ZCD69B4957F0918080229 位置访问该进程。

Error :错误

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

What did I do wrong here, why does it throw an access violation error?我在这里做错了什么,为什么会引发access violation错误?

Thanks in advance.提前致谢。

when you create thread from DLL - of course DLL must not be unloaded while thread running.当您从 DLL 创建线程时 - 当然,在线程运行时不得卸载 DLL。 you need add reference to DLL before create thread.您需要在创建线程之前添加对 DLL 的引用。 this can be done via call GetModuleHandleExW function.这可以通过调用GetModuleHandleExW function 来完成。 when thread is exit - we must free reference to DLL - this is done via FreeLibraryAndExitThread .当线程退出时——我们必须自由引用 DLL——这是通过FreeLibraryAndExitThread完成的。 and this need do for every dll thread.这需要为每个dll 线程做。

so code for create thread in general must be next所以创建线程的代码通常必须是下一个

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

and in the end of thread must be call to并且在线程结束时必须调用

FreeLibraryAndExitThread((HMODULE)&__ImageBase,0);

if you want self unload DLL - create thread direct via CreateThread without call GetModuleHandleExW before it and in the end of thread call FreeLibraryAndExitThread .如果您想自行卸载 DLL - 通过CreateThread直接创建线程,而不在它之前调用GetModuleHandleExW并在线程结束时调用FreeLibraryAndExitThread

with your concrete code you not need EjectThread at all, but exit from MainThread with FreeLibraryAndExitThread((HMODUE)&__ImageBase,0);使用您的具体代码,您根本不需要EjectThread ,而是使用FreeLibraryAndExitThread((HMODUE)&__ImageBase,0);MainThread退出and not call GetModuleHandleExW ( CreateThreadInDLL need if you create several additional threads and can exit from main thread (with DLL unload) without wait on this thread termination)并且不调用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;
}

Quouting RbMm's answer:引用 RbMm 的回答:

when thread is exit - we must free reference to DLL - this is done via FreeLibraryAndExitThread.当线程退出时——我们必须自由引用 DLL——这是通过 FreeLibraryAndExitThread 完成的。 and this need do for every dll thread.这需要为每个 dll 线程做。

I think what happnes, is that your EjectThread actually susccsessfully unloads DLL and exits.我认为发生的事情是,您的EjectThread实际上成功卸载 DLL 并退出。 BUT, you MainThread is still running at this time, So what happens next, it tries to do one of it's function calls and uses memory from DLL that no longer exists.但是,此时您的MainThread仍在运行,所以接下来会发生什么,它尝试执行其中一个 function 调用并使用 DLL 中的 memory 不再存在。 which causes access violation.这会导致访问冲突。 I had same error in my own program.我在自己的程序中遇到了同样的错误。 What you need to do is WaitForSingleObject instead of using timeout of 100 ms.您需要做的是WaitForSingleObject而不是使用 100 毫秒的超时。 Somehow (I'm not sure how) its not enough time for MainThread to exit.不知何故(我不确定如何)它没有足够的时间让MainThread退出。 Maybe because of console?也许是因为控制台?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM