首页 文章

无法卸载注入的DLL

提问于
浏览
1

我've written a dll in C which I' m通过 CreateRemoteThread() 注入C控制台程序 .

C程序只需调用 Sleep(INFINITE) ,基本上充当注入的dll的主机 .

这是DllMain:

HINSTANCE thisDllHandle = NULL;

BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD entryReason, void *impLoad)
{
    switch (entryReason)
    {
        case DLL_PROCESS_ATTACH:
        {
            thisDllHandle = hInstance;
            HANDLE thread = (HANDLE)_beginthreadex(NULL, 0, Boss, NULL, 0, NULL);
            if (thread) CloseHandle(thread);
        }
    }
    return TRUE;
}

通过 CreateRemoteThread() 创建的线程然后返回,我的Boss线程是运行此dll代码的唯一线程 .

如果我然后告诉Boss退出,清理后调用 FreeLibraryAndExitThread(thisDllHandle, 0); - 线程退出但dll仍然在我的主机进程中加载 .

使用Brandon在here的答案中的想法,我让主程序告诉我加载了哪些模块并显示模块的 GlblcntUsageProccntUsage . 注入dll后,计数为1.在 FreeLibraryAndExitThread() 之后,计数为零 - 但仍然加载了dll!为什么?

顺便说一下,如果我改为调用 FreeLibrary(thisDllHandle) ,主机程序崩溃(如预期的那样),但dll会被卸载 .

EDIT

总结一下我要做的事情:我试图通过创建一个加载我的dll的远程线程在远程进程中注入一个dll;该DLL生成另一个运行相同dll代码的线程,并且原始线程退出;然后我想要该线程卸载DLL并退出 .

虽然试图减少代码以便发布它以响应@David Heffernan的评论,我设法让它工作 - 通过在调用 FreeLibraryAndExitThread 之前让退出的线程调用 FreeLibrary . 但是我真的很了解这些东西 . 我不是很直白:

  • 获取远程进程的句柄 .

  • 在自己的kernel32模块中获取 LoadLibraryW 的地址 .

  • 在远程进程中分配内存,将[dll的路径]写入所述内存 .

  • 在远程进程句柄上调用 CreateRemoteThread ,将步骤2中的地址作为起始地址传入,将步骤3中的地址作为参数传入 .

这会导致远程进程中的线程使用 LoadLibraryW 加载我的dll . 当我的Dll被加载时,它启动一个新线程(参见前面的DllMain代码),它在我的dll中运行一些其他函数(这个其他函数中的内容不重要 - 我可以让它睡10秒然后调用 FreeLibraryAndExitThread ,然后行为是一样的) . 我远程创建的原始线程在LoadLibraryW返回时死亡 . 所以现在只有一个线程运行我的dll代码 .

当该线程调用 FreeLibraryAndExitThread 时,我希望我的dll从远程进程中卸载,因为该线程已释放库并退出 . 但是dll仍然被加载,并且只有释放它两次它才会卸载 .

1 回答

  • 1

    因为你在一个注入的DllMain函数中,并且由于你没有通过调用_endthreadex()函数退出线程,所以你应该使用CreateThread()而不是_beginthreadex()来启动新线程 . 避免使用任何C运行时库函数也是明智之举,特别是如果您无法确保C库与目标进程的C库匹配 .

    [究竟为什么以及在什么情况下运行时库以所描述的方式表现的行为对我来说并不清楚,但OP报告说使用CreateThread()纠正了问题 . 我最好的猜测是它与_onexit()支持有关 .

相关问题