Windows C++:深入理解Windows API:用户身份验证、访问令牌获取和权限管理

        

目录

CreateProcessAsUser介绍

函数原型

参数详解 

返回值

使用注意

代码实例

代码解释:

注意事项:

用户身份验证和令牌管理

进程创建和管理

会话和桌面管理

权限和安全

用户身份验证、访问令牌获取和权限管理代码示例

步骤概述

注意事项

总结

CreateProcessAsUser 函数详细解析

相关API

博客撰写

实现远程连接并以不同用户执行功能的程序

总结


        围绕 CreateProcessAsUser 的 API 主要用于创建进程、管理用户会话和权限。以下是与 CreateProcessAsUser 相关的一系列重要 Windows API 函数:

CreateProcessAsUser介绍

  CreateProcessAsUser 是 Windows API 中的一个函数,它允许程序以另一个用户的身份创建一个新进程。这通常用于服务或进程需要以不同于启动该服务或进程的用户的权限执行任务时。使用 CreateProcessAsUser 可以实现高级的权限管理和安全性,特别是在需要精细控制进程权限的情况下。

函数原型

  CreateProcessAsUser 的函数原型如下所示:

BOOL CreateProcessAsUser(HANDLE                hToken,LPCWSTR               lpApplicationName,LPWSTR                lpCommandLine,LPSECURITY_ATTRIBUTES lpProcessAttributes,LPSECURITY_ATTRIBUTES lpThreadAttributes,BOOL                  bInheritHandles,DWORD                 dwCreationFlags,LPVOID                lpEnvironment,LPCWSTR               lpCurrentDirectory,LPSTARTUPINFOW        lpStartupInfo,LPPROCESS_INFORMATION lpProcessInformation
);

参数详解 

  • hToken:用于指定用户令牌的句柄,该令牌代表将要用于新进程的用户。通常,这个令牌是通过登录用户并使用 LogonUserDuplicateTokenEx 函数获取的。

  • lpApplicationName:要执行的模块的名称。这个参数可以为 NULL,如果为 NULL,必须在 lpCommandLine 参数中指定模块。

  • lpCommandLine:命令行字符串。如果 lpApplicationName 是 NULL,lpCommandLine 应该指定要执行的程序的全路径和文件名,以及任何必要的参数。

  • lpProcessAttributeslpThreadAttributes:指向 SECURITY_ATTRIBUTES 结构的指针,这些结构决定了新进程和其主线程的继承属性。如果这些参数为 NULL,那么处理的句柄和线程句柄不可继承。

  • bInheritHandles:如果此参数为 TRUE,每个继承的开放句柄都被新的进程继承。否则,句柄不被继承。

  • dwCreationFlags:控制新进程的优先级类和创建的窗口的显示方式的标志。

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

  • lpCurrentDirectory:新进程的当前目录的路径。如果此参数为 NULL,新进程将继承调用进程的当前目录。

  • lpStartupInfo:指向 STARTUPINFOSTARTUPINFOEX 结构的指针,该结构指定新进程的主窗口特性。

  • lpProcessInformation:指向 PROCESS_INFORMATION 结构的指针,该结构接收新进程的识别信息。

返回值

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

使用注意

  • 使用 CreateProcessAsUser 之前,你必须确保有足够的权限来执行这项操作。这通常意味着你的程序必须以管理员身份运行。

  • 为了成功调用 CreateProcessAsUser,可能需要调整令牌的权限,如 SeAssignPrimaryTokenPrivilegeSeIncreaseQuotaPrivilege

  • 此函数的使用涉及到复杂的权限和安全考虑,因此在使用时应特别注意确保不会引入安全漏洞。

代码实例

        以下是一个使用 CreateProcessAsUser 函数创建新进程的示例代码,展示了如何以特定用户身份启动一个新进程。这个例子中,我们将尝试以特定用户身份启动记事本(Notepad.exe)。请注意,为了成功运行此示例,你需要具有相应的权限和能力来获取用户令牌。

#include <windows.h>
#include <iostream>int main()
{HANDLE hToken = NULL;STARTUPINFO si = {sizeof(si)};PROCESS_INFORMATION pi;LPWSTR pszCommandLine = L"notepad.exe";BOOL bResult = FALSE;// 1. 登录用户 - 假设用户名、密码和域已知// 请替换L"DOMAIN", L"USERNAME", 和 L"PASSWORD"为实际的值if (LogonUser(L"USERNAME", L"DOMAIN", L"PASSWORD", LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken)){// 2. 创建进程 - 使用CreateProcessAsUserZeroMemory(&si, sizeof(STARTUPINFO));si.cb = sizeof(STARTUPINFO);si.lpDesktop = NULL; // 使用默认桌面ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));bResult = CreateProcessAsUser(hToken,           // 用户令牌句柄NULL,             // 应用程序名称pszCommandLine,   // 命令行字符串NULL,             // 进程安全属性NULL,             // 线程安全属性FALSE,            // 句柄继承选项0,                // 创建标志NULL,             // 新环境块NULL,             // 当前目录名&si,              // STARTUPINFO指针&pi               // 接收PROCESS_INFORMATION);if (!bResult){std::cerr << "CreateProcessAsUser failed: " << GetLastError() << std::endl;}else{// 3. 等待进程结束WaitForSingleObject(pi.hProcess, INFINITE);CloseHandle(pi.hProcess);CloseHandle(pi.hThread);}// 4. 关闭令牌句柄CloseHandle(hToken);}else{std::cerr << "LogonUser failed: " << GetLastError() << std::endl;}return bResult ? 0 : -1;
}

 

代码解释:

  • LogonUser:尝试登录用户。这里需要提供有效的用户名、密码和域名。成功后,会得到一个代表用户的令牌。

  • CreateProcessAsUser:以特定用户的身份创建新进程。这里尝试启动 notepad.exe。此函数需要用户令牌、应用程序名称(或命令行)、以及 STARTUPINFO 结构,后者提供了有关新进程的主窗口特性的信息。

  • WaitForSingleObject:等待新创建的进程终止。这确保了主程序会等待记事本程序关闭,之后才继续。

  • CloseHandle:关闭打开的句柄,避免资源泄漏。

注意事项:

  • 在实际使用中,替换 L"DOMAIN", L"USERNAME", 和 L"PASSWORD" 为有效的登录凭据。

  • CreateProcessAsUser 需要足够的权限来执行。确保运行此代码的账户具有相应的权限,或者程序以管理员权限运行。

  • 错误处理在这个示例中非常基本。在生产代码中,应进行更详细的错误检查和处理。

  • 使用 CreateProcessAsUser 时,请注意安全和权限问题,避免安全漏洞。

  CreateProcessAsUser 是一个强大的工具,用于在需要时以不同的用户身份执行进程,但它也需要谨慎使用,以确保应用程序的安全性。

用户身份验证和令牌管理

  • LogonUser:验证用户的用户名和密码,并获取表示该用户的令牌。这通常是获取用于 CreateProcessAsUser 的用户令牌的第一步。

  • DuplicateTokenEx:复制一个访问令牌,可能会修改其权限。这在使用 CreateProcessAsUser 之前,调整令牌权限时非常有用。

  • OpenProcessToken:打开与进程关联的访问令牌。

  • AdjustTokenPrivileges:启用或禁用指定访问令牌的权限。在调用 CreateProcessAsUser 之前,可能需要启用特定的权限。

进程创建和管理

  • CreateProcess:创建一个新进程和其主线程。这个函数创建的进程运行在调用进程的上下文中。

  • CreateProcessWithTokenW:以指定的令牌创建一个新进程。这类似于 CreateProcessAsUser,但有一些不同的使用场景和限制。

  • CreateProcessWithLogonW:使用指定的用户凭证创建一个新进程。这不需要先调用 LogonUser 来获取令牌,但它不能用于创建服务进程。

会话和桌面管理

  • SetTokenInformation:设置访问令牌的信息。这可以用来更改令牌的会话ID,使新进程在特定的会话中启动。

  • CreateDesktop:创建一个新的桌面,新的进程可以在这个独立的桌面上运行,这有助于隔离运行环境。

  • SwitchDesktop:切换输入焦点到不同的桌面。

权限和安全

  • GetTokenInformation:检索有关访问令牌的信息,例如,所属用户、组、权限等。

  • PrivilegeCheck:检查访问令牌是否具有指定的权限。

        这些 API 在复杂的应用程序中常常协同工作,特别是在需要细粒度控制进程权限和用户会话的场景中。使用这些函数时,需要有深入理解的 Windows 安全模型,确保应用程序既满足功能需求,又不会引入安全漏洞。

用户身份验证、访问令牌获取和权限管理代码示例

        实现用户远程连接到Windows并且Windows上的程序需要以不同用户执行不同的功能,通常涉及到用户身份验证、访问令牌获取和权限管理。其中,CreateProcessAsUser 函数是关键。以下是一个简化的示例,展示如何使用 CreateProcessAsUser 来满足这一需求。示例中的程序将以不同的用户身份启动一个新进程,例如,运行一个简单的应用程序或脚本。

步骤概述

  1. 验证用户身份:使用 LogonUser 函数验证远程用户的凭证。
  2. 获取用户令牌:验证成功后,LogonUser 会返回一个令牌,该令牌代表了用户的身份。
  3. 创建新进程:使用 CreateProcessAsUser 函数以获取的用户令牌创建新进程,该进程将以指定用户的身份运行。
#include <windows.h>
#include <iostream>int main() {// 用户凭证LPCWSTR username = L"RemoteUserName";LPCWSTR domain = L"DOMAIN"; // 对于本地用户,可以是 NULL 或 "."LPCWSTR password = L"Password123";LPCWSTR applicationName = L"C:\\Path\\To\\Application.exe"; // 要运行的应用程序// 尝试登录用户HANDLE userToken;BOOL loginSuccess = LogonUser(username,domain,password,LOGON32_LOGON_INTERACTIVE, // 登录类型,根据需求选择LOGON32_PROVIDER_DEFAULT,&userToken);if (!loginSuccess) {std::cerr << "Login failed with error " << GetLastError() << std::endl;return 1;}// 设置启动信息STARTUPINFO si;ZeroMemory(&si, sizeof(si));si.cb = sizeof(si);PROCESS_INFORMATION pi;ZeroMemory(&pi, sizeof(pi));// 创建进程BOOL processCreated = CreateProcessAsUser(userToken,applicationName,    // 要运行的应用程序路径NULL,               // 命令行参数可以放这里NULL,               // 进程安全属性NULL,               // 线程安全属性FALSE,              // 句柄继承选项0,                  // 创建标志NULL,               // 使用调用者的环境块NULL,               // 使用调用者的当前目录&si,                // 指向STARTUPINFO结构&pi);               // 指向PROCESS_INFORMATION结构if (!processCreated) {std::cerr << "CreateProcessAsUser failed with error " << GetLastError() << std::endl;CloseHandle(userToken);return 1;}std::cout << "Process created successfully" << std::endl;// 关闭句柄CloseHandle(userToken);CloseHandle(pi.hProcess);CloseHandle(pi.hThread);return 0;
}

 

注意事项

  • 确保替换 usernamedomainpasswordapplicationName 为实际的值。
  • 根据目标应用程序的不同,可能需要调整 LOGON32_LOGON_INTERACTIVE 和其他参数。
  • 此示例假设您有权限执行 LogonUserCreateProcessAsUser。在某些情况下,可能需要为运行此程序的账户调整本地安全策略,以授予相应的权限。
  • 处理错误和清理资源(如句柄)是非常重要的,以避免资源泄露。

        通过上述步骤和示例代码,你可以实现一个程序,它允许远程用户连接到Windows机器并以不同用户身份执行不同的任务。这种方法在需要临时提权或切换用户上下文执行任务的应用场景中非常有用。

总结

        我们探讨了几个关键主题,包括 CreateProcessAsUser 函数的详细解析、围绕 CreateProcessAsUser 的相关API、如何撰写介绍这些内容的博客,以及如何实现一个特定的需求——即在Windows环境下,远程连接并以不同用户身份执行不同功能的程序。以下是各主题的总结:

CreateProcessAsUser 函数详细解析

  • CreateProcessAsUser 允许以不同用户的身份创建新进程,这在多用户环境和需要特定权限执行任务的场景中非常有用。
  • 函数的参数涵盖了从用户令牌、应用程序名称、命令行参数、安全属性到进程和线程属性等方面。
  • 使用时需注意权限配置,确保调用者拥有足够权限。

相关API

  • 用户身份验证和令牌管理LogonUser, DuplicateTokenEx, OpenProcessToken, AdjustTokenPrivileges
  • 进程创建和管理CreateProcess, CreateProcessWithTokenW, CreateProcessWithLogonW
  • 会话和桌面管理SetTokenInformation, CreateDesktop, SwitchDesktop
  • 权限和安全GetTokenInformation, PrivilegeCheck

博客撰写

  • 提出了博客标题:“深入理解Windows API:从CreateProcessAsUser到权限管理”。
  • 博客内容涵盖了 CreateProcessAsUser 及其相关API的重要性、使用场景、以及如何正确使用这些API以保障安全性和满足高级权限管理需求。

实现远程连接并以不同用户执行功能的程序

  • 提供了一个示例代码,展示如何使用 LogonUser 验证用户凭证,获取用户令牌,然后通过 CreateProcessAsUser 创建新进程以实现不同用户执行不同功能的需求。
  • 示例代码包含了详细的注释,解释了每一步的作用和必要的参数配置。

总结

        通过本次对话,我们深入了解了Windows操作系统中进程管理和权限控制的核心API CreateProcessAsUser 及其相关函数。我们讨论了如何通过这些API实现高级的权限管理和应用程序安全,提供了实用的示例代码,并指导了如何撰写相关内容的博客。这些知识不仅对于深入理解Windows系统的安全模型和进程管理机制至关重要,也为需要在Windows平台上开发复杂、安全性高的应用程序的开发者提供了实用指南。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/720445.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【深度学习笔记】5_5 LeNet

注&#xff1a;本文为《动手学深度学习》开源内容&#xff0c;部分标注了个人理解&#xff0c;仅为个人学习记录&#xff0c;无抄袭搬运意图 5.5 卷积神经网络&#xff08;LeNet&#xff09; 在3.9节&#xff08;多层感知机的从零开始实现&#xff09;里我们构造了一个含单隐藏…

c# 连接oracle 及对应获取数据集

1、数据库配置xml&#xff0c;首先连接成功后会自动创建xml并保存到对应xml&#xff0c;如下 static string ConnPath AppDomain.CurrentDomain.BaseDirectory "ConnOrcle.xml"; 声明xml名称&#xff0c;便于后续写入对应数据库参数 2、创建xml /// <summar…

182基于matlab的半监督极限学习机进行聚类

基于matlab的半监督极限学习机进行聚类&#xff0c;基于流形正则化将 ELM 扩展用于半监督&#xff0c;三聚类结果可视化输出。程序已调通&#xff0c;可直接运行。 182matlab ELM 半监督学习 聚类 模式识别 (xiaohongshu.com)

「滚雪球学Java」:JDBC(章节汇总)

&#x1f3c6;本文收录于「滚雪球学Java」专栏&#xff0c;专业攻坚指数级提升&#xff0c;助你一臂之力&#xff0c;带你早日登顶&#x1f680;&#xff0c;欢迎大家关注&&收藏&#xff01;持续更新中&#xff0c;up&#xff01;up&#xff01;up&#xff01;&#xf…

SpringBoot中实现拦截器和过滤器

1.过滤器和拦截器简述 过滤器Filter和拦截器Interceptor&#xff0c; 在功能方面很类似&#xff0c; 但在具体实现方面差距还是比较大。 1.1 运行顺序不同&#xff1a;Filter →Servlet →Interceptor→Controller&#xff1b;1.2 配置方式不同&#xff1a;Filter在web.xml中…

C# Winform画图绘制圆形

一、因为绘制的圆形灯需要根据不同的状态切换颜色,所以就将圆形灯创建为用户控件 二、圆形灯用户控件 1、创建用户控件UCLight 2、设值用户控件大小(30,30)。放一个label标签,AutoSize为false(不自动调整大小),Dock为Fill(填充),textaglign为居中显示。 private Color R…

微服务架构SpringCloud(2)

热点参数限流 注&#xff1a;热点参数限流默认是对Springmvc资源无效&#xff1b; 隔离和降级 1.开启feign.sentinel.enabletrue 2.FeignClient(fallbackFactory) 3.创建一个类并实现FallbackFactory接口 4.加入依赖 <!--添加Sentienl依赖--><dependency><gro…

C语言如何正确使⽤循环嵌套?

一、问题 循环嵌套的应⽤⾮常⼴泛&#xff0c;如⽆限循环、查找循环、计数循环等&#xff0c;那么如何正确使⽤它呢&#xff1f; 二、解答 正确的循环嵌套模式是这样的&#xff1a;在⼀个循环结构当中包含另外⼀个循环结构&#xff0c;就像玩具套娃⼀样&#xff0c;⼀层套⼀层…

机器学习笔记 大语言模型是如何运作的?一、语料库和N-gram模型

一、语料库 语言模型、ChatGPT和人工智能似乎无处不在。了解大型语言模型(LLM)“背后”发生的事情将是驾驭数字世界的关键。 首先在提示中键入一个单词,然后点击提交。您可以尝试新的提示,并根据需要多次重新生成响应。 这个我们称之为“T&C”的语言模型是在一…

量子效应可以消灭熵

按照热寂论&#xff0c;宇宙最终达到热平衡&#xff0c;死气沉沉&#xff0c;此时熵最大。那么这一切就没有希望了吗&#xff1f; 我于是提出一个想法&#xff1a; 只要有量子效应&#xff0c;经过足够长时间&#xff08;期间无数次的变化&#xff09;&#xff0c;就会再次发…

店匠科技颁布 Shoplazza Awards:品牌出海迎历史性机遇,赋能品牌腾飞

在全球化的今天&#xff0c;中国品牌在全球市场的地位日益显著&#xff0c;品牌意识的提升推动了企业出海战略的全新转型。以全球电商市场发展为例&#xff0c;根据 ecommerceBD 数据&#xff0c;2023 年全球零售电子商务销售额预计 6.3 万亿美元&#xff0c;到 2026 年&#x…

Overload方法的重载

在一个类中&#xff0c;我们可以定义多个方法。但是有一系列方法&#xff0c;他们的功能相似&#xff0c;只是参数不同(参数的个数、顺序、类型不同)&#xff0c;那么在JavaOOP的语法中允许把这一系列方法定义为同名方法&#xff0c;这种方法名相同&#xff0c;但是参数不同的方…

Spring ControllerAdvice:全局异常处理与控制器增强

Spring ControllerAdvice&#xff1a;全局异常处理与控制器增强 在Spring框架中&#xff0c;ControllerAdvice是一个非常重要的注解&#xff0c;它提供了一种机制来全局地处理控制器层的异常&#xff0c;并且能够增强控制器的行为。通过使用ControllerAdvice&#xff0c;我们可…

我们距离AGI还有多远?

关于HBM那份纪要的其他反馈 上篇文章发了一篇HBM纪要小部分内容&#xff08;星球更新了另一部分&#xff09;&#xff0c;收到很多业内大佬们的反馈&#xff0c;包括颗粒计算、封装订单划分等等&#xff0c;以及是不是某通某电的一个专家。其中倒是出现一个非共识的说法&#…

【论文阅读】TensoRF: Tensorial Radiance Fields 张量辐射场

发表于ECCV2022. 论文地址&#xff1a;https://arxiv.org/abs/2203.09517 源码地址&#xff1a;https://github.com/apchenstu/TensoRF 项目地址&#xff1a;https://apchenstu.github.io/TensoRF/ 摘要 本文提出了TensoRF&#xff0c;一种建模和重建辐射场的新方法。不同于Ne…

Python字符串中%d,%.f的用法

在字符串中&#xff0c;我们经常需要改变其中的一些几个字符&#xff0c;比如 第一个d%就是epoch1&#xff0c;会随着epoch的变化而变化。同理&#xff0c;后面的也是。打印出的结果就是 其中&#xff0c;epoch迭代了3次&#xff0c;从0开始。会发现 d%&#xff0c;是整数&…

12-Java享元模式 ( Flyweight Pattern )

Java享元模式 摘要实现范例 享元模式&#xff08;Flyweight Pattern&#xff09;主要用于减少创建对象的数量&#xff0c;以减少内存占用和提高性能 享元模式尝试重用现有的同类对象&#xff0c;如果未找到匹配的对象&#xff0c;则创建新对象 享元模式属于结构型模式&…

复现ConvE遇到问题:spodernet安装不上

问题&#xff1a; (py37) D:\Python\CodeHub\MTL\Siamese_MTL\ConvE>pip install -r requirements.txt Obtaining spodernet from gitgit://github.com/TimDettmers/spodernet.git#eggspodernet (from -r requirements.txt (line 2)) Cloning git://github.com/TimDettmers/…

开发一套小程序所需的费用取决于多个因素

随着移动互联网的发展&#xff0c;小程序已经成为许多企业和个人推广业务和服务的重要工具。 不过&#xff0c;对于很多想要开发小程序的人来说&#xff0c;最大的疑问就是开发一套小程序要花多少钱。 这个问题的答案并不是固定的&#xff0c;因为开发一个小程序的成本取决于几…

字符编码学习目录

字符 兆究竟在中文里表示百万还是万亿&#xff1f; 1分钟理解位、字节、字符之间的区别 1分钟搞清字符和字节的对应关系 1分钟理解什么是字符集 Unicode的表现形式? 什么是字符编码? encode decode作用&#xff0c;以及为什么会出现乱码呢&#xff1f;如何准确检查字符长度&…