恢复创建的进程的线程暂停,丢失了线程句柄

时间:2015-12-31 20:44:41

标签: python winapi python-2.x

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

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

所以,问题是:是否有一种更有效的方式来恢复由CREATE_SUSPENDED暂停的进程的执行,如果您拥有的是进程句柄和设施Python 2标准库(包括ctypes,但不是 winapi附加组件)? Vista和更高技术是可以接受的,但XP兼容性是首选。

2 个答案:

答案 0 :(得分:1)

我找到了更快的方法;遗憾的是,它依赖于未记录的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))

在使用其他空闲的Windows 7虚拟机上,使用此技术测量的流程设置开销比使用Toolhelp少大约20%。正如预期的那样,根据Toolhelp的工作原理,系统中存在的线程越多,性能增量就越大 - 无论它们是否与相关程序有任何关系。

鉴于NtResumeProcess及其对应NtSuspendProcess的明显的一般效用,我想知道为什么他们从未被记录并给出了kernel32包装器。它们被少数核心系统DLL和EXE使用,所有这些都是AFAICT,是Windows错误报告机制的一部分(faultrep.dllwerui.dllwerfault.exedwwin.exe等等,并且似乎没有重新公开文档名称下的功能。这些函数似乎不太可能更改它们的语义而不改变它们的名字,但是一个防御性编码的程序应该准备好让它们消失(我想回到工具帮助)。

答案 1 :(得分:-2)

我在这里张贴这个,因为我找到了解决这个问题的东西。我自己正在研究这个问题,我相信我已经找到了解决方案。

我不能给你一个摘录或摘要,因为它太多了,我发现它只是两个小时前。我在这里发布这个给所有其他人,像我一样,寻求一种方法来“轻松”在Windows中生成一个正确的子进程,但是想要执行 cuckoo 。 ;)

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

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

我希望它能帮助别人,希望能帮助我。

编辑:

我想我可以添加更多内容。根据我收集的内容,本文档解释了如何生成一个永不执行的睡眠过程。这样我们就可以正常运行Windows进程。然后它解释了通过使用win32api函数VirtualAllocExWriteProcessMemory,我们可以轻松地分配可执行页面并将机器代码注入其他进程。

然后 - 我认为最好的部分 - 可以更改进程的寄存器,允许程序员将指令指针更改为指向 cuckoo

惊人!