Merge pull request #924 from immense/feature/show-consent-winlogon

Allow remote control consent and chat on Windows Login screen.
This commit is contained in:
Jared Goodwin 2024-08-07 08:19:41 -07:00 committed by GitHub
commit e69fa4d01b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 52 additions and 29 deletions

View File

@ -49,8 +49,6 @@ public class AppLauncherWin : IAppLauncher
$" --org-name \"{orgName}\"" +
$" --org-id \"{orgId}\"",
targetSessionId: -1,
forceConsoleSession: false,
desktopName: "default",
hiddenWindow: false,
out var procInfo);
if (!result)
@ -122,8 +120,6 @@ public class AppLauncherWin : IAppLauncher
$" --session-id \"{sessionId}\"" +
$" --access-key \"{accessKey}\"",
targetSessionId: targetSessionId,
forceConsoleSession: Shlwapi.IsOS(OsType.OS_ANYSERVER) && targetSessionId == -1,
desktopName: "default",
hiddenWindow: false,
out _);
if (!result)
@ -180,8 +176,6 @@ public class AppLauncherWin : IAppLauncher
$" --viewers {string.Join(",", viewerIds)}",
targetSessionId: targetSessionID,
forceConsoleSession: Shlwapi.IsOS(OsType.OS_ANYSERVER) && targetSessionID == -1,
desktopName: "default",
hiddenWindow: false,
out _);

View File

@ -104,11 +104,9 @@ public class Win32Interop
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;
@ -117,21 +115,7 @@ public class Win32Interop
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");
@ -171,7 +155,7 @@ public class Win32Interop
// 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;
@ -208,6 +192,53 @@ public class Win32Interop
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);

View File

@ -154,8 +154,6 @@ public static class IServiceProviderExtensions
commandLine,
-1,
false,
"default",
true,
out var procInfo);
Console.WriteLine($"Elevate result: {result}. Process ID: {procInfo.dwProcessId}.");
Environment.Exit(0);