createemotethread出现ERROR_NOT_ENOUGH_MEMORY错误

CreateRemoteThread failing with ERROR_NOT_ENOUGH_MEMORY

本文关键字:MEMORY 错误 ENOUGH NOT ERROR createemotethread 出现      更新时间:2023-10-16

这是一个很奇怪的问题,但是,我相信,这是一个很好的话题。

介绍:

我有一个用c#编写的服务,它调用我的c++库。C++库通过WinExec执行一些第三方软件。

第三方软件通过CreateRemoteThread注入DLL。我没有这个软件的源文件。

我有两台pc - Win2008和Win10。

对于Win10 -这个弗兰肯斯坦工作完美,服务运行DLL, DLL运行第三方DLL注入器,DLL注入器注入的东西。

对于Win2008,情况就不同了。如果我运行3rdparty DLL注入器从CMD -它的工作完美无缺。但是如果我运行service - Injector返回,他会从CreateRemoteThread得到ERROR_NOT_ENOUGH_MEMORY。

服务从LocalService帐户工作,在Windows 10上一切正常。我正在寻找可能的想法线索,为什么服务有问题(记住,CMD工作得很好),只适用于Windows 2008。

这个问题可能与跨权限级别创建远程线程有关,如下文所述:

向Win32特权进程注入代码

在XP SP2和更高版本(2003,Vista)中,一些新的安全措施会阻止传统的CreateRemoteThread()函数正常工作。您应该能够打开进程,在其堆上分配内存,并将数据写入分配的区域,但是当尝试调用远程线程时,它将以ERROR_NOT_ENOUGH_MEMORY失败。

对于XP SP2,我做了一点调试,发现在CreateRemoteThread()中,有一个对ZwCreateThread()的调用,这是从ntdll.dll导出的。调用是在指定线程应该挂起启动时进行的,这是正确的,但是在调用ZwResumeThread()之前,仍然在CreateRemoteThread()中,对CsrClientCallServer()的调用失败并最终导致错误消息。

文章解释了在不同版本的Windows上注入远程线程以避免错误的一些不同方法,并以以下结论结束:

在这一点上,我们可以成功地在所有目标平台上的特权进程中执行远程线程,但是正如前面提到的,它相当混乱。我们使用了三个不同的,大部分未记录的函数,并根据操作系统版本自动检测使用哪一个。

更好的解决方案是创建一个二级程序,将一个服务对象(你的注入器程序)添加到目标系统上的服务控制管理器数据库中。由于您是管理员(无论如何都是必需的),因此您将能够添加这些条目并启动服务。这将使注入器程序能够以不同于普通代码的访问权限运行,并且传统的CreateRemoteThread()将在Windows 2000、所有XP和2003/Vista上正常工作。用于添加和控制服务的API函数由MSDN记录,并在所有平台上保持一致。

因此,我们学到的是,我们可以使用许多不同的函数来将代码注入特权远程进程,包括XP SP2上的RtlCreateUserThread()和Vista上的NtCreateThreadEx(),但最佳方法是安装一个临时服务,并允许CreateRemoteThread()作为单个API来完成所有平台的任务。

当然,这些都不重要,因为你没有注入器的源代码,因此无法改变它的工作方式。

同样,您也不能跨会话边界创建远程线程。在服务中调用WinExec()将会在与该服务相同的会话(即会话0)中运行注入器进程。如果它试图注入到正在用户会话中运行的进程中,那么这将永远不起作用。这也解释了为什么从CMD运行注入器是有效的,如果CMD与被注入的进程运行在同一个会话中。

我今天遇到了同样的问题,这似乎是问题-

在Windows 8之前,终端服务通过设计隔离每个终端会话。因此,如果目标进程与调用进程处于不同的会话中,则CreateRemoteThread会失败。

这解释了为什么你的代码可以在Windows 10上运行,而不能在Windows 7/2008上运行。

来源:https://msdn.microsoft.com/en-us/library/windows/desktop/dd405484 (v = vs.85) . aspx

相关文章: