Skip to main content

How does it work internally?

When gsudo is invoked, an elevated instance of gsudo in service mode is launched (with Verb='RunAs'). The service will allow one elevation (or many if the credentials cache is enabled).

Elevation modes

To achieve the sudo functionality, gsudo has 4 different mechanisms implemented.

In a way, each one superseded the previous one, leading to the current default TokenSwitch.

In the source code, each mode is implemented as one IProcessRenderer (running non-elevated) and a IProcessHost (running in the elevated service).

Communication between both is done via two Named Pipes in the ProtectedPrefix\Administrators namespace. One for data and another for control. Each elevation mode defines the "communication protocol", what is sent thru each pipe.

These are the elevations modes implemented in gsudo, in the order they were implemented:

Piped mode

This is a naive mechanism, implemented first more like a proof of concept (that later proved to be useful).

The elevated PipedProcessHost runs the command with its I/O redirected (For example as in (input) > Elevated Process > (output)), and sends all I/O to the unelevated via named pipes.

The PipedProcessRenderer captures input and display the output on screen. In this mode, keyboard input is managed by the client console (without knowledge of which app you are running), and not by the elevated command/shell, hence TAB key auto-completion doesn't work. The user experience is far from ideal.

The process is created with the elevated Environment Variables.

Pros:

  • Redirection works

Cons:

  • Apps always run in redirected mode.
  • Input only support of chars, not key presses.
  • Struggles with encoding, especially explicit code page changes.

VT mode (PseudoConsole)

Side story

It was the day Microsoft announced Pseudo Consoles for Windows, I asked myself: What can PseudoConsoles be used for? a sudo for windows!!

The elevated instance runs a VT PseudoConsole, and sends all I/O it to the unelevated via named pipes.

The process is created with the elevated Environment Variables.

Pros:

  • Full featured console screen
  • Full input support.

Cons:

  • Good but not best performance (compared with the following alternatives).
  • Apps always runs in console mode (not redirected). Redirection could be done but the result would be more like console screen recording than process redirection.
  • Struggles with encoding IF encoding or code page changes.
  • Console screen resizing still not implemented.

Attached mode

The elevated window 'attaches' to the non-elevated. The bridge is actually done by Windows and ConHost. Doesn't work with I/O redirected.

The process is created with the elevated Environment Variables.

Pros:

  • Native console functioning. Full speed, colors, input, etc.
  • No encoding issues

Cons:

  • Does not support redirection

TokenSwitch Mode

This is the current default mode. Using undocumented kernel32 Apis, the unelevated instance creates the new process in paused mode, then the elevated host replaces it's primary token, and its execution is resumed.

The process is created with the non-elevated context/Environment Variables.

Pros:

  • Native console functioning. Full speed, colors, input, etc.
  • No encoding issues
  • Supports redirection

Cons:

  • (debatable) The new process inherits the non-elevated environment variables.

This last item is a confirmed problem when the elevation is done as somebody else (i.e. the current user is not admin and RunAs asks for credentials). To avoid it, and only in this scenario, this mode falls back to Attached mode (if no redirection) or Piped mode (if redirection exists).

Should the elevated process inherit the same environment variables?

Great question. If your user is a local admin, i.e. you elevate as yourself, both contexts have similar if not same env vars.

But if you are not local admin, UAC will prompt for credentials, and then you will be running as another user, so env var isolation becomes more important. On Linux/Unix, you always sudo as somebody else and env vars are not preserved, unless -E is specified. gsudo provides --copyEV to copy all the vars, except %USERNAME%.

How do I force one mode over the other?

You shouldn't. gsudo should do a better job choosing than you. Still reading? Ok... I will tell you. But this is marked as deprecated and can change anytime.

To force Attached mode use --attached or permanently with gsudo config ForceAttachedConsole True

To force Piped mode use --piped or permanently with gsudo config ForcePipedConsole True

To force VT mode use --vt or permanently with gsudo config ForceVTConsole True

Use only one at the same time.