Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows 来自服务和用户安全问题的CreateProcessAsUser_Windows_Security_Delphi_Service - Fatal编程技术网

Windows 来自服务和用户安全问题的CreateProcessAsUser

Windows 来自服务和用户安全问题的CreateProcessAsUser,windows,security,delphi,service,Windows,Security,Delphi,Service,我有一个启动我的应用程序的windows服务。此服务是一个调度程序,用于执行最终用户定义的一些自定义操作 它以LocalSystem帐户运行,并将启动我的应用程序(具有windows) 为此,我使用函数。 这非常有效,但前提是登录的用户是Administrators组的成员 我不能将用户保留为管理员,他需要是默认用户(用户组的成员) 作为管理员,它可以从服务中正常运行。但当进程作为默认用户启动时,它会异常终止: ExitCode: 0xC0000142 STATUS_DLL_INIT_FAILE

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

它以LocalSystem帐户运行,并将启动我的应用程序(具有windows)

为此,我使用函数。 这非常有效,但前提是登录的用户是Administrators组的成员

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

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

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;
类型
TProcessRec=记录
标记:红衣主教;
ProfileInfo:TProfileInfo;
工作:红衣主教;
环境:指针;
ProcessInfo:TProcessInformation;
温斯塔:HWINSTA;
结束;
t进程=类
私有的
fProcess:TProcessRec;
公众的
构造函数Create(aUser、aDomain、aPassword、aCommand、aWorkingDir:string;aUtil:TJJWServiceUtil);
毁灭者毁灭;推翻
程序终止(AEXIT代码:基数);
函数getExitCode:基数;
结束;
构造函数TProcess.Create(aUser、aDomain、aPassword、aCommand、aWorkingDir:string;aUtil:TJJWServiceUtil);
类型
TCreateProcessFuncType=(cpAsUser,cpWithLogon);
常数
DES_创建类型:字符串的数组[TCreateProcessFuncType]=
('CreateProcessAsUser','CreateProcessWithLogon');
变量
sa:t安全属性;
si:TStartupInfo;
限制:TJobObjectExtendedLimitInformation;
wUser、wDomain、wPassword、wCommand、wWorkingDir:WideString;
creationType:TCreateProcessFuncType;
开始
//se estiver rodando com一个连续的本地系统(em serviço de windows)
如果
iPrivilegeEnabled(SE_TCB_名称)或iPrivilegeEnabled(SE_增加_配额_名称)
然后
creationType:=cpAsUser
其他的
creationType:=cpWithLogon;
aUtil.debug('ENV:'+AnsiReplaceStr(GetEnvironmentVariable('PATH')、'%'、'%');
自动调试('Criando novo processo em modo:'+创建类型[creationType]);
FillChar(fProcess,SizeOf(fProcess),0);
FillChar(sa,SizeOf(sa),0);
sa.nLength:=SizeOf(sa);
FillChar(si,SizeOf(si),0);
si.cb:=SizeOf(si);
案例创建类型
cpAsUser:
开始
aUtil.debug('Efetuando login do usuário%s',[aUser]);
//登录
如果不是LogonUser(PChar(aUser)、PChar(aDomain)、PChar(aPassword)、LOGON32\u LOGON\u INTERACTIVE、LOGON32\u PROVIDER\u DEFAULT、fProcess.Token),则
赖斯·塞罗;
尝试
aUtil.debug('Carrengado profile do usuário%s',[aUser]);
//乌苏瓦里奥酒店
fProcess.ProfileInfo.dwSize:=SizeOf(fProcess.ProfileInfo);
fProcess.ProfileInfo.dwFlags:=PI_NOUI;
fProcess.ProfileInfo.lpUserName:=PChar(aUser);
如果没有LoadUserProfile(fProcess.Token、fProcess.ProfileInfo),则
赖斯·塞罗;
尝试
aUtil.debug('Criando o bloco de variáveis de ambiente do usuário%s',[aUser]);
//环境变量
如果不是CreateEnvironmentBlock(fProcess.Environment,fProcess.Token,false),则
赖斯·塞罗;
自动调试('Criando o JOB para associar o processo filho ao processo pai');
//工作助理
fProcess.Job:=CreateJobObject(@sa,nil);
如果fProcess.Job=0,则
赖斯·塞罗;
尝试
//有限的工作时间,包括工作时间和工作时间
FillChar(限值),SizeOf(限值),0;
有了限制,基本信息就可以了
LimitFlags:=作业\u对象\u限制\u终止\u作业\u关闭或作业\u对象\u限制\u分离\u确定;
如果未设置InformationJobObject(fProcess.Job,JobObjectExtendedLimitInformation,@limits,SizeOf(limits)),则
赖斯·塞罗;
尝试
fProcess.WinStat:=createWindowsStation(调度器_WinStat,0,0,nil);
如果fProcess.WinStat=0,则
赖斯·塞罗;
si.lpDesktop:=PChar(调度器_WINSTAT);
自动调试('Criando-o-processo:%s',[aCommand]);
//过程!
如果不是CreateProcessAsUser(
fProcess.Token,
无
PChar(ACOMAND),
@sa,
无
假,,
创建\u挂起或创建\u脱离\u作业或正常\u优先级\u类或创建\u新建\u控制台或创建\u新建\u进程\u组或创建\u UNICODE \u环境,
fProcess.Environment,
PChar(工作目录),
硅,
fProcess.ProcessInfo)
然后
赖斯·塞罗;
尝试
自动调试(“相关作业和流程调试”);
//associa ao processo do插件o作业(gruda nele!)
如果未分配ProcessToJobObject(fProcess.Job、fProcess.ProcessInfo.hProcess),则
赖斯·塞罗;
//美国之音,美国之音!
如果恢复线程(fProcess.ProcessInfo.h
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;