CreateProcessAsUser is successful, but no process is created

北城以北 提交于 2019-12-25 08:17:38

问题


We have a service application which spawns a process in the console session (WTSGetActiveConsoleSessionId) to allow for a desktop control style access to the machine. This works well in most situations however there are some VM's which appear to successfully create the process as far as the result of CreateProcessAsUser is concerned, however the process does not get created.

The service runs under the LocalSystem account. The process being started is NOT already running. No virus protection programs are running. We have only seen this behaviour on Windows Server 2008 R2 (but that is not to say it that is exclusive).

The code we use is as follows:

function StartProcessInSession(strProcess: String; bLocalSystem: Boolean = True; iSessionID: Integer = -1): Boolean;

  procedure SPISLog(strLog: String; bError: Boolean = False);
  begin
    Log(strLog);
    if bError then Abort;
  end;

var pi: PROCESS_INFORMATION;
  si: STARTUPINFO;
  winlogonPid, dwSessionId: DWord;
  hUserToken, hUserTokenDup, hPToken, hProcess: THANDLE;
  dwCreationFlags: DWORD;
  tp: TOKEN_PRIVILEGES;
  lpenv: Pointer;
  bError: Boolean;
  strClone: String;
begin
  if GetProcessID(strProcess, iSessionID) > 0 then
  begin
    Result := True;
    Exit;
  end;
  Result := False;
  bError := False;
  if not InitProcLibs then Exit;
  if bLocalSystem then strClone := 'winlogon.exe' else strClone := 'explorer.exe';
  winlogonPid := GetProcessID(strClone, iSessionID);
  try
    dwSessionId := WTSGetActiveConsoleSessionId();
    dwCreationFlags := NORMAL_PRIORITY_CLASS or CREATE_NEW_CONSOLE;
    ZeroMemory(@si, sizeof(STARTUPINFO));
    si.cb := sizeof(STARTUPINFO);
    si.lpDesktop := PChar('Winsta0\Default'); 
    ZeroMemory(@pi, sizeof(pi));
    hProcess := OpenProcess(MAXIMUM_ALLOWED, FALSE, winlogonPid);
    if (not OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY or TOKEN_DUPLICATE or
      TOKEN_ASSIGN_PRIMARY or TOKEN_ADJUST_SESSIONID or TOKEN_READ or TOKEN_WRITE, hPToken)) then
        bError := True;
    if bError then SPISLog('SPIS - OpenProcessToken failed (' + SysErrorMessage(GetLastError) + ').', True);
    if (not LookupPrivilegeValue(nil, SE_DEBUG_NAME, tp.Privileges[0].Luid)) then bError := True;
    if bError then SPISLog('SPIS - LookupPrivilegeValue failed (' + SysErrorMessage(GetLastError) + ').', True);
    tp.PrivilegeCount := 1;
    tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
    DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, nil, SecurityIdentification, TokenPrimary, hUserTokenDup);
    SetTokenInformation(hUserTokenDup, TokenSessionId, Pointer(dwSessionId), SizeOf(DWORD));
    if (not AdjustTokenPrivileges(hUserTokenDup, FALSE, @tp, SizeOf(TOKEN_PRIVILEGES), nil, nil)) then bError := True;
    if bError then SPISLog('SPIS - AdjustTokenPrivileges failed (' + SysErrorMessage(GetLastError) + ').', True);
    if (GetLastError() = ERROR_NOT_ALL_ASSIGNED) then bError := True;
    if bError then SPISLog('SPIS - AdjustTokenPrivileges: ERROR_NOT_ALL_ASSIGNED (' + SysErrorMessage(GetLastError) + ').', True);
    lpEnv := nil;
    if (CreateEnvironmentBlock(lpEnv, hUserTokenDup, TRUE)) then
      dwCreationFlags := dwCreationFlags or CREATE_UNICODE_ENVIRONMENT
    else
      lpEnv := nil;
    if not Assigned(lpEnv) then SPISLog('SPIS - CreateEnvironmentBlock failed (' + SysErrorMessage(GetLastError) + ').', True);
    try
      UniqueString(strProcess);
      if not CreateProcessAsUser(hUserTokenDup, nil, PChar(strProcess), nil, nil, FALSE,
        dwCreationFlags, lpEnv, PChar(ExtractFilePath(strProcess)), si, pi) then bError := True;
      if bError then 
        SPISLog('SPIS - CreateProcessAsUser failed (' + SysErrorMessage(GetLastError) + ').', True)
      else
        SPISLog('Started process in ' + IntToStr(dwSessionId) + ' using token from ' + IntToStr(winlogonPid) + '.');
      try
        try CloseHandle(hProcess); except {} end;
        try CloseHandle(hUserToken); except {} end;
        try CloseHandle(hUserTokenDup); except {} end;
        try CloseHandle(hPToken); except {} end;
      except
        {}
      end;
    finally
      DestroyEnvironmentBlock(lpEnv);
    end;
  except
    on E: Exception do
    begin
      bError := True;
      if not (E is EAbort) then
        SPISLog('SPIS - ' + E.Message + ' (' + SysErrorMessage(GetLastError) + ').', True);
    end;
  end;
  Result := not bError;
end;

function GetProcessID(strProcess: String; iSessionID: Integer = -1): DWORD;
var dwSessionId, winlogonSessId: DWord;
  hsnap: THandle;
  procEntry: TProcessEntry32;
  myPID: Cardinal;
begin
  Result := 0;
  if not InitProcLibs then Exit;
  { check running processes and return ID of process in current session... }
  if iSessionID = -1 then
    dwSessionId := WTSGetActiveConsoleSessionId
  else
    dwSessionId := iSessionID;
  hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if (hSnap = INVALID_HANDLE_VALUE) then Exit;
  strProcess := UpperCase(ExtractFileName(strProcess));
  myPID:= GetCurrentProcessId;
  procEntry.dwSize := sizeof(TProcessEntry32);
  if (not Process32First(hSnap, procEntry)) then Exit;
  repeat
    if (procEntry.th32ProcessID <> myPID) and ((UpperCase(procEntry.szExeFile) = strProcess) or
      (UpperCase(ExtractFileName(procEntry.szExeFile)) = strProcess)) then
    begin
      winlogonSessId := 0;
      if (ProcessIdToSessionId(procEntry.th32ProcessID, winlogonSessId) and (winlogonSessId = dwSessionId)) then
      begin
        Result := procEntry.th32ProcessID;
        break;
      end;
    end;
  until (not Process32Next(hSnap, procEntry));
end;

Does anyone know why it would fail, or whether there is a way of working out what is happening in the API with this call?


回答1:


thank you all so much for your help, I finally found the problem, the process I was starting statically linked a DLL (specifically aw_sas64.dll), this worked on most machines but not others, I'm still unsure why (the DLL is in the same folder as the EXE).

I couldn't get the DLL to work by dynamically linking it (although the 32-bit version dynamically linked OK), but once I'd commented the static link and usage out the process was started OK by the above procedure.

Again, big thanks to everyone, I still have a few problems left but this solves the mystery.



来源:https://stackoverflow.com/questions/39665084/createprocessasuser-is-successful-but-no-process-is-created

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!