简体   繁体   中英

Unloading dll throws an Access violation error

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

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.

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?

Thanks in advance.

when you create thread from DLL - of course DLL must not be unloaded while thread running. you need add reference to DLL before create thread. this can be done via call GetModuleHandleExW function. when thread is exit - we must free reference to DLL - this is done via FreeLibraryAndExitThread . and this need do for every dll thread.

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 .

with your concrete code you not need EjectThread at all, but exit from MainThread with FreeLibraryAndExitThread((HMODUE)&__ImageBase,0);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)

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:

when thread is exit - we must free reference to DLL - this is done via FreeLibraryAndExitThread. and this need do for every dll thread.

I think what happnes, is that your EjectThread actually susccsessfully unloads DLL and exits. 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. 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. Somehow (I'm not sure how) its not enough time for MainThread to exit. Maybe because of console?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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