CreateProcessAsUser 从服务和用户安全问题

2023-12-02

我有一个启动我的应用程序的 Windows 服务。该服务是一个调度程序,用于执行最终用户定义的一些自定义操作。

它作为本地系统帐户运行,并将启动我的应用程序(有窗口)。

为此我使用函数登录用户, 加载用户配置文件, 创建进程为用户。 这很完美但前提是用户,至log on,是管理员组的成员。

我不能将该用户保留为管理员,他需要是默认用户(用户组的成员)。

作为管理员,它从服务中运行良好。但是当进程以默认用户身份启动时,它会异常终止:

ExitCode: 0xC0000142 STATUS_DLL_INIT_FAILED
Message: {DLL Initialization Failed} Initialization of the dynamic link library %hs failed. The process is terminating abnormally.

如果我使用该用户(用户组的成员)登录并手动启动应用程序,一切都会正常。

我还没有弄清楚导致问题的库是什么。我检查了系统事件日志,但没有日志。 我已经尝试过模拟登录用户但没有成功。

这是代码:

type 
    TProcessRec = record
        Token: Cardinal;
        ProfileInfo: TProfileInfo;
        Job: Cardinal;
        Environment: Pointer;
        ProcessInfo: TProcessInformation;
        WinStat: HWINSTA;
      end;

      TProcess = class
      private
        fProcess: TProcessRec;
      public
        constructor Create(aUser, aDomain, aPassword, aCommand, aWorkingDir: string; aUtil: TJJWServiceUtil);
        destructor Destroy; override;

        procedure Terminate(aExitCode: Cardinal);

        function getExitCode: Cardinal;
      end;

    constructor TProcess.Create(aUser, aDomain, aPassword, aCommand, aWorkingDir: string; aUtil: TJJWServiceUtil);
    type
      TCreateProcessFuncType = (cpAsUser, cpWithLogon);
    const
      DES_CREATION_TYPE: array [TCreateProcessFuncType] of string =
        ('CreateProcessAsUser', 'CreateProcessWithLogon');
    var
      sa: TSecurityAttributes;
      si: TStartupInfo;
      limits : TJobObjectExtendedLimitInformation;
      wUser, wDomain, wPassword, wCommand, wWorkingDir: WideString;
      creationType: TCreateProcessFuncType;
    begin

        // se estiver rodando com a conta LocalSystem (em serviço de windows)
        if
          IsPrivilegeEnabled(SE_TCB_NAME) or IsPrivilegeEnabled(SE_INCREASE_QUOTA_NAME)
        then
          creationType := cpAsUser
        else
          creationType := cpWithLogon;

      aUtil.debug('ENV: ' + AnsiReplaceStr(GetEnvironmentVariable('PATH'), '%', '%%'));
      aUtil.debug('Criando novo processo em modo: ' + DES_CREATION_TYPE[creationType]);

      FillChar(fProcess, SizeOf(fProcess), 0);

      FillChar(sa, SizeOf(sa), 0);
      sa.nLength := SizeOf(sa);

      FillChar(si, SizeOf(si), 0);
      si.cb := SizeOf(si);

      case creationType of

        cpAsUser:
          begin
            aUtil.debug('Efetuando o login do usuário %s', [aUser]);
            // login
            if not LogonUser(PChar(aUser), PChar(aDomain), PChar(aPassword), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, fProcess.Token) then
              RaiseLastOSError;

            try
              aUtil.debug('Carrengado o profile do usuário %s', [aUser]);

              // carrega o profile do usuário
              fProcess.ProfileInfo.dwSize := SizeOf(fProcess.ProfileInfo);
              fProcess.ProfileInfo.dwFlags := PI_NOUI;
              fProcess.ProfileInfo.lpUserName := PChar(aUser);
              if not LoadUserProfile(fProcess.Token, fProcess.ProfileInfo) then
                RaiseLastOSError;

              try
                aUtil.debug('Criando o bloco de variáveis de ambiente do usuário %s', [aUser]);
                // variaveis de ambiente
                if not CreateEnvironmentBlock(fProcess.Environment, fProcess.Token, false) then
                  RaiseLastOSError;

                aUtil.debug('Criando o JOB para associar o processo filho ao processo pai');
                // job para associar
                fProcess.Job := CreateJobObject(@sa, nil);
                if fProcess.Job = 0 then
                  RaiseLastOSError;

                try
                  // limita o job para matar o seu processo caso o processo pai termine antes
                  FillChar(Limits,SizeOf(Limits),0);
                  with Limits,BasicLimitInformation do
                    LimitFlags := JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE or JOB_OBJECT_LIMIT_BREAKAWAY_OK;

                  if not SetInformationJobObject(fProcess.Job, JobObjectExtendedLimitInformation, @limits, SizeOf(limits)) then
                    RaiseLastOSError;

                  try
                    fProcess.WinStat := CreateWindowStation(SCHEDULER_WINSTAT, 0, 0, nil);
                    if fProcess.WinStat = 0 then
                      RaiseLastOSError;
                    si.lpDesktop := PChar(SCHEDULER_WINSTAT);

                    aUtil.debug('Criando o processo: %s', [aCommand]);

                    // processo!
                    if not CreateProcessAsUser(
                      fProcess.Token,
                      nil,
                      PChar(aCommand),
                      @sa,
                      nil,
                      false,
                      CREATE_SUSPENDED or CREATE_BREAKAWAY_FROM_JOB or NORMAL_PRIORITY_CLASS or CREATE_NEW_CONSOLE or CREATE_NEW_PROCESS_GROUP or CREATE_UNICODE_ENVIRONMENT,
                      fProcess.Environment,
                      PChar(aWorkingDir),
                      si,
                      fProcess.ProcessInfo)
                    then
                      RaiseLastOSError;

                    try
                      aUtil.debug('Associando o JOB ao processo filho');
                      // associa ao processo do plugin o JOB (gruda nele!)
                      if not AssignProcessToJobObject(fProcess.Job, fProcess.ProcessInfo.hProcess) then
                        RaiseLastOSError;

                      // VOA PROCESSO, VOA!
                      if ResumeThread(fProcess.ProcessInfo.hThread) = $FFFFFFFF then
                        RaiseLastOSError;

                      aUtil.debug('Processo disparado');
                    except
                      TerminateProcess(fProcess.ProcessInfo.hProcess, Cardinal(-1));

                      CloseHandle(fProcess.ProcessInfo.hThread);
                      CloseHandle(fProcess.ProcessInfo.hProcess);

                      FillChar(fProcess.ProcessInfo, SizeOf(fProcess.ProcessInfo), 0);

                      raise;
                    end;

                  except
                    DestroyEnvironmentBlock(fProcess.Environment);
                    fProcess.Environment := nil;
                    raise;
                  end;

                except
                  CloseHandle(fProcess.Job);
                  fProcess.Job := 0;
                  raise;
                end;

              except
                UnloadUserProfile(fProcess.Token, fProcess.ProfileInfo.hProfile);
                FillChar(fProcess.ProfileInfo, SizeOf(fProcess.ProfileInfo), 0);
                raise;
              end;

            except
              CloseHandle(fProcess.Token);
              fProcess.Token := 0;
              raise;
            end;
          end;

        //////////////////////////////////////////////////////////////////////////////

        cpWithLogon:
          begin
            wUser := aUser;
            wDomain := aDomain;
            wPassword := aPassword;
            wCommand := aCommand;
            wWorkingDir := aWorkingDir;

            aUtil.debug('Disparando o processo: %s', [aCommand]);

            // o CreateProcessWithLogon já cria um JOB para evitar
            // que o processo fique órfão no limbo
            if not CreateProcessWithLogon(
               PWideChar(wUser),
               PWideChar(wDomain),
               PWideChar(wPassword),
               LOGON_WITH_PROFILE,
               nil,
               PWideChar(wCommand),
               NORMAL_PRIORITY_CLASS or CREATE_NEW_CONSOLE or CREATE_NEW_PROCESS_GROUP,
               nil,
               PWideChar(wWorkingDir),
               si,
               fProcess.ProcessInfo
             )
            then
              RaiseLastOSError;
          end;

          end;
    end;

    destructor TProcess.Destroy;
    begin
      if fProcess.ProcessInfo.hProcess > 0 then
      begin
        if getExitCode = STILL_ACTIVE then
          TerminateProcess(fProcess.ProcessInfo.hProcess, Cardinal(-1));

        CloseHandle(fProcess.ProcessInfo.hThread);
        CloseHandle(fProcess.ProcessInfo.hProcess);
      end;

      if fProcess.Environment <> nil then
        DestroyEnvironmentBlock(fProcess.Environment);

      if fProcess.Job > 0 then
        CloseHandle(fProcess.Job);

      if fProcess.ProfileInfo.hProfile > 0 then
        UnloadUserProfile(fProcess.Token, fProcess.ProfileInfo.hProfile);

      if fProcess.Token > 0 then
        CloseHandle(fProcess.Token);

      if fProcess.WinStat > 0 then
        CloseWindowStation(fProcess.WinStat);

      FillChar(fProcess, SizeOf(fProcess), 0);

      inherited;
    end;

    function TProcess.getExitCode: Cardinal;
    begin
      if not GetExitCodeProcess(fProcess.ProcessInfo.hProcess, Result) then
        RaiseLastOSError;
    end;

这可能很有用

用 C++ 启动交互式客户端进程


根据这个:用 C++ 启动交互式客户端进程

和这个:CreateProcessAsUser() 窗口站和桌面

我解决了创建新的 Window Station 和桌面来启动该过程的问题:

myWinStat := CreateWindowStation('myWinStat', 0, GENERIC_READ or GENERIC_WRITE, nil);
myDesk := CreateDesktop('myDesktop', nil, nil, 0, GENERIC_READ or GENERIC_WRITE, nil);
startupInfo.lpDesktop := 'myDesktop';
try
   // createProcessAsUser...
   // Wait for process termination...
finally
   CloseDesktop(myDesk);
   CloseWindowStation(myWinStat);
end;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CreateProcessAsUser 从服务和用户安全问题 的相关文章

  • SSL 错误 1409442E 使用 TIdHTTP 通过 HTTPS 下载文件 [重复]

    这个问题在这里已经有答案了 我正在使用德尔福10 3 3 下面的代码曾经有效 但现在尝试通过 HTTPS 下载文件时遇到错误 连接 SSL 错误错误 1409442E SSL 例程 SSL3 READ BYTES tlsv1 警报协议版本
  • 添加到 .NET 任务栏中的右键单击应用程序菜单

    大多数应用程序只有 恢复 移动 调整大小 最小化 最大化和关闭 但是MS SQL提供了额外的选项 帮助 自定义视图 按照这些思路 是否可以添加到任务栏中应用程序的右键单击菜单 注 我是not指通知区域中时钟旁边的图标 这是一个更简单的ans
  • 如何获取属于某个进程的打开句柄的计数?

    您可以使用该程序流程浏览器 http technet microsoft com en us sysinternals bb896653查看正在运行的应用程序有多少个句柄 有没有办法用Delphi代码来获取这个数字 我有兴趣跟踪应用程序本身
  • Delphi XE 和 OmniXML:使用 SelectNode()?

    我将以下 XML 片段作为一个更大的 XML 文件的一部分 我正在使用最新的 OmniXML 快照进行处理
  • 有没有其他方法可以在delphi上观看youtube视频?

    我看到http www delphiflash com demo youtube video http www delphiflash com demo youtube video关于如何在 delphi 上加载 flash 视频 但它不是
  • 如果我使用带有表单身份验证的 WCF,php 或 java 客户端将如何进行身份验证?

    我有一个通用的概念验证 WCF 服务 它使用表单身份验证来保护访问 当我的客户端是 NET 时 一切都很好 vb 代码如下 Dim client As SupplierServiceClient New SupplierServiceCli
  • ASP.NET MVC 防伪造令牌不安全

    在没有 ssl 的情况下向服务器发出请求时 我实际上可以看到 MVC3 框架以纯文本形式生成的验证令牌密钥 该密钥存储在名为 RequestVerificationToken Lw 的 cookie 中 在混合安全环境中 实际上可以在向非
  • 带图像的简单 GUI [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我试图在简单的 GUI 上显示一些卡
  • 自动从 C# 代码进行调试过程并读取寄存器值

    我正在寻找一种方法来读取某个地址的 edx 注册表 就像这个问题中所问的那样 读取eax寄存器 https stackoverflow com questions 16490906 read eax register 虽然我的解决方案需要用
  • OpenJDK 版本控制

    上下文 我想确保我们系统上安装的 Java 不受 CVE 2022 21449 的影响 java version 给出 openjdk version 11 0 7 2020 04 14 LTS OpenJDK Runtime Enviro
  • 你能给我一个会话固定攻击的例子吗?

    我读过有关会话固定的内容 据我了解 它强制用户使用攻击者的会话 它是否正确 你能举个例子来说明这会如何冒犯用户吗 我通常不喜欢发布维基百科的链接 但这里有一个链接维基百科上有很好的解释 http en wikipedia org wiki
  • 如何在服务器上保存用户凭据以在后台运行查询

    背景 我们有一个 ASP NET Silveright Web 应用程序 silverlight客户端显示用户 图形形式的特定数据 它从服务器请求数据 问题 由于服务器必须执行底层数据库查询 获取这些数据的成本很高 因此客户端必须等待 优化
  • 如何禁止 celery 中的 pickle 序列化

    Celery 默认使用 pickle 作为任务的序列化方法 如中所述FAQ http ask github com celery faq html isn t using pickle a security concern 这代表一个安全漏
  • 从 Symfony2 中的 http_basic auth 注销

    每当我去 admin logout 我已正确重定向到项目的根目录 但在访问时仍处于登录状态 admin 因为没有提示我输入凭据 这是我的配置 安全 yml security firewalls admin area pattern admi
  • 为什么 Sleep() 会使后续代码减慢 40 毫秒?

    我最初是在 coderanch com 上询问这个问题的 所以如果您尝试在那里帮助我 谢谢 并且不必重复这个努力 不过 coderanch com 主要是一个 Java 社区 而且 经过一些研究 这似乎确实是一个 Windows 问题 因此
  • 为什么使用过程来创建对象比使用函数更受欢迎?

    这类似于这个问题 https stackoverflow com questions 1894217 is it memory safe to provide an object as a function result 我问 为什么 到最
  • 有没有办法在 TRttiField 中 FieldType 为零的结构中获取 real48 和短字符串变量的 RTTI 提示?

    我发现 Delphi 中的扩展 RTTI 功能有一个奇怪的疏忽 可能是故意的 我想转储包含大约 1500 个不同字段的记录类型中的所有字段 是的 认真的 其中一些是 real48 类型 一些是短字符串 对于这两种类型 在运行时这些类型的 F
  • 如何处理第三方库中的警告/提示?

    我们使用 FastReport 来生成报告 事实上 我们为访问源代码付费 我们目前使用的是FastReport的最新稳定版本 虽然它对于我们的生产来说足够稳定 但每当我编译时 我都会看到以下内容 dcc32 Hint fs iinirtti
  • 从命令行增加 Delphi XE 项目版本号

    我有一个 Delphi XE 项目 我试图在使用 MSBuild 构建它之前更改程序的版本号 版本号信息位于 DPROJ 文件中 但如果我更改这些值 版本号不会更改 我认为原因是当您在 IDE 中更改版本号时 Delphi 会将更改保存到
  • 如何清理 Runtime.exec() 中使用的用户输入?

    我需要通过命令行调用自定义脚本 这些脚本需要很少的参数并在 Linux 机器上调用 当前版本容易出现各种shell注入 如何清理用户给出的参数 参数包括登录名和路径 Unix 或 Windows 路径 用户应该能够输入任何可能的路径 该路径

随机推荐

  • 获取 SQL Server 表中每列的每个值的计数

    所以我查了一下 这个问题非常相似 但缺少一个关键部分 SQL Server 计算表中每一列中不同值的数量 因此 在这个问题中 他们想要每列的不同计数 我想要做的是获取表中每一列的每个不同值的计数 并且我正在对特定数据库中的所有表执行此操作
  • 如何从 ElasticSearch 中彻底删除某些内容?

    我们使用 ELK 堆栈进行日志记录 我被要求设计一个流程来删除意外记录的敏感信息 现在基于我对 ElasticSearch Lucene 如何处理的阅读删除和更新数据仍在索引中 只是不可用 随着索引合并等 它最终会被清理 是否有一个流程来运
  • 动态三元运算符

    为什么以及如何在下面的代码中工作 dynamic x c a new D1 x new D2 但不是这个 dynamic x c a new D1 new D2 Code class Program static void Main str
  • 无法正确设置 Android Actionbar 背景

    问题当我设置 ActionBar 背景颜色时 该栏看起来像这样 我无法在这里上传图片 所以这是文件 Android ActionBar问题 我的价值观 风格文件
  • 如何在 Adob​​e Flex 中合并 DataGrid/Advanced DataGrid 中的单元格

    我需要合并单元格 如图所示 Flex 以我的理解 并没有直接提供这一点 你有几个选择 无论哪种方式 您可能需要在分层模型中排列数据 有 3 个孩子的家长似乎描述了您的问题 我看到的第一个选项涉及直接将您的数据声明为高级数据网格的分层结构 如
  • 找出 Eclipse 运行在什么 JVM 上

    我目前正在尝试调整 Eclipse 安装并遇到了 vm 选项 SO 上的其他帖子提到 始终使用可用的最新 JVM 是件好事 因为它们在性能方面不断变得更好 所以我很可能会这样做 我想知道如果您没有指定 vm 参数 您如何找出 Eclipse
  • jenkins 不执行 mvn 命令后的最后一个命令

    我将我的工作配置为自由式 我需要将案例运行到指定的机器上 我的项目是maven项目 我想在案例运行完成后将报告复制到主节点 詹金斯版本 1 483 我使用 pscp 复制文件 这些文件在 Windows 命令提示符下手动工作正常 我的命令如
  • 使用 PHP 和 PDO 访问 Microsoft

    我正在尝试连接到我的访问数据库 但无法连接 我的 Microsoft server 2008 上装有 IIS 7 我不断收到此错误消息 SQLSTATE IM002 SQLDriverConnect 0 Microsoft ODBC 驱动程
  • 陈述/计算的生日悖论

    显然 我实际上应该创建一个数组 在多次试验中随机分配生日 5000 然后 假设每次有 2 50 个人至少有 2 个生日时进行计数 并将结果除以 5 000 以获得近似概率 我相信我的循环搞砸了 需要一些反馈 不是代码 我想确切地了解出了什么
  • Hive SELECT 语句创建结构数组

    我在 Hive 中选择结构数组时遇到问题 我的源表如下所示 field id fieldid fieldlabel fieldtype answer id unitname 这是调查数据 其中id是调查id 中间的四个字段是响应数据 uni
  • 从 Excel VBA 运行 R,无需 RExcel

    这个过程可以简化吗 首先 我在 R 中手动打开该文件 C R ExampleModel ModelScript R 在 R 编辑器中 当从打开的 ModelScript R 文件运行以下代码时 它会正确处理 Model R 脚本 sourc
  • 我应该如何将 UIImage 存储在我的 Core Data 数据库中?

    我正在开发一个应用程序 需要将大约 100 张或更多图像与其他相关信息一起预先插入到核心数据数据库中 现在 我只需编写几行代码就可以轻松添加其他数据 但对于 UIImages 我不确定如何在不编写大量代码的情况下做到这一点 我想知道 是否有
  • AngularJS $http 未定义

    我对 AngularJS 还很陌生 当我打电话时 http get我得到一个 http is not defined error 这是我的模块的内容 var demoApp angular module demoApp demoApp co
  • 在一个语句中输出多个后置和前置增量[重复]

    这个问题在这里已经有答案了 我是 C 语言新手 所以请 sum1 帮助我 写的一段C代码 int i 3 printf d i i 编译器给出 O P 9 如何 结果未定义 您在表达式中多次修改变量 或者序列点更准确 在序列点之间多次修改变
  • EXC_BAD_INSTRUCTION 仅在 iPhone 5 模拟器中

    在 iPhone 5 模拟器上运行我的代码会引发如图所示的异常 在任何其他模拟器上运行代码就可以了 我无法在这行不起眼的代码中发现我在哪里犯了错误 还有其他人有这个问题吗 NSInteger 这是一个类型别名Int在 Swift 中 是 3
  • Android:NullPointerException 使用 SharedPreferences

    使用 SharedPreferences 此活动在启动时崩溃 首先我将发布活动代码 然后我将发布我的 LogCat 非常感谢你们 你们总是给予我们很大的帮助 活动代码 package com creativecoders gymbuddy
  • 在设置 {app} 之前获取 wpSelectDir 中的路径 Inno Setup

    当用户单击时 我想获取安装目录的路径Next 当我在wpSelectDirInno 设置 我需要检查路径 因为我需要验证路径 如果不正确 我不会让用户继续 我的问题是常数 app 尚未设置 因为它将在之后设置wpSelectDir我还在 U
  • 使用Python将日记文件拆分为多个文件

    我保留一份技术笔记的日记文件 每个条目都带有时间戳 如下所示 Monday 02012 05 07 at 01 45 20 PM This is a sample note Lorem ipsum dolor sit amet consec
  • 我可以在ironruby 中运行rubygems 吗?

    目前是否可以通过预发布的ironruby来运行rubygems 好像我必须设置一个环境变量才能找到它们 您已经能够在 IronRuby 下运行 ruby gems 有一段时间了 只需下载并安装最新的来自 codeplex 的 IronRub
  • CreateProcessAsUser 从服务和用户安全问题

    我有一个启动我的应用程序的 Windows 服务 该服务是一个调度程序 用于执行最终用户定义的一些自定义操作 它作为本地系统帐户运行 并将启动我的应用程序 有窗口 为此我使用函数登录用户 加载用户配置文件 创建进程为用户 这很完美但前提是用