2016-09-23 25 views
0

콘솔 세션에서 프로세스를 생성하는 서비스 응용 프로그램 (WTSGetActiveConsoleSessionId)을 사용하여 컴퓨터에 대한 데스크톱 제어 스타일 액세스를 허용합니다. 이것은 대부분의 상황에서 잘 작동하지만 CreateProcessAsUser의 결과와 관련하여 프로세스를 성공적으로 생성하는 것으로 보이는 VM이 ​​있지만 프로세스가 생성되지 않습니다.CreateProcessAsUser는 성공했지만 프로세스가 생성되지 않았습니다.

서비스는 LocalSystem 계정으로 실행됩니다. 시작중인 프로세스가 아직 실행되고 있지 않습니다. 실행중인 바이러스 방지 프로그램이 없습니다. 우리는 Windows Server 2008 R2에서만이 동작을 보았습니다 (하지만 독점적이지는 않습니다).

다음과 같이 우리가 사용하는 코드는 : 그것은 실패 이유

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; 

사람이 알고 있나요, 또는이 호출과 API에 무슨 일이 일어나고 있는지 운동하는 방법이 있는지?

+1

WTSEnumerateSessions를 사용하고 WTSGetActiveConsoleSession 대신 첫 번째 활성 세션을 검색하십시오. RDP 연결에는 작동하지 않습니다. – FredS

+0

"이 호출로 API에서 어떤 일이 일어나고 있는지 알아내는 방법?" - 일시 중지 상태에서 프로세스를 생성하고 디버거를 새로 만든 프로세스에 연결 한 후이 작업을 재개해야합니다. – RbMm

+2

이 코드는 읽을 수 없습니다. 오류 처리는 불가능합니다. –

답변

0

모두 도움을 주셔서 감사합니다. 드디어 문제를 발견했습니다. 정적으로 DLL (특히 aw_sas64.dll)을 연결하기 시작한 프로세스입니다.이 작업은 대부분의 컴퓨터에서 수행되었지만 다른 작업은 수행되지 않았습니다. (DLL은 EXE와 같은 폴더에 있습니다).

DLL을 동적으로 연결하여 작동하도록 DLL을 가져올 수 없지만 (32 비트 버전이 동적으로 연결되었지만) 일단 정적 링크와 사용법을 주석 처리하면 위 절차에 따라 OK로 시작됩니다. .

다시 한 번 큰 고마워, 나는 여전히 몇 가지 문제가 남아 있지만 이것은 수수께끼를 해결합니다.