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

标签 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 的基地址,然后创建一个主线程,该主线程将创建一个调用jectThread 函数的线程当按下 VK_DELETE 键时,应使用 myhModuleFreeLibraryAndExitThread 方法卸载 dll。

遇到的步骤和错误:

所以我用注入(inject)器将我的 dll 注入(inject)到进程中,然后如果按下删除键,它会卸载 dll,但是我收到访问冲突错误,告诉我无法访问内存位置的进程。

错误:

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

我在这里做错了什么,为什么会抛出访问冲突错误?

提前致谢。

最佳答案

当你从 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;
}

关于c++ - 卸载 dll 会引发访问冲突错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61312902/

相关文章:

c++ - 在不声明成员变量的情况下更改按钮颜色

c++ - 字符串到 float 的转换和格式化

c++ - C++ 中带线程的强力搜索算法的并行化

python - 如果笔记本电脑屏幕关闭,通过 printwindow 获取屏幕截图不会重绘

C++代码到类图

c++ - 如何设计一个 moSTLy 运行 tcl 脚本的 C++ GUI 应用程序

c++ - 多线程中的同步

C++ 在后台读取文件

c++ - 如何在 win32 中更改窗口的背景图像?

windows - 如何以编程方式获取强制密码历史组策略设置?