繁体   English   中英

如何检查是否在Visual C ++应用程序的第三方DLL中创建了新线程

[英]How to check whether new threads created inside third party DLL in visual c++ application

我目前正在努力验证是否可以从可视c ++应用程序中的代码调用的dll文件中创建新线程。 最好是我想查看资源消耗并在dll内部创建任何线程的情况下调用堆栈。 我需要在非调试模式下运行应用程序时发生这种情况。 你们中有人知道我们如何解决这个问题吗?

让应用程序在其启动代码中挂接CreateThread API,最好在DLL初始化之前。 虽然这是深奥的魔力。 您必须确切地知道自己在做什么。

编辑:如果您要问,您可能不适合该任务。 继续需要您自担风险。

大概的想法是:使用反汇编程序在正在运行的进程中查看CreateThread()的前几个命令。 在主要的exe代码中,修补CreateThread的内存,以将JMP命令插入到自己的蹦床功能中。 在汇编中编写一个蹦床,它将调用您自己的钩子函数,也许从修补部分重复一些命令,然后跳回到CreateThread()的未修补部分。

这不是用于生产-仅用于在自己的计算机上运行具有已知版本的CreateThread的可执行文件,因为这将取决于CreateThread的内容。 在某种程度上,应用程序成为其自己的调试器,但这不是DLL可以轻易注意到的调试器。

要修补进程内存的可执行部分,您可能必须调整内存保护标志,默认情况下它将不可写。

自然,您必须介意这些问题。

另外,您可以修补CreateThread的开头以引发异常(例如INT 3),并使用向量异常处理程序来捕获该异常。 Win32 API函数的开头有一个2字节的NOP,刚好可以打补丁。

编辑:尝试了VEH方法,似乎更干净。 现在,在我的机器上,CreateThread的第一个命令是MOV EDI, EDI实际上是2字节的无操作,非常适合修补。 因此,异常处理程序变为:

LONG NTAPI OnExc(_EXCEPTION_POINTERS* Exc)
{
    if (Exc->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)
    { //Feel free to add an extra check for exception address
      //Just in case there are rogue INT 3's elsewhere

        wprintf(L"Yay, thread created\n");
        //Not a good idea to do I/O from the exception handler :)

        //Continue from the next command after INT 3
        Exc->ContextRecord->Eip++; 
        return EXCEPTION_CONTINUE_EXECUTION;
    }
    else
        return EXCEPTION_CONTINUE_SEARCH;
}

挂钩代码如下:

AddVectoredExceptionHandler(1, OnExc);

HMODULE hKernel32 = GetModuleHandle(L"kernel32.dll");
unsigned char* pCreateThread = (unsigned char*)GetProcAddress(hKernel32, "CreateThread");

//Allow writing to the memory block where CreateThread is
MEMORY_BASIC_INFORMATION mi;
VirtualQuery(pCreateThread, &mi, sizeof mi);
DWORD dw;
VirtualProtect(mi.BaseAddress, mi.RegionSize, PAGE_EXECUTE_READWRITE, &dw);

//Check if the first two bytes are indeed MOV EDI, EDI
if (pCreateThread[0] == 0x8b && pCreateThread[1] == 0xff)
{
    //And patch!
    pCreateThread[0] = 0xcc; //Replace with INT 3 
    pCreateThread[1] = 0x90; //Replace with NOP
}

就这样,着迷了。 可以通过调用_beginthread_beginthreadex随意进行测试-但不能在调试器下进行。 调试器将在异常处理程序执行之前捕获并处理INT 3。

这都是32位代码。 甚至都没有看过Win64的外观。

我没有涉及其他方面的工作。 具体来说,如果所讨论的DLL是静态加载的, 并且在其启动代码中创建了线程, 并且如果该钩子安装在[Win] main()中,则该钩子将无法捕获那些线程。 由于这是您的项目,因此我无法对其进行检查。

增强的另一种途径-如果您想捕获线程创建的结果(例如,线程ID),仅此技术是行不通的。 您不仅需要钩住CreateThread的入口点,还需要钩住出口。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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