Unloading dll throws an Access violation error

1

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.

c++
multithreading
winapi
dll
asked on Stack Overflow Apr 19, 2020 by Alex • edited Apr 19, 2020 by Alex

1 Answer

1

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;
}
answered on Stack Overflow Apr 19, 2020 by RbMm • edited Apr 20, 2020 by RbMm

User contributions licensed under CC BY-SA 3.0