Windows 过程创立过程
一、过程创立函数
Windows API 提供了多个创立过程的函数,最简略的是CreateProess()
,该函数创立一个和以后过程具备雷同用户 Token 的过程。
如果想要创立和以后过程具备不同用户 Token 的过程,则须要应用CreateProcessAsUser()
,该函数能够承受一个 Token 句柄作为参数,并创立一个具备该 Token 的过程。
其余创立过程的函数还包含 CreateProcessWithTokenW()
以及 CreateProcessWithLogonW()
(都是advapi.dll
的导出函数)。CreateProcessWithTokenW()
和函数 CreateProcessAsUser()
很类似,然而两者对以后过程 Token 的权限要求不同。CreateProcsssWithTokenW()
须要以后过程中的用户 Token 具备 SE_IMPERSONATE_NAME 权限,CreateProcessWithLogonW()
则须要以后过程中具备 SE_INCREASE_NOT_HELD 权限。
CreateProcessWithLogonW()
是通过用户凭证登录并创立具备对应用户 Token 的过程的便捷形式。
这两个函数都要通过 RPC 来调用位于 Svchost.exe 中的 SecLogon.dll 来实现理论的过程创立。SecLogon 调用位于外部的 SLrCreatePrcoessWithLogonW()
函数,如果该过程顺利进行,最终会调用 CreateProcssAsUser()
函数。
SecLogon 服务被默认配置为手动启动,所以当第一次调用 CreateProcessWithTokenW()
以及 CreateProcessWithLogonW()
时,该服务会被启动。如果该服务启动失败,则这两个函数也无奈执行。罕用的命令runas
,就调用了这两个函数。
用户态创立过程函数调用流程图:
二、过程创立过程
下面所形容的 4 个函数都只能对一个具备的 PE 文件构造的文件(不须要有.exe 拓展)、批处理文件或者 16 位 COM 利用进行解决。
对于除了这三种文件外的其余类型的文件,上述的这些函数不晓得如何依据文件拓展名来定位到能够执行的应用程序 (比方:不能依据.txt 扩大定位到,能够启动 Notepad 来关上该 txt 文件。
然而 Windows Shell 提供了这种定位性能,就是对于函数 ShellExecute()
以及 ShellExecuteEx()
来说,其能够承受一个非可执行文件作为输出,并且能够依据其拓展名以及位于 HKEY_CLASSES_ROOT
中的设置来定位适合的可执行程序来关上这些文件。最初,这两个函数会通过具备适合的命令行参数的 CreateProcess()
函数实现用户须要的用意。
CreateProcess()函数会首先找到咱们指定的可执行文件映像,并创立一个内存区域,稍后会调用其余函数将该文件映像映射到过程的地址空间中。此外,当然,依据不同的文件映像名和参数,该函数还会启动其余程序来反对指定文件类型的运行,并从新执行 CreateProcess()函数。
之后,如上图所述,CreateProcess()
函数会调用 CreateProcessInternel()
。该函数实现创立一个用户模式过程的理论工作。
-->CreateProcessInternel()首先会对传入的参数进行一些判断,并将参数或者构造体中的 ANSI 格局的字符串转化为 Unicode 字符串.
--> 再做一些初始化和判断后,会调用 NtOpenFile()失去映像文件句柄,并调用 NtCreateSection()来失去内存区句柄,即咱们所说的过程用户空间的虚拟地址空间会在这一步实现创立。--> 接着会调用 BaseplsProcessAllowed()函数来判断应用程序是否在受权文件列表中,该函数通过调用 NtOpenKey()函数关上注册表的 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Option 键
--> 失去过程对应的内存区对象句柄后,调用 NtQuerySection()函数,返回失去的节的根本信息(基址、大小、属性)
--> 而后对映像文件信息的有效性进行判断,判断是否蕴含 DEBUG_PROCESS 或者 DEBUG_ONLY_THIS_PROCESS,查看机器类型、子系统版本号、控制台、GUI 等,并通过 BaseIsImageVersionOk()判断镜像文件版本是否非法。--> 如果创立标记中蕴含 DEBUG_PROCESS 或者 DEBUG_ONLY_THIS_PROCESS(即以后处于调试模式中),就加载 advapi32.dl 并获取 CreateProcessAsSecure()函数的地址。--> 而后调用 BaseFormatObjectAttrubutes()将平安属性构造 (对于过程平安、权限方面的信息) 格局为 NT 对象属性构造(失去了对象属性)。--> 接着调用_DbgUiConnectToDbg()实现通过调用 NtCreateDebugObject()函数来创立调试对象,调用 DbgUiGetThreadObject()来取得调试对象。
而最终,CreateProcessInternel()
会调用位于 NTdll.dll 中的 NtCreateUserProcess()
来转换到位于内核模式的执行体模块中的同名函数中,实现过程创立过程内核局部的行为。
此外,内核中的 执行体模块还反对 必须绕过 Windows API 的过程 的创立。例如:native processes,minimal processes,以及 Pico processes。
像 Smss(the Session Manager) 就是一个 native process,其 间接被内核创立,显然不会应用 CreateProcess()
接口,而是间接调用进入执行体模块的 NtCreateUserProcess()
函数中 。同样的,当 Smss 创立 Autochk(检测磁盘组件) 或者 Csrss (Windows subsystem process) 时,Windows API 也是不可用的。此外,native processes 也不能作为 Windows 应用程序 被创立,因为CreatePrcoessInternel()
会回绝具备 native subsysem 映像类型的内存映像 。而为了加重上诉的复杂性 Ntdll.dll 中存在一个封装于NtCreateUserProcess()
的函数RtlCreateUserProcess()
。
对于一些 内核模式的过程 ,比方 System process 以及 Memory Compression processes(minimal processes) 以及被 Windows Subsystem for Linux 治理的 Pico procsses。这些过程的创立通过调用NtCreateProcessEx()
函数 (仅仅能被内核态过程调用) 实现。
对于被 Pico providers 治理的过程,在创立时,Pico providers 会调用一个帮忙函数 PspCreatePicoProcess()
,该函数不仅能够创立 minimal process,也会初始化 Pico provider 上下文环境。该函数并未导出,仅仅可能被 Pico providers 通过其非凡接口调用。
最初,尽管 NtCreateProcessEx()
以及函数 NtCreateUserProcess()
是不同的零碎调用,但这两个函数 最初会调用雷同的外部子例程 [PspAllocateProcess() 以及 PspInsertProcess()
] 来实现创立过程的工作。并且,所有的你能举进去的创立过程的形式,从 WMI Powershell cmdlet 到 内核驱动,都会在这两个函数处终止。
三、参考
1. 链接:
郑瀚 Andrew_Hann
2. 书籍
Windows Internals 7th Edition Part 1