Monday, March 05, 2007 11:08 PM bart

Windows Vista - WinSta0 isolation explained

Time for another security feature in Windows Vista: WinSta0 isolation. The first question that might pop up in your head is "So, what exactly is WinSta0?". Keith Brown has the answer.

The problem with WinSta0 is the possibility for Windows Services to display a UI prompt in the window station. Pre-Vista, this prompt just appears on top of the desktop of the user logged on to the system. Because of this, the service is exceeding its boundary of isolation and the inware user is providing information across that "trust boundary".

Windows Vista reduces this risk by isolating WinSta0 from the active user's desktop; a user has to provide his/her consent to switch to the bare WinSta0 when that screams for attention (which is detected by an executable called UI0Detect.exe as displayed below):

When you see this kind of message, the app you're dealing with has "partial incompatibility with Windows Vista". The message to developers: fix it - Windows doesn't like the old approach anymore! An example I've been faced with in practice is the HP LaserJet 1020 software that uses WinSta0 to show out of paper messages and other printer maintenance messages.

In this post, I'm showing you the code for a demo of a WinSta0 isolation demo I gave some time ago, together with demonstration instructions.


Step 1 - Creating an interactive Windows Service

So, for sake of the demo, let's create something we really shouldn't have created: an interactive Windows Service. Open Visual Studio 2005 and create a new Windows Service project called "WinSta0Inspector" in C#:

Next, go to Service1.cs and change the service name to WinSta0Inspector:

Right-click the designer surface and choose Add Installer. This will create a new file ProjectInstaller.cs that makes the executable installutil.exe-able. In there, select the serviceProcessInstaller1 "control" and set the Account property to Local System (to make things really bad):

In order to make the service interactive, we'll create a simple Windows Form. Right click the project in the Solution Explorer, choose Add New Item and add a Windows Form called ExecuteCommand.cs. Design it so that it looks like this:

Hook up event handlers for both LinkLabels, with definitions like this:

private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { Process.Start("cmd.exe"); } private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { DialogResult = DialogResult.OK; }

Don't forget to import System.Diagnostics in order to have access to the Process class. Now go back to Service1.cs and switch to the code view. Define the Service1 class as follows:

public partial class Service1 : ServiceBase { private ExecuteCommand dialog = new ExecuteCommand(); public Service1() { InitializeComponent(); } protected override void OnStart(string[] args) { } protected override void OnCustomCommand(int command) { MessageBox.Show("Welcome to WinSta0.", "WinSta0 is calling you!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); dialog.ShowDialog(); } }

You'll need to import System.Windows.Forms to have access to MessageBox. This completes our interactive service.


Step 2 - Installing it

Compile the solution and switch to a Visual Studio 2005 Command Prompt which runs elevated with administrator privileges. Install the service using installutil -i WinSta0Inspector.exe. Then open the Services MMC snap-in (services.msc), locate the WinSta0Inspector service and change its properties to make it interactive:

Command-line freaks could also use the following command to install the service directly as an interactive service; no need to run installtutil then, just do this:

sc create WinSta0Inspector binPath= WinSta0Inspector.exe type= interact DisplayName= "WinSta0 Inspector"


Step 3 - Action!

In order to see it in action, start the service and send it a custom command. You could write another app to send the custom command using the System.Service.ServiceController::ExecuteCommand method, but sc.exe has everything we need:

First, we started the service using net start WinSta0Inspector. Next, we sent a command to the service by using sc control WinSta0Inspector 129 (valid commands should be higher than 128, other values are system-reserved). Right away you'll see the Interactive services dialog detection dialog popping up in the background:

Click Show me the message and Vista will bring you to the raw WinSta0 environment which should look somewhat like this:

Press OK in our message box; the WinForms dialog will show up now:

Feel free to take a look around WinSta0 using the command-prompt link on the form. For example, run whoami /all to find out about your SYSTEM power :-)

If you have a hacker's mindset you might find HKLM\SECURITY\SAM an attractive place to visit while you're the Windows ├╝bermensch :o. Below you can see a few other screenshots of what it is like to be in WinSta0 (e.g. how did I create the screenshots?):


Have fun! | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Filed under: ,


# re: Windows Vista - WinSta0 isolation explained

Tuesday, March 06, 2007 8:30 PM by Dennes

Hi, Bart !

Another great article ! I already talked about session 0 isolation but not with a demonstration like this.

But It seems you created the wrong way, the wrong comunication with the service.

So :

1) What's the right way ? I saw something about API's to call windows cross sessions, but I don't remember

2) This wrong way can be disabled through GPO's can't It ?

Thanks !

# re: Windows Vista - WinSta0 isolation explained

Wednesday, March 07, 2007 2:44 AM by bart

Hi Dennes,

Thx for the feedback. Whenever I write something on my blog I try to stick to the core message, in casu WinSta0 isolation. So I didn't want to bloat the code with communication stuff and another app just to send a message to the Windows service. For simple control messages, command codes are still a useful communication mechanism for services. Nevertheless, when you need a more robust and flexible way (in terms of parameterization) other solutions exist, like named pipes, .NET Remoting, WCF, raw TCP communication, MSMQ, etc. Just pick one :-). In today's technology state I tend to opt for WCF because of its RPC-style that allows to send natural-feeling parameterized messages from endpoint A to endpoint B, and because it encapsulates all of the other mentioned low-level technologies.

To conclude, I'd rather say there's no such thing as a "wrong way" (even more when considering the extenuating circumstances of demo stuff) but there always might be better ways :-).


# re: Windows Vista - WinSta0 isolation explained

Wednesday, March 07, 2007 7:19 AM by dotnetjunkie

I think what Dennes really meant by "wrong way", was the same thing as you were referring to in this quote from your blog post:

"When you see this kind of message, the app you're dealing with has "partial incompatibility with Windows Vista". The message to developers: fix it "

So, how to fix it and have full compatibility with Vista :)

# re: Windows Vista - WinSta0 isolation explained

Wednesday, March 07, 2007 7:37 AM by Dennes

Thanks Bart, that's a good article. Just to clarify (my english is terrible) by "wrong way" I mean (I understood that...) the old way services talked with the user, wich in windows Vista generates these messages, exactly what your article demonstrate.

Thanks !



# re: Windows Vista - WinSta0 isolation explained

Wednesday, March 07, 2007 9:37 AM by bart

Hi folks,

Now I see what issue you're referring to. Basically, you should make sure that WinSta0 doesn't do UI work at all - as a rule of thumb, a Windows Service shouldn't have a reference to System.Windows.Forms. In order to allow communication, a process in the user's session should be active and listening for messages coming from the service, e.g. via .NET Remoting, WCF, named pipes, etc. When no direct interaction is required, logging to the Windows Event Logs might be a sufficient level of "communication", together with some configuration tool to perform the service's configuration.