Выгрузка dll выдает ошибку нарушения доступа - PullRequest
2 голосов
/ 20 апреля 2020

Итак, у меня есть эта 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, затем мы создаем mainthread, который создаст поток, вызывающий функцию ejectThread, которая должна выгружать dll, используя myhModule и метод FreeLibraryAndExitThread при нажатии клавиши VK_DELETE.

Шаги и возникшие ошибки :

Поэтому я внедряю свою dll в процесс с помощью инжектора, затем, если нажать клавишу Delete, она выгружает dll, однако я получаю ошибка нарушения прав доступа, сообщающая, что я не могу получить доступ к процессу в ячейке памяти.

Ошибка :

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

Что я сделал не так, почему он выбрасывает access violation ошибка?

Заранее спасибо.

1 Ответ

1 голос
/ 20 апреля 2020

при создании потока из 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, но выйдите из MainThread с FreeLibraryAndExitThread((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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...