在 Python 脚本中以 Windows 上的不同用户(非管理员)身份运行程序

2024-02-26

使用以下代码:

class ImpersonateWin32Sec(object):

    def __init__(self, domain, username, password):
        self.username = username
        self.password = password
        self.domain = domain
        self.handle = None

    def __enter__(self):
        self.handle = win32security.LogonUser(self.username, self.domain, self.password, win32con.LOGON32_LOGON_INTERACTIVE, win32con.LOGON32_PROVIDER_DEFAULT)
        win32security.ImpersonateLoggedOnUser(self.handle)

    def __exit__(self, *args):
        win32security.RevertToSelf()
        self.handle.Close()

with ImpersonateWin32Sec("domain", "altuser", "password"):
    prc = subprocess.Popen(cmdLine, cwd = "C:\\Temp", stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, env = env, shell = shell, creationflags = CREATE_NO_WINDOW)
    stdOut, stdErr = prc.communicate(timeout = 60)

我正在尝试以不同的用户身份运行程序。它似乎只能部分工作,因为某些命令失败。以下3条命令显示环境的某些部分仍然适用于原始用户:

os.getlogin() # altuser
getpass.getuser() # origuser   --> WRONG!!!
win32api.GetUserName() # altuser

我的代码缺少/有什么问题?我发现一些信息 ImpersonateLoggedOnUser 为用户创建模拟令牌,而不是主令牌?这可能是问题所在吗?如果是,我怎样才能获得主令牌?代码示例将非常感激。

问候, 马丁


最后我找到了如何做到这一点。它相当复杂,我不得不合并几个示例的代码(其中一些是 C 语言)。下面的示例在执行时有效网络服务 or System用户。在用户会话或会话 0 中执行并不重要。

这是代码:

import os
import msvcrt
import win32security
import win32con
import win32pipe
import win32process
import win32api
import win32net
import win32file
import win32event
import win32profile
import win32service


GENERIC_ACCESS = win32con.GENERIC_READ | win32con.GENERIC_WRITE | win32con.GENERIC_EXECUTE | win32con.GENERIC_ALL

WINSTA_ALL = (win32con.WINSTA_ACCESSCLIPBOARD  | win32con.WINSTA_ACCESSGLOBALATOMS | \
win32con.WINSTA_CREATEDESKTOP    | win32con.WINSTA_ENUMDESKTOPS      | \
win32con.WINSTA_ENUMERATE        | win32con.WINSTA_EXITWINDOWS       | \
win32con.WINSTA_READATTRIBUTES   | win32con.WINSTA_READSCREEN        | \
win32con.WINSTA_WRITEATTRIBUTES  | win32con.DELETE                   | \
win32con.READ_CONTROL            | win32con.WRITE_DAC                | \
win32con.WRITE_OWNER)

DESKTOP_ALL = (win32con.DESKTOP_CREATEMENU      | win32con.DESKTOP_CREATEWINDOW  | \
win32con.DESKTOP_ENUMERATE       | win32con.DESKTOP_HOOKCONTROL   | \
win32con.DESKTOP_JOURNALPLAYBACK | win32con.DESKTOP_JOURNALRECORD | \
win32con.DESKTOP_READOBJECTS     | win32con.DESKTOP_SWITCHDESKTOP | \
win32con.DESKTOP_WRITEOBJECTS    | win32con.DELETE                | \
win32con.READ_CONTROL            | win32con.WRITE_DAC             | \
win32con.WRITE_OWNER)


def runAsDomainUser(domainName, userName, password, cmdLine, maxWait):
    # maxWait = Maximum execution time in ms
    userGroupSid = win32security.LookupAccountName(domainName, userName)[0]
    # Login as domain user and create new session
    userToken = win32security.LogonUser(userName, domainName, password,
                                        win32con.LOGON32_LOGON_INTERACTIVE,
                                        win32con.LOGON32_PROVIDER_DEFAULT)
    rc = win32api.GetLastError()
    if userToken is None or (rc != 0):
        return -1, "", "LogonUser failed with RC=%d!" % rc
    profileDir = win32profile.GetUserProfileDirectory(userToken)
    tokenUser = win32security.GetTokenInformation(userToken, win32security.TokenUser)

    # Set access rights to window station
    hWinSta = win32service.OpenWindowStation("winsta0", False, win32con.READ_CONTROL | win32con.WRITE_DAC )
    # Get security descriptor by winsta0-handle
    secDescWinSta = win32security.GetUserObjectSecurity(hWinSta, win32security.OWNER_SECURITY_INFORMATION
                                                                 | win32security.DACL_SECURITY_INFORMATION
                                                                 | win32con.GROUP_SECURITY_INFORMATION)
    # Get DACL from security descriptor
    daclWinSta = secDescWinSta.GetSecurityDescriptorDacl()
    if daclWinSta is None:
        # Create DACL if not exisiting
        daclWinSta = win32security.ACL()
    # Add ACEs to DACL for specific user group
    daclWinSta.AddAccessAllowedAce(win32security.ACL_REVISION_DS, GENERIC_ACCESS, userGroupSid)
    daclWinSta.AddAccessAllowedAce(win32security.ACL_REVISION_DS, WINSTA_ALL, userGroupSid)
    # Set modified DACL for winsta0
    win32security.SetSecurityInfo(hWinSta, win32security.SE_WINDOW_OBJECT, win32security.DACL_SECURITY_INFORMATION,
                                  None, None, daclWinSta, None)

    # Set access rights to desktop
    hDesktop = win32service.OpenDesktop("default", 0, False, win32con.READ_CONTROL
                                                             | win32con.WRITE_DAC
                                                             | win32con.DESKTOP_WRITEOBJECTS
                                                             | win32con.DESKTOP_READOBJECTS)
    # Get security descriptor by desktop-handle
    secDescDesktop = win32security.GetUserObjectSecurity(hDesktop, win32security.OWNER_SECURITY_INFORMATION
                                                                   | win32security.DACL_SECURITY_INFORMATION
                                                                   | win32con.GROUP_SECURITY_INFORMATION )
    # Get DACL from security descriptor
    daclDesktop = secDescDesktop.GetSecurityDescriptorDacl()
    if daclDesktop is None:
        #create DACL if not exisiting
        daclDesktop = win32security.ACL()
    # Add ACEs to DACL for specific user group
    daclDesktop.AddAccessAllowedAce(win32security.ACL_REVISION_DS, GENERIC_ACCESS, userGroupSid)
    daclDesktop.AddAccessAllowedAce(win32security.ACL_REVISION_DS, DESKTOP_ALL, userGroupSid)
    # Set modified DACL for desktop
    win32security.SetSecurityInfo(hDesktop, win32security.SE_WINDOW_OBJECT, win32security.DACL_SECURITY_INFORMATION,
                                  None, None, daclDesktop, None)

    # Setup stdin, stdOut and stderr
    secAttrs = win32security.SECURITY_ATTRIBUTES()
    secAttrs.bInheritHandle = 1
    stdOutRd, stdOutWr = win32pipe.CreatePipe(secAttrs, 0)
    stdErrRd, stdErrWr = win32pipe.CreatePipe(secAttrs, 0)

    ppid = win32api.GetCurrentProcess()
    tmp = win32api.DuplicateHandle(ppid, stdOutRd, ppid, 0, 0, win32con.DUPLICATE_SAME_ACCESS)
    win32file.CloseHandle(stdOutRd)
    stdOutRd = tmp

    environment = win32profile.CreateEnvironmentBlock(userToken, False)

    startupInfo = win32process.STARTUPINFO()
    startupInfo.dwFlags = win32con.STARTF_USESTDHANDLES
    startupInfo.hStdOutput = stdOutWr
    startupInfo.hStdError = stdErrWr

    hPrc = win32process.CreateProcessAsUser(
                            userToken,
                            None,               # appName
                            cmdLine,            # commandLine
                            None,               # processAttributes
                            None,               # threadAttributes
                            1,                  # bInheritHandles
                            win32process.CREATE_NEW_CONSOLE, # dwCreationFlags
                            environment,        # newEnvironment
                            profileDir,         # currentDirectory
                            startupInfo)[0]

    win32file.CloseHandle(stdErrWr)
    win32file.CloseHandle(stdOutWr)
    win32security.RevertToSelf()

    # Wait for process to complete
    stdOutBuf = os.fdopen(msvcrt.open_osfhandle(stdOutRd, 0), "rb")
    stdErrBuf = os.fdopen(msvcrt.open_osfhandle(stdErrRd, 0), "rb")
    win32event.WaitForSingleObject(hPrc, maxWait)
    stdOut = stdOutBuf.read()
    stdErr = stdErrBuf.read()
    rc = win32process.GetExitCodeProcess(hPrc)
    return rc, str(stdOut, "utf-8"), str(stdErr, "utf-8")


if __name__ == "__main__":
    cmdLine = "C:/Windows/System32/cmd.exe"
    domainName = input("Domain: ")
    userName = input("User: ")
    password = input("Password: ")
    print(runAsDomainUser(domainName, userName, password, cmdLine, 60000))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Python 脚本中以 Windows 上的不同用户(非管理员)身份运行程序 的相关文章

  • Python 中的哈希映射

    我想用Python实现HashMap 我想请求用户输入 根据他的输入 我从 HashMap 中检索一些信息 如果用户输入HashMap的某个键 我想检索相应的值 如何在 Python 中实现此功能 HashMap
  • 如何使用 Win32 API 与 com 端口 (RS232) 通信

    我正在尝试使用 win32 API 与 com 端口对话 我找到了这个http www robbayer com files serial win pdf http www robbayer com files serial win pdf
  • Python 中的舍入浮点问题

    我遇到了 np round np around 的问题 它没有正确舍入 我无法包含代码 因为当我手动设置值 而不是使用我的数据 时 返回有效 但这是输出 In 177 a Out 177 0 0099999998 In 178 np rou
  • 需要在python中找到print或printf的源代码[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我正在做一些我不能完全谈论的事情 我
  • 跟踪 pypi 依赖项 - 谁在使用我的包

    无论如何 是否可以通过 pip 或 PyPi 来识别哪些项目 在 Pypi 上发布 可能正在使用我的包 也在 PyPi 上发布 我想确定每个包的用户群以及可能尝试积极与他们互动 预先感谢您的任何答案 即使我想做的事情是不可能的 这实际上是不
  • 如何有效截断文件头?

    大家都知道truncate file size 函数 通过截断文件尾部将文件大小更改为给定大小 但是如何做同样的事情 只截断文件的尾部和头部呢 通常 您必须重写整个文件 最简单的方法是跳过前几个字节 将其他所有内容复制到临时文件中 并在完成
  • YOLOv8获取预测边界框

    我想将 OpenCV 与 YOLOv8 集成ultralytics 所以我想从模型预测中获取边界框坐标 我该怎么做呢 from ultralytics import YOLO import cv2 model YOLO yolov8n pt
  • 在Python中连接反斜杠

    我是 python 新手 所以如果这听起来很简单 请原谅我 我想加入一些变量来生成一条路径 像这样 AAAABBBBCCCC 2 2014 04 2014 04 01 csv Id TypeOfMachine year month year
  • 为什么 PyYAML 花费这么多时间来解析 YAML 文件?

    我正在解析一个大约 6500 行的 YAML 文件 格式如下 foo1 bar1 blah name john age 123 metadata whatever1 whatever whatever2 whatever stuff thi
  • 从Python中的字典列表中查找特定值

    我的字典列表中有以下数据 data I versicolor 0 Sepal Length 7 9 I setosa 0 I virginica 1 I versicolor 0 I setosa 1 I virginica 0 Sepal
  • 如何使用 Mysql Python 连接器检索二进制数据?

    如果我在 MySQL 中创建一个包含二进制数据的简单表 CREATE TABLE foo bar binary 4 INSERT INTO foo bar VALUES UNHEX de12 然后尝试使用 MySQL Connector P
  • Numpy - 根据表示一维的坐标向量的条件替换数组中的值

    我有一个data多维数组 最后一个是距离 另一方面 我有距离向量r 例如 Data np ones 20 30 100 r np linspace 10 50 100 最后 我还有一个临界距离值列表 称为r0 使得 r0 shape Dat
  • pip 列出活动 virtualenv 中的全局包

    将 pip 从 1 4 x 升级到 1 5 后pip freeze输出我的全局安装 系统 软件包的列表 而不是我的 virtualenv 中安装的软件包的列表 我尝试再次降级到 1 4 但这并不能解决我的问题 这有点类似于这个问题 http
  • 如何断言 Unittest 上的可迭代对象不为空?

    向服务提交查询后 我会收到一本字典或一个列表 我想确保它不为空 我使用Python 2 7 我很惊讶没有任何assertEmpty方法为unittest TestCase类实例 现有的替代方案看起来并不正确 self assertTrue
  • Pandas 将多行列数据帧转换为单行多列数据帧

    我的数据框如下 code df Car measurements Before After amb temp 30 268212 26 627491 engine temp 41 812730 39 254255 engine eff 15
  • Python:XML 内所有标签名称中的字符串替换(将连字符替换为下划线)

    我有一个格式不太好的 XML 标签名称内有连字符 我想用下划线替换它 以便能够与 lxml objectify 一起使用 我想替换所有标签名称 包括嵌套的子标签 示例 XML
  • 在本地网络上运行 Bokeh 服务器

    我有一个简单的 Bokeh 应用程序 名为app py如下 contents of app py from bokeh client import push session from bokeh embed import server do
  • python import inside函数隐藏现有变量

    我在我正在处理的多子模块项目中遇到了一个奇怪的 UnboundLocalError 分配之前引用的局部变量 问题 并将其精简为这个片段 使用标准库中的日志记录模块 import logging def foo logging info fo
  • Scipy Sparse:SciPy/NumPy 更新后出现奇异矩阵警告

    我的问题是由大型电阻器系统的节点分析产生的 我基本上是在设置一个大的稀疏矩阵A 我的解向量b 我正在尝试求解线性方程A x b 为了做到这一点 我正在使用scipy sparse linalg spsolve method 直到最近 一切都
  • Pandas 每周计算重复值

    我有一个Dataframe包含按周分组的日期和 ID df date id 2022 02 07 1 3 5 4 2022 02 14 2 1 3 2022 02 21 9 10 1 2022 05 16 我想计算每周有多少 id 与上周重

随机推荐

  • 部署到天蓝色网站后,对路径的访问被拒绝(发生“System.UnauthorizedAccessException”类型的异常)

    我正在从 blob 下载内容并将其存储在浏览我的应用程序的用户的本地文件夹中 一切工作正常 本地没有任何问题 但部署到应用服务 Web 应用程序后 我遇到了访问被拒绝的问题 我尝试过以下选项 选项1 string pathString D
  • Delphi性能:读取数据集中某个字段下的所有值

    我们正在尝试找出一些从 TADOQuery 读取的性能修复程序 目前 我们使用 while not Q eof do begin Q next 方法循环记录 对于每条记录 我们读取每条记录的 ID 和值 并将每条记录添加到组合框列表中 有没
  • 滚动视图内部滚动视图

    我知道 Google 的人要求我们不要将 Scrollable 视图放入另一个 Scrollable 视图中 但是他们有任何官方声明指示我们不要这样做吗 试试这个 Note Here parentScrollView意味着外层ScrollV
  • Pos() 在 utf8 字符串边界内

    我希望有一个 Pos 适合用于指定源字符串内的边界 而不是让它在整个数据中执行搜索 假设我有一个 100 个字符长的字符串 我只想在 unicode utf8 字符串的第 5 个和第 20 个字符之间执行 Pos 该代码应该改编自 delp
  • MySQL - 如何在 INSERT 语句中将字符串值解析为 DATETIME 格式?

    我有一个MySQL database 其中有一列是日期类型DATETIME 我从外部应用程序获取日期 时间的字符串值 该字符串值如下所示 5 15 2012 8 06 26 AM MySQL 在 INSERT 上抛出错误 Error Inc
  • System.IO.IOException CreateHostBuilder(args).Build().Run() 中的“功能未实现”

    当我开始在 Linux Docker 容器中调试我的应用程序时 在调用时出现异常CreateHostBuilder args Build 该代码是一个相当新的 AspASP NET Core MVC 3 1 项目的一部分 I saw the
  • Nexus 存储库 3 备份

    最近我安装了Nexus 存储库 3在 OpenStack Cloud 中 我已经使用它一段时间了 我想对 Nexus 执行增量备份 从而保护我们的数据 如何对 Nexus 数据进行增量备份 Nexus 备份的过程描述于文档 https he
  • 使用负年份创建 Instant

    我正在尝试创建一个Instant基于公元前公历中的年份 这是我到目前为止所拥有的 Instant FromDateTimeOffset new DateTimeOffset 1000 10 01 0 0 0 0 new System Glo
  • SwiftUI 中带有背景图像的透明导航栏

    我有一个自定义导航栏 它是一个图像 后跟标题文本 图像设置为缩放以填充 但没有完全填满导航栏 因此 您可以看到图像未覆盖的一小部分条形 我尝试将导航栏的背景颜色设置为清除 但这不起作用 有什么建议么 struct ContentView V
  • 如何通过 GPS 检查距 x,y 位置 10 米的半径

    我从 GPS 得到这个位置 40 715192 74 005795 如何判断i是否在10米半径范围内 提前致谢 使用半正矢公式http en wikipedia org wiki Haversine formula http en wiki
  • 将 yuv 序列转换为 bmp 图像

    我有 yuv 序列 我想将它们转换为 bmp 图像 我想将其保存到我的计算机上的文件夹中 我使用了 yuv2bmp m 文件这个链接 http www mathworks com matlabcentral fileexchange 255
  • 数据库 - 为什么不区分大小写?

    我看到一两个线程在全球范围内讨论区分大小写 但我的问题更具体 例如 我理解对文本值不区分大小写的搜索的兴趣 但为什么我们要使用不区分大小写的数据库名称 表和列呢 难道不会导致错误吗 使用数据库的脚本语言都是区分大小写的 因此 例如 如果我们
  • MS Graph Java SDK:如何将大文件上传到 OneDrive?

    我正在尝试从 Java 应用程序将文件上传到 OneDrive 但我不了解流程 也没有在 SKD 中看到任何用于文件上传的文档或方法 我发现的唯一流程是 driveClient me drive root createUploadSessi
  • 如何获取 DShellFolderViewEvents 的方法签名

    我试图沉沦DShellFolderViewEvents使用 ATL 我能够成功订阅的唯一方法是DISPID SELECTIONCHANGED 标题中似乎列出了许多其他事件shdispid h 但我无法让他们开火 不确定我做错了什么 可能与
  • Blogger Javascript 在帖子 > 500 上出现 JSON 错误

    我想向我的博主展示随机帖子 我从谷歌搜索得到了一个 javascript 并尝试了它 但是随机帖子的数量不正确 应该是 10 但有时是 4 有时是 2 等等 我尝试检查发生了什么 发现 json feed entry 500 抛出错误 这是
  • 为什么Restlet无法注册JSON转换器?

    我在这里束手无策 似乎从来没有遇到过这个问题 我发现设置快速 HelloWorld 应用程序以确保 Restlet 2 0 启动并运行相对容易 然而 我面临着一个我以前从未遇到过的奇怪异常 我的类路径和 WEB INF lib 文件夹中都有
  • g++:错误:libgomp.spec:没有这样的文件或目录

    我使用 g GCC 4 7 2 在 Windows 7 64 位版本上 下载自http nuwen net mingw html http nuwen net mingw html 我尝试使用 fopenmp 标志并收到错误 g 错误 li
  • Swagger/Swashbuckle 列出可接受的值?

    我已在 Web API 应用程序上成功实现了 Swashbuckle Swagger 但对输出并不满意 我的 Web api 方法之一 企业事件日志记录工具 接受复杂对象值的 JSON 对象 问题在于 当存在可以使用的可接受值的选定列表时
  • 在 Windows 上监听“使用我的 Java 应用程序打开文件”事件

    标题很混乱 但不知道如何用几句话来解释 我有一个读取 example 文件的 java 应用程序 我还添加了一个文件关联 感谢install4j因此 当用户双击任何扩展名为 example 的文件时 我的应用程序就会启动 看来 instal
  • 在 Python 脚本中以 Windows 上的不同用户(非管理员)身份运行程序

    使用以下代码 class ImpersonateWin32Sec object def init self domain username password self username username self password pass