恢复创建的进程的线程挂起,已丢失线程指针

2024-09-24 04:21:58 发布

您现在位置:Python中文网/ 问答频道 /正文

在Windows上,Python(2)的标准库例程^{}允许您为CreateProcess指定任意标志,并且您可以从Popen返回的对象访问新创建进程的进程句柄。但是,新创建进程的初始线程的线程句柄在Popen返回之前由库关闭。在

现在,我需要创建一个挂起的进程(CREATE_SUSPENDED在创建标志中),以便在它有机会执行任何代码之前对其进行操作(具体地说,将其附加到作业对象)。但是,这意味着我需要线程句柄来从挂起中释放进程(使用ResumeThread)。恢复线程句柄的唯一方法是使用“工具帮助”库遍历整个系统上的所有线程(例如,请参见this question and answer)。这是有效的,但我不喜欢。具体地说,我担心每次需要创建进程时对系统上的所有线程进行快照的成本太高了。(较大的应用程序是一个测试套件,使用进程进行隔离;它以每秒几十到几百个的速度创建和销毁进程。)

因此,问题是:如果您所拥有的只是进程句柄和python2标准库的功能(包括ctypes,但是不是winapi插件),是否有一种更有效的方法来恢复由CREATE_SUSPENDED挂起的进程的执行?Vista和更高的技术是可以接受的,但是XP兼容性是首选。在


Tags: 对象方法代码标准进程标志windowscreate
2条回答

我把这个贴在这里,因为我发现了一些可以解决这个问题的东西。我自己也在调查,我相信我已经找到了解决办法。在

我不能给你节选或总结,因为太多了,我两小时前才找到的。我把这个贴在这里是为了其他人,像我一样,想“轻松”在windows中生成一个适当的子进程,但却想执行一个布谷鸟。;)

整个第二章很重要,但具体细节从第12页开始。在

http://lsd-pl.net/winasm.pdf

我希望它能像帮助我一样帮助别人。在

编辑:

我想我可以再加些。根据我收集到的信息,这个文档是否解释了如何产生一个永远不会执行的休眠进程。这样我们就有一个正确设置的windows进程在运行。然后说明通过使用win32api函数VirtualAllocExWriteProcessMemory,我们可以很容易地分配可执行页面并将机器代码注入到另一个进程中。在

然后-在我看来最好的部分-可以更改进程的寄存器,允许程序员将指令指针更改为指向布谷鸟!在

太棒了!在

我发现了一种更快的方法;不幸的是,它依赖于一个没有文档的API,NtResumeProcess。这就像它听起来的那样-接受一个进程句柄,并将ResumeThread的等价物应用于进程中的每个线程。Python/ctypes使用它的代码类似于

import ctypes
from ctypes.wintypes import HANDLE, LONG, ULONG

ntdll = ctypes.WinDLL("ntdll.dll")
RtlNtStatusToDosError = ntdll.RtlNtStatusToDosError
NtResumeProcess = ntdll.NtResumeProcess

def errcheck_ntstatus(status, *etc):
   if status < 0: raise ctypes.WinError(RtlNtStatusToDosError(status))
   return status

RtlNtStatusToDosError.argtypes = (LONG,)
RtlNtStatusToDosError.restype  = ULONG
# RtlNtStatusToDosError cannot fail

NtResumeProcess.argtypes = (HANDLE,)
NtResumeProcess.restype  = LONG
NtResumeProcess.errcheck = errcheck_ntstatus

def resume_subprocess(proc):
    NtResumeProcess(int(proc._handle))

我在一台闲置的windows7虚拟机上测量到,使用这种技术的进程设置开销比使用Toolhelp要少20%。正如所期望的,在Toolhelp的工作方式下,性能增量随着系统上线程的增多而变大,不管它们是否与所讨论的程序有关。在

鉴于NtResumeProcess及其对应的{}的明显的通用性,我想知道为什么它们从未被记录下来,也没有被赋予kernel32包装器。它们被一些核心系统DLL和EXE所使用,所有这些DLL和EXE都是Windows错误报告机制的一部分(faultrep.dllwerui.dllwerfault.exedwwin.exe等)的一部分,并且似乎不会在文档名称下重新公开功能。这些函数似乎不太可能在不更改名称的情况下改变其语义,但应该准备一个防御性编码的程序来让它们消失(我想应该回到toolhelp)。在

相关问题 更多 >