在MSDN的“ 过程安全性和访问权限”文章中有一个有趣的评论:
...如果进程A具有访问具有PROCESS_DUP_HANDLE的进程B的句柄,则它可以复制进程B的伪句柄。这将创建对进程B具有最大访问权限的句柄。
如果可以免费将其翻译成俄语,则表示拥有一个具有PROCESS_DUP_HANDLE访问权限的进程的描述符,我们可以使用DuplicateHandle(...)函数来获得该进程具有最大允许访问掩码的描述符。

示范
利用此功能的源代码非常简单:
#include <Windows.h> int wmain(int argc, PWSTR argv[]) { HANDLE ProcessAllAccessHandle; HANDLE ProcessDuplicateHandle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, _wtoi(argv[1])); if (ProcessDuplicateHandle) { if (DuplicateHandle(ProcessDuplicateHandle, GetCurrentProcess(), GetCurrentProcess(), &ProcessAllAccessHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) { CloseHandle(ProcessAllAccessHandle); } CloseHandle(ProcessDuplicateHandle); } return 0; }
作为编译和链接的结果,我们得到了一个测试实用程序,该实用程序将目标进程的标识符(PID)作为参数。 然后,该实用程序将使用PROCESS_DUP_HANDLE权限打开指定的进程。 因此,对于具有正确的PROCESS_DUP_HANDLE (== 0x40)的进程,我们模拟了描述符的可用性的必要条件。
作为演示,我将在WinDbg中跟踪组装的实用程序:
0:000> lsa @$ip 0,3 > 13: if (ProcessDuplicateHandle) 14: { 15: if (DuplicateHandle(ProcessDuplicateHandle, 0:000> !handle @@C++(ProcessDuplicateHandle) 3 Handle 80 Type Process Attributes 0 GrantedAccess 0x40: None DupHandle HandleCount 9 PointerCount 260518
然后 腕部轻弹 通过调用DuplicateHandle (...),我们获得了同一进程的第二个描述符,但具有最大的权限:
0:000> lsa @$ip 0,3 > 23: CloseHandle(ProcessAllAccessHandle); 24: } 25: CloseHandle(ProcessDuplicateHandle); 0:000> !handle @@C++(ProcessAllAccessHandle) 3 Handle 84 Type Process Attributes 0 GrantedAccess 0x1fffff: Delete,ReadControl,WriteDac,WriteOwner,Synch Terminate,CreateThread,,VMOp,VMRead,VMWrite,DupHandle,CreateProcess,SetQuota,SetInfo,QueryInfo,SetPort HandleCount 10 PointerCount 292877
关键点是GrantedAccess值,对于新的描述符,该值是0x1fffff,它对应于PROCESS_ALL_ACCESS 。 不幸的是,WinDbg不会显示目标进程的PID。 但是,要确保已收到所需进程的描述符,您可以通过Process Explorer查看描述符(预先指定调试器的命令行参数中指定的PID):
0:000> dx argv[1] argv[1] : 0x1b7c2e2412c : "21652" [Type: wchar_t *]

在屏幕截图中,该实用程序打开用于运行notepad.exe的描述符。
为什么会这样呢?
首先,因为复制描述符时,如果未扩展对象的访问掩码(并且为我们专门指定了操作标志DUPLICATE_SAME_ACCESS ),则无法验证该进程(将在其中创建复制描述符的进程)可以访问该对象。 仅检查传递给DuplicateHandle(...)函数的进程描述符是否具有允许的访问掩码PROCESS_DUP_HANDLE 。 然后在不检查访问权限的情况下在进程之间复制描述符(我重复:如果新描述符的允许权限掩码不比原始复制的描述符宽)。
然后应该注意,对GetCurrentProcess()的调用返回一个常数,该常数与本出版物一开始所提到的伪描述符(伪句柄)相同。 进程描述符表中实际遗漏了两个带有常量值的伪伪描述符。 但是,所有内核功能都将处理这些描述符(以及进程描述符表中的常用描述符):
NtCurrentProcess(== -1)的值返回GetCurrentProcess()调用。
在特定过程的框架中,此伪描述符表示该过程的对象,其权限为PROCESS_ALL_ACCESS (实际上,存在细微差别,但本文与之无关)。 事实证明,这样的链接指向他自己,但是通过描述符:

也就是说,我们对DuplicateHandle的调用(ProcessDuplicateHandle,GetCurrentProcess(),...)将解释如下:从打开的(目标)进程中,复制值为-1的句柄。 对于目标进程(将描述符存储在ProcessDuplicateHandle变量中的目标进程),值-1将引用具有PROCESS_ALL_ACCESS权限的同一目标进程。 因此,结果,我们获得了具有最大权限的目标进程的描述符。
而不是结尾
我重复一开始的想法:如果某人收到具有PROCESS_DUP_HANDLE权限的进程的描述符,则在Windows安全模型下,他将能够获得同一进程的另一个描述符,但具有PROCESS_ALL_ACCESS权限(并且可以根据自己的意愿执行该进程)
感谢所有阅读该出版物的人。 我邀请所有人参加调查,以了解此类出版物如何对受众产生吸引力/帮助。