2016-09-23 21 views
0

コンソールセッション(WTSGetActiveConsoleSessionId)でプロセスを起動し、マシンにデスクトップコントロールスタイルのアクセスを許可するサービスアプリケーションがあります。これはほとんどの状況でうまくいきますが、CreateProcessAsUserの結果が問題になる限り、プロセスを正常に作成するように見えるVMがいくつかありますが、プロセスは作成されません。CreateProcessAsUserは成功しましたが、プロセスは作成されません。

サービスはLocalSystemアカウントで実行されます。開始されているプロセスはまだ実行されていません。ウイルス対策プログラムは実行されていません。 Windows Server 2008 R2ではこの動作しか見ていません(ただし、これは排他的ではありません)。次のように

我々が使用するコードは次のとおりです。それが失敗、またはこの呼び出しをAPIで何が起こっているのかワークアウトの方法があるかどうかだろう、なぜ

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; 

誰でも知っていますか?

+1

WTSEnumerateSessionsを使用し、WTSGetActiveConsoleSessionの代わりに最初のアクティブなセッションを検索します。 RDP接続では機能しません。 – FredS

+0

"この呼び出しでAPIで何が起こっているかを調べる方法?" - サスペンド状態でプロセスを作成する必要があります。デバッガを新規作成したプロセスにアタッチしてから再開します。 – RbMm

+2

このコードは判読できません。エラー処理は不可能です。 –

答えて

0

私は最終的に問題を発見しました。私は静的にDLL(特にaw_sas64.dll)をリンクしていましたが、これはほとんどのマシンで動作しましたが、 (DLLはEXEと同じフォルダにあります)。

ダイナミックリンク(ただし、32ビットバージョンは動的にリンクされていますが)でもDLLを動作させることはできませんでしたが、上記の手順で静的リンクと使用方法をコメントしてから。

もう一度、皆様に感謝します。まだいくつかの問題が残っていますが、これは謎を解決します。

関連する問題