CreateProcessAsUser「建议收藏」

CreateProcessAsUser「建议收藏」该CreateProcessAsUser函数创建一个新的进程及其主线程

该CreateProcessAsUser函数创建一个新的进程及其主线程。新进程然后执行指定的可执行文件。该CreateProcessAsUser功能类似的CreateProcess函数,除了新进程运行在由hToken参数表示的用户的安全上下文中。默认情况下,新进程是非交互式的,即它运行在不可见且无法接收用户输入的桌面上。此外,默认情况下,新进程继承调用进程的环境,而不是与指定用户关联的环境。

BOOL CreateProcessAsUser(

HANDLE hToken ,// 处理代表登录用户的令牌
LPCTSTR lpApplicationName ,// 指向可执行模块名称的指针
LPTSTR lpCommandLine ,// 指向命令行字符串的指针
LPSECURITY_ATTRIBUTES lpProcessAttributes ,// 指向进程安全属性的指针
LPSECURITY_ATTRIBUTES lpThreadAttributes ,// 指向线程安全属性的指针
BOOL bInheritHandles ,// 新进程继承句柄
DWORD dwCreationFlags ,// 创建标志
LPVOID lpEnvironment ,// 指向新环境块的指针
LPCTSTR lpCurrentDirectory ,// 指向当前目录名的指针
LPSTARTUPINFO lpStartupInfo ,// 指向 STARTUPINFO 的指针
LPPROCESS_INFORMATION lpProcessInformation// 指向 PROCESS_INFORMATION 的指针
);

参数

hToken

处理代表用户的主要hToken。由hToken表示的用户必须具有对lpApplicationNamelpCommandLine参数指定的应用程序的读取和执行访问权限。

如果您的进程具有 SE_TCB_NAME 权限,它可以调用LogonUser 函数来获取代表指定用户的主要hToken

或者,您可以调用DuplicateTokenEx函数将模拟hToken转换为主要hToken。这允许模拟客户端的服务器应用程序创建具有客户端安全上下文的进程。

的的其它参数CreateProcessAsUser函数表现就像的类似参数的CreateProcess 功能。

应用名称

指向一个以空字符结尾的字符串,指定要执行的模块的完整路径和文件名。如果指定了部分名称,则默认使用当前驱动器和当前目录。如果此参数为 NULL,则模块名称必须是lpCommandLine字符串中的第一个以空格分隔的标记。指定的模块可以是基于 Win32 的应用程序,也可以是其他类型的模块(例如,MS-DOS 或 OS/2),前提是本地计算机上有适当的子系统。

lp命令行

指向一个以空字符结尾的字符串,指定要执行的应用程序的命令行。如果此参数为 NULL,则lpApplicationName字符串用作命令行。如果lpApplicationNamelpCommandLine都不为 NULL,则lpApplicationName指定要执行的模块,lpCommandLine用作命令行。新进程可以使用GetCommandLine检索整个命令行;或 C 运行时进程可以使用argc / argv机制。

如果lpApplicationName为 NULL,则命令行的第一个以空格分隔的标记指定模块名称。如果文件名不包含扩展名,则假定为 .EXE。如果文件名以句点 (.) 结尾且没有扩展名,或者文件名包含路径,则不会附加 .EXE。如果文件名不包含目录路径,Windows 将按以下顺序搜索可执行文件:

  1. 应用程序加载的目录。

  2. 当前目录。

  3. 32 位 Windows 系统目录。使用GetSystemDirectory函数获取该目录的路径。该目录的名称是 SYSTEM32。

  4. 16 位 Windows 系统目录。没有Win32函数获取这个目录的路径,而是搜索了。此目录的名称是 SYSTEM。

  5. Windows 目录。使用GetWindowsDirectory 函数来获取这个目录的路径。

  6. PATH 环境变量中列出的目录。

如果要创建的进程是基于 MS-DOS

或 16 位 Windows 的应用程序,lpCommandLine应该是一个完整的命令行,其中第一个元素是应用程序名称。因为这也适用于基于 Win32 的应用程序,所以它是设置lpCommandLine的最可靠的方法。

lpProcessAttributes

指向SECURITY_ATTRIBUTES 的指针为新进程指定安全描述符并确定子进程是否可以继承返回的句柄的结构。如果lpProcessAttributes为 NULL,则进程获得一个默认的安全描述符并且句柄不能被继承。

lpThread属性

指向SECURITY_ATTRIBUTES 的指针为新进程指定安全描述符并确定子进程是否可以继承返回的句柄的结构。如果lpThreadAttributes为 NULL,则线程获得一个默认的安全描述符并且句柄不能被继承。

bInheritHandles

指示新进程是否从调用进程继承句柄。如果为 TRUE,则调用进程中的每个可继承打开句柄都由新进程继承。继承的句柄与原始句柄具有相同的值和访问权限。

dwCreationFlags

指定控制优先级类和进程创建的附加标志。可以以任意组合指定以下创建标志,除非另有说明:

价值意义
CREATE_DEFAULT_ERROR_MODE
新进程不继承调用进程的错误模式。相反,CreateProcessAsUser为新进程提供当前默认错误模式。应用程序通过调用SetErrorMode设置当前默认错误模式.
此标志对于在禁用硬错误的情况下运行的多线程 shell 应用程序特别有用。 CreateProcessAsUser
的默认行为是新进程继承调用者的错误模式。设置此标志会更改默认行为。
CREATE_NEW_CONSOLE
新进程有一个新的控制台,而不是继承父级的控制台。此标志不能与 DETACHED_PROCESS 标志一起使用。
CREATE_NEW_PROCESS_GROUP
新进程是新进程组的根进程。进程组包括作为此根进程的后代的所有进程。新进程组的进程标识与lpProcessInformation参数中返回的进程标识相同。GenerateConsoleCtrlEvent使用进程组 启用向一组控制台进程发送 CTRL+C 或 CTRL+BREAK 信号的功能。
CREATE_SEPARATE_WOW_VDM
此标志仅在启动 16 位 Windows 程序时有效。如果设置,新进程将在私有虚拟 DOS 机 (VDM) 中运行。默认情况下,所有 16 位 Windows 程序都在单个共享 VDM 中运行。单独运行的好处是崩溃只会杀死单个 VDM;在不同 VDM 中运行的任何其他程序继续正常运行。此外,在单独的 VDM 中运行的 16 位 Windows 应用程序具有单独的输入队列。这意味着,如果一个应用程序暂时挂起,单独 VDM 中的应用程序将继续接收输入。
CREATE_SUSPENDED
新进程的主线程创建时处于挂起状态,直到ResumeThread才运行 函数被调用。
CREATE_UNICODE_ENVIRONMENT
如果设置,lpEnvironment指向的环境块使用 Unicode 字符。如果清除,则环境块使用 ANSI 字符。
DEBUG_PROCESS
如果设置,则调用进程被视为调试器,新进程是被调试的进程。系统将在被调试进程中发生的所有调试事件通知调试器。
DEBUG_ONLY_THIS_PROCESS
如果未设置并且正在调试调用进程,则新进程将成为调用进程的调试器正在调试的另一个进程。如果调用进程不是正在调试的进程,则不会发生与调试相关的操作。
DETACHED_PROCESS
对于控制台进程,新进程无权访问父进程的控制台。新进程可以调用AllocConsole稍后再创建一个新的控制台。此标志不能与 CREATE_NEW_CONSOLE 标志一起使用。

dwCreationFlags参数还控制新进程的优先级,这是在确定进程的线程调度优先级使用。如果没有指定以下优先级类标志,则优先级类默认为NORMAL_PRIORITY_CLASS ,除非创建进程的优先级类是IDLE_PRIORITY_CLASS。在这种情况下,子进程的默认优先级类是IDLE_PRIORITY_CLASS。可以指定以下标志之一:

优先意义
HIGH_PRIORITY_CLASS表示执行时间关键任务的进程必须立即执行才能正确运行。高优先级进程的线程抢占普通优先级或空闲优先级进程的线程。一个例子是 Windows 任务列表,它必须在用户调用时快速响应,而不管操作系统的负载如何。使用高优先级类时要格外小心,因为高优先级类 CPU 密集型应用程序几乎可以使用所有可用周期。
IDLE_PRIORITY_CLASS表示一个进程,其线程仅在系统空闲时运行,并被运行在更高优先级类中的任何进程的线程抢占。一个例子是屏幕保护程序。空闲优先级类由子进程继承。
NORMAL_PRIORITY_CLASS表示没有特殊调度需求的正常进程。
REALTIME_PRIORITY_CLASS表示具有最高优先级的进程。实时优先级进程的线程抢占所有其他进程的线程,包括执行重要任务的操作系统进程。例如,执行时间超过很短时间间隔的实时进程可能会导致磁盘缓存不刷新或导致鼠标无响应。

lp环境

指向新进程的环境块。如果此参数为 NULL,则新进程使用调用进程的环境。

环境块由空终止字符串的空终止块组成。每个字符串的格式如下:

名称=值

因为等号用作分隔符,所以不能在环境变量的名称中使用它。

如果应用程序提供环境块,而不是为此参数传递 NULL,则系统驱动器的当前目录信息不会自动传播到新进程。有关这种情况以及如何处理的讨论,请参阅以下备注部分。

环境块可以包含 Unicode 或 ANSI 字符。如果lpEnvironment指向的环境块包含 Unicode 字符,则dwCreationFlags字段的 CREATE_UNICODE_ENVIRONMENT 标志将被设置。如果块包含 ANSI 字符,则该标志将被清除。

请注意,ANSI 环境块由两个零字节终止:一个用于最后一个字符串,另一个用于终止块。Unicode 环境块由四个零字节终止:两个用于最后一个字符串,另外两个用于终止块。

lp当前目录

指向一个以空字符结尾的字符串,该字符串指定新进程的当前驱动器和目录。该字符串必须是包含驱动器号的完整路径和文件名。如果此参数为 NULL,则使用与调用进程相同的当前驱动器和目录创建新进程。此选项主要用于需要启动应用程序并指定其初始驱动器和工作目录的 shell。

启动信息

指向一个STARTUPINFO 指定新进程的主窗口应如何显示的结构。

lp进程信息

指向PROCESS_INFORMATION 接收有关新进程的标识信息的结构。

返回值

如果函数成功,则返回值非零。

如果函数失败,则返回值为零。要获取扩展错误信息,请调用GetLastError.

评论

CreateProcessAsUser功能需要SE_ASSIGNPRIMARYTOKEN_NAME和SE_INCREASE_QUOTA_NAME特权。如果它们尚未启用,则CreateProcessAsUser在调用期间启用它们。

默认情况下,CreateProcessAsUser在桌面不可见且无法接收用户输入的非交互式窗口站上创建新进程。要启用用户与新进程的交互,您必须在STARTUPINFO的lpDesktop成员中指定默认交互式窗口站和桌面的名称“winsta0\default”结构体。此外,在调用CreateProcessAsUser之前,您必须更改默认交互式窗口站和默认桌面的自由访问控制列表 (DACL)。窗口站和桌面的 DACL 必须授予hToken参数代表的用户访问权限。

CreateProcessAsUser不会将指定用户的配置文件加载到 HKEY_USERS 注册表项中。这意味着访问 HKEY_CURRENT_USER 注册表项中的信息可能不会产生与正常交互式登录一致的结果。您有责任在调用CreateProcessAsUser之前将用户的注册表配置单元加载到 HKEY_USERS 中。

如果lpEnvironment参数为 NULL,则新进程继承调用进程的环境。CreateProcessAsUser不会自动修改环境块以包含特定于由hToken表示的用户的环境变量。例如,如果lpEnvironment为 NULL ,则 USERNAME 和 USERDOMAIN 变量是从调用进程继承的。您有责任为新进程准备环境块并在lpEnvironment 中指定它。

CreateProcessAsUser允许您在调用者或目标用户的安全上下文中访问指定的目录和可执行映像。默认情况下,CreateProcessAsUser访问调用者安全上下文中的目录和可执行映像。在这种情况下,如果调用者无权访问目录和可执行映像,则该函数将失败。要使用目标用户的安全上下文访问目录和可执行映像,请在对ImpersonateLoggedOnUser的调用中指定hToken调用CreateProcessAsUser之前的函数。

新进程和新线程句柄是使用完全访问权限(PROCESS_ALL_ACCESS 和 THREAD_ALL_ACCESS)创建的。对于任一句柄,如果未提供安全描述符,则可以在需要该类型对象句柄的任何函数中使用该句柄。如果提供了安全描述符,则在授予访问权限之前,将对句柄的所有后续使用执行访问检查。如果访问检查拒绝访问,则请求进程无法使用句柄来访问进程或线程。

如果lpProcessAttributes参数为 NULL,则将使用hToken参数中引用的用户的默认安全描述符。此安全描述符可能不允许调用者访问,在这种情况下,一旦运行该进程可能不会再次打开。PROCESS_INFORMATION 中返回的句柄结构有效并将继续拥有所有访问权限。对于线程属性也是如此。

在把手PROCESS_INFORMATION必须关闭CloseHandle的 当不再需要它们时。

该进程被分配了一个进程标识符。该标识符在进程终止之前一直有效。它可以用来标识进程,或者在OpenProcess 中指定函数打开进程的句柄。进程中的初始线程也被分配了一个线程标识符。该标识符在线程终止之前一直有效,可用于唯一标识系统内的线程。这些标识符在PROCESS_INFORMATION结构中返回。

lpApplicationNamelpCommandLine字符串中指定应用程序名称时,应用程序名称是否包含文件扩展名无关紧要,但有一个例外:

图片/WIN3200090000.gif文件扩展名为 .COM 的基于MS-DOS或基于 Windows 的应用程序必须包含 . COM 扩展名。

调用线程可以使用WaitForInputIdle函数等待新进程完成其初始化并等待用户输入,而没有输入未决。这对于父进程和子进程之间的同步很有用,因为CreateProcessAsUser无需等待新进程完成其初始化就返回。例如,创建进程会在尝试查找与新进程关联的窗口之前使用WaitForInputIdle

关闭进程的首选方法是使用ExitProcess函数,因为该函数通知所有附加到即将终止的进程的动态链接库 (DLL)。关闭进程的其他方法不会通知附加的 DLL。请注意,当一个线程调用ExitProcess 时,进程的其他线程将被终止,而没有机会执行任何附加代码(包括附加 DLL 的线程终止代码)。

退出进程,退出线程, 创建线程, 创建远程线程和正在启动的进程(作为CreateProcessAsUser调用的结果)在进程内彼此序列化。一次只能发生这些事件之一。这意味着以下限制成立:

  • 在进程启动和 DLL 初始化例程期间,可以创建新线程,但在进程的 DLL 初始化完成之前它们不会开始执行。

  • 一个进程中一次只能有一个线程处于 DLL 初始化或分离例程中。

  • 直到没有线程正在执行 DLL 初始化或分离例程时,ExitProcess函数才会返回。

今天的文章CreateProcessAsUser「建议收藏」分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/79186.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注