Skip to content

Commit

Permalink
Merge pull request #924 from immense/feature/show-consent-winlogon
Browse files Browse the repository at this point in the history
Allow remote control consent and chat on Windows Login screen.
  • Loading branch information
bitbound authored Aug 7, 2024
2 parents 8417df7 + 232ab26 commit e69fa4d
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 29 deletions.
6 changes: 0 additions & 6 deletions Agent/Services/Windows/AppLauncherWin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@ public async Task<int> LaunchChatService(string pipeName, string userConnectionI
$" --org-name \"{orgName}\"" +
$" --org-id \"{orgId}\"",
targetSessionId: -1,
forceConsoleSession: false,
desktopName: "default",
hiddenWindow: false,
out var procInfo);
if (!result)
Expand Down Expand Up @@ -122,8 +120,6 @@ await hubConnection.SendAsync("DisplayMessage",
$" --session-id \"{sessionId}\"" +
$" --access-key \"{accessKey}\"",
targetSessionId: targetSessionId,
forceConsoleSession: Shlwapi.IsOS(OsType.OS_ANYSERVER) && targetSessionId == -1,
desktopName: "default",
hiddenWindow: false,
out _);
if (!result)
Expand Down Expand Up @@ -180,8 +176,6 @@ public async Task RestartScreenCaster(string[] viewerIds, string sessionId, stri
$" --viewers {string.Join(",", viewerIds)}",

targetSessionId: targetSessionID,
forceConsoleSession: Shlwapi.IsOS(OsType.OS_ANYSERVER) && targetSessionID == -1,
desktopName: "default",
hiddenWindow: false,
out _);

Expand Down
73 changes: 52 additions & 21 deletions Desktop.Native/Windows/Win32Interop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,9 @@ public static nint OpenInputDesktop()

public static bool CreateInteractiveSystemProcess(
string commandLine,
int targetSessionId,
bool forceConsoleSession,
string desktopName,
bool hiddenWindow,
out PROCESS_INFORMATION procInfo)
int targetSessionId,
bool hiddenWindow,
out PROCESS_INFORMATION procInfo)
{
uint winlogonPid = 0;
var hUserTokenDup = nint.Zero;
Expand All @@ -117,21 +115,7 @@ public static bool CreateInteractiveSystemProcess(

procInfo = new PROCESS_INFORMATION();

// If not force console, find target session. If not present,
// use last active session.
var dwSessionId = Kernel32.WTSGetActiveConsoleSessionId();
if (!forceConsoleSession)
{
var activeSessions = GetActiveSessions();
if (activeSessions.Any(x => x.Id == targetSessionId))
{
dwSessionId = (uint)targetSessionId;
}
else
{
dwSessionId = activeSessions.Last().Id;
}
}
var dwSessionId = ResolveWindowsSession(targetSessionId);

// Obtain the process ID of the winlogon process that is running within the currently active session.
var processes = Process.GetProcessesByName("winlogon");
Expand Down Expand Up @@ -171,7 +155,7 @@ public static bool CreateInteractiveSystemProcess(
// interaction with the new process.
var si = new STARTUPINFO();
si.cb = Marshal.SizeOf(si);
si.lpDesktop = @"winsta0\" + desktopName;
si.lpDesktop = @"winsta0\" + ResolveDesktopName(dwSessionId);

// Flags that specify the priority and creation method of the process.
uint dwCreationFlags;
Expand Down Expand Up @@ -208,6 +192,53 @@ public static bool CreateInteractiveSystemProcess(
return result;
}

public static string ResolveDesktopName(uint targetSessionId)
{
var winDir = Environment.GetFolderPath(Environment.SpecialFolder.Windows);
var logonUiPath = Path.Combine(winDir, "System32", "LogonUI.exe");
var consentPath = Path.Combine(winDir, "System32", "consent.exe");

var isLogonScreenVisible = Process
.GetProcessesByName("LogonUI")
.Any(x => x.SessionId == targetSessionId && x.MainModule?.FileName.Equals(logonUiPath, StringComparison.OrdinalIgnoreCase) == true);

var isSecureDesktopVisible = Process
.GetProcessesByName("consent")
.Any(x => x.SessionId == targetSessionId && x.MainModule?.FileName.Equals(consentPath, StringComparison.OrdinalIgnoreCase) == true);

if (isLogonScreenVisible || isSecureDesktopVisible)
{
return "Winlogon";
}

return "Default";
}

public static uint ResolveWindowsSession(int targetSessionId)
{
var activeSessions = GetActiveSessions();
if (activeSessions.Any(x => x.Id == targetSessionId))
{
// If exact match is found, return that session.
return (uint)targetSessionId;
}

if (Shlwapi.IsOS(OsType.OS_ANYSERVER))
{
// If Windows Server, default to console session.
return Kernel32.WTSGetActiveConsoleSessionId();
}

// If consumer version and there's an RDP session active, return that.
if (activeSessions.Find(x => x.Type == WindowsSessionType.RDP) is { } rdSession)
{
return rdSession.Id;
}

// Otherwise, return the console session.
return Kernel32.WTSGetActiveConsoleSessionId();
}

public static void SetMonitorState(MonitorState state)
{
SendMessage(0xFFFF, 0x112, 0xF170, (int)state);
Expand Down
2 changes: 0 additions & 2 deletions Desktop.Shared/Startup/IServiceProviderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,6 @@ private static void RelaunchElevated()
commandLine,
-1,
false,
"default",
true,
out var procInfo);
Console.WriteLine($"Elevate result: {result}. Process ID: {procInfo.dwProcessId}.");
Environment.Exit(0);
Expand Down

0 comments on commit e69fa4d

Please sign in to comment.