Bypassing Session 0 Isolation in Windows Server 2008 -- successful, but still not visible

Sean Anderson picture Sean Anderson · Apr 4, 2011 · Viewed 7.3k times · Source

I am using the code located here basically as-is to start a process. This code works flawlessly in Vista/7 -- If I start a process using System.Diagnostics.Process.Start() I see that it starts, but is not visible because it is located in Session 0. Using this code, I see the process start in Session 1 (the same session I start programs in manually in Vista/7).

Now, in Server 2008, when I start a program manually it opens up into Session 2. When I do not use this code, I see the process still start into Session 0. When I use this code, it starts into Session 1 -- but is not visible. Presumably this is because it is not started in the same session as I, and thus is existing on an 'invisible' desktop elsewhere.

Has anyone encountered this problem before? The blog seems relatively popular, so I am hard-pressed to believe that this issue hasn't been addressed already. The server I am working on is 64-bit architecture, my win 7 machine is 32-bit. I don't think that makes a difference though, the blog indicates that the solution works on both architectures.

Answer

Sean Anderson picture Sean Anderson · Oct 8, 2013

You will need to use the ID override if you are attempting to bypass UAC through Remote Desktop. The reason for this is because the Microsoft API method WTSGetActiveConsoleSessionId fails to provide correct information when using Remote Desktop:

The session identifier of the session that is attached to the physical console.

So, to bypass Vista/Win7/2k8 UAC you can just use the basic Ping function -- it will start the process under LOCAL SYSTEM with the correct SID to be visible by the user.

If you notice this not occurring you can go into process manager, inspect the SID, and use ping w/ userIDOverride to specify the correct SID.

private static readonly ILog Logger
    = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

String applicationName = String.Empty;
bool result; 

public Access()
{
    Logger.Debug("I am now in Access Constructor");
}

public void Ping(string address)
{
    Logger.Debug("I am now in Ping");

    applicationName = @"C:\Windows\System32\ping.exe " + address + " -t";
    Logger.Debug(String.Format("Application Name: {0} ", applicationName));

    ApplicationLoader.PROCESS_INFORMATION procInfo;
    result = ApplicationLoader.StartProcessAndBypassUAC(
        applicationName,
        out procInfo,
        null);

    Logger.Debug(String.Format(
        "Result of StartProcessAndBypassUAC: {0} ", result.ToString()));
}

public void Ping(string address, int userIDOverride)
{
    Logger.Debug("I am now in Ping w/ override");

    applicationName = @"C:\Windows\System32\ping.exe " + address + " -t";
    Logger.Debug(String.Format("Application Name: {0} ", applicationName));

    ApplicationLoader.PROCESS_INFORMATION procInfo;
    result = ApplicationLoader.StartProcessAndBypassUAC(
        applicationName,
        out procInfo,
        userIDOverride);

    Logger.Debug(String.Format(
        "Result of StartProcessAndBypassUAC: {0} ", result.ToString()));
}