[Go] address Vista and Win7 Interactive desktop permissions issues in Windows Services: Penetrating Session 0 isolation

Source: Internet
Author: User
Tags sessions

Service is no stranger to everyone, it is an important part of the Windows operating system. We can think of the service as a special application that starts and stops its work with the system's "turn-off" and "Start-stop", during which no user involvement is required.

Windows Services performs a variety of tasks in the background, supporting our daily desktop operations. Sometimes it may be necessary for the service to interact with the user for information or interface, which is not a problem in the XP era, but since Vista begins you will find that this approach does not seem to work.

Session 0Isolation experiment

Here is a service called Alertservice, its role is to send a prompt to the user dialog box, we look at the service in Windows 7 what happens.

Using system.serviceprocess;using system.windows.forms;namespace alertservice{public    partial class Service1: ServiceBase    {public        Service1 ()        {            InitializeComponent ();        }        protected override void OnStart (string[] args)        {            MessageBox.Show ("A message from Alertservice.");        protected override void OnStop ()        {        }}}    

After the program is compiled, it is loaded into the system service via InstallUtil :

In the service properties, tick "allow service to interact with desktop", which enables Alertservice to interact with desktop users.

When the Alertservice service starts in Service Manager, an icon will flash in the taskbar:

Clicking the icon displays the following window, prompting a program (Alertservice) that is trying to display the information and whether it needs to be browsed:

Try to click on "View the message" will display the interface (in fact, this interface I have not been able to operate from the current desktop, is the virtual PC screenshot, the reason please continue to read). Note that the desktop background that you can find is not the default desktop background for Windows 7, which indicates that Alertservice is not the same as the session of the desktop system, which is the result of Session 0 isolation.

Session 0Isolation principle

In the era of Windows XP, Windows Server 2003, or earlier Windows systems, services and applications run in the same session when the first user logs on to the system. This is session 0 as shown:

However, this way of running increases the security risk of the system, because the service is running with elevated user rights, and the application is often run by ordinary users who do not have an administrator, the danger is obvious.

Starting with Vista, Session 0 contains only system services, while other applications run through separate sessions to isolate service and application to improve system security. As shown in the following:

This makes it impossible for session 0 to interact with other sessions, and the Information window, UI window, and so on are not available to the desktop user through the service. That's why I just said that the diagram is not going through the current desktop.

SessionCheck

During the actual development process, you can check which session the service or program is in through process Explorer , and you will not encounter session 0 isolation issues. We found the previously loaded Alertservice service in the services and right-click Properties to see its session status.

You can see that Alertservice is in session 0:

Look again at the Outlook application:

Obviously in Windows 7 the services and applications are in different sessions, and they are separated by a protective wall, and in the next article you will learn how to cross the wall to make the service interoperate with desktop users.

If you do need services to interact with desktop users during development, you can complete the interaction by bypassing session 0 's isolation through the Remote Desktop Services API.

For simple interactions, the service can display the message window on the user session via the wtssendmessage function. For some complex UI interactions, you must call CreateProcessAsUser or other methods (WCF,. NET remoting, etc.) for cross-session communication, creating an application interface on the desktop user.

WtssendmessageFunction

If the service simply sends a message window to the desktop user session, it can be implemented using the Wtssendmessage function. First, add a Interop.cs class to the previous downloaded code and add the following code to the class:

public static IntPtr Wts_current_server_handle = intptr.zero;public static void ShowMessageBox (String message, string tit Le) {    int resp = 0;    Wtssendmessage (        wts_current_server_handle,         Wtsgetactiveconsolesessionid (),        title, title. Length,         message, message. Length,         0, 0, out resp, false);} [DllImport ("kernel32.dll", SetLastError = True)]public static extern int Wtsgetactiveconsolesessionid (); [DllImport ("Wtsapi32.dll", SetLastError = True)]public static extern bool Wtssendmessage (    IntPtr hserver,    int SessionId,    string ptitle,    int titlelength,    string pMessage,    int messagelength,    int Style,    int Timeout, out    int presponse,    bool bwait);

The wtssendmessage is called in the ShowMessageBox function to send the information window so that we can use it in the service's OnStart function and open the Service1.cs to add the following code:

protected override void OnStart (string[] args) {    Interop.showmessagebox ("This is a message from Alertservice.",
"Alertservice Message");}

After compiling the program, restart the Alertservice service in Service Manager, where you can see that the message window is displayed on the current user's desktop instead of Session 0.

CreateProcessAsUserFunction

If you want to create a complex UI program interface from a service to a desktop user session, you need to use the CreateProcessAsUser function to create a new process for the user to run the corresponding program. Open the Interop class and continue adding the following code:

public static void CreateProcess (String app, string path) {bool result; IntPtr Htoken = WindowsIdentity.GetCurrent ().    Token;    IntPtr Hdupedtoken = IntPtr.Zero;    process_information pi = new process_information ();    Security_attributes sa = new security_attributes (); Sa.    Length = marshal.sizeof (SA);    Startupinfo si = new Startupinfo ();    SI.CB = marshal.sizeof (SI);    int dwsessionid = Wtsgetactiveconsolesessionid ();        result = Wtsqueryusertoken (Dwsessionid, out htoken);    if (!result) {ShowMessageBox ("Wtsqueryusertoken failed", "Alertservice Message"); } result = Duplicatetokenex (Htoken, generic_all_access, ref SA, (int) Security_impe Rsonation_level. Securityidentification, (int) token_type.    Tokenprimary, ref Hdupedtoken);    if (!result) {ShowMessageBox ("Duplicatetokenex failed", "Alertservice Message");    } IntPtr lpenvironment = IntPtr.Zero; result = CreateenvironmentbloCK (out Lpenvironment, Hdupedtoken, false);    if (!result) {ShowMessageBox ("Createenvironmentblock failed", "Alertservice Message");                         } result = CreateProcessAsUser (Hdupedtoken, app,                         String.Empty, ref SA, ref SA, False, 0, IntPtr.Zero,    Path, ref si, ref pi);        if (!result) {int error = Marshal.GetLastWin32Error ();        String message = String.Format ("CreateProcessAsUser error: {0}", error);    ShowMessageBox (Message, "Alertservice message");    } if (pi.hprocess! = IntPtr.Zero) CloseHandle (pi.hprocess);    if (pi.hthread! = IntPtr.Zero) CloseHandle (Pi.hthread); if (hdupedtoken! = IntPtr.Zero) CloseHandle (Hdupedtoken);}    [StructLayout (layoutkind.sequential)]public struct startupinfo{public Int32 CB;    public string lpreserved;    public string lpDesktop;  public string Lptitle;  Public Int32 DwX;    Public Int32 DwY;    Public Int32 dwxsize;    Public Int32 Dwxcountchars;    Public Int32 Dwycountchars;    Public Int32 Dwfillattribute;    Public Int32 dwFlags;    Public Int16 Wshowwindow;    Public Int16 CbReserved2;    Public IntPtr LpReserved2;    Public IntPtr hStdInput;    Public IntPtr Hstdoutput; Public IntPtr Hstderror;}    [StructLayout (layoutkind.sequential)]public struct process_information{public IntPtr hprocess;    Public IntPtr Hthread;    Public Int32 Dwprocessid; Public Int32 dwThreadID;}    [StructLayout (layoutkind.sequential)]public struct security_attributes{public Int32 Length;    Public IntPtr Lpsecuritydescriptor; public bool bInheritHandle; Public enum security_impersonation_level{securityanonymous, Securityidentification, Securityimpersonation, Se curitydelegation}public enum token_type{tokenprimary = 1, tokenimpersonation}public const int generic_all_access = 0x10000000 [DllImport ("Kernel32.dll", SetlasterroR = True, CharSet = CharSet.Auto, callingconvention = callingconvention.stdcall)]public static extern bool CloseHandle ( INTPTR handle); [DllImport ("advapi32.dll", SetLastError = true, CharSet = CharSet.Ansi, callingconvention = Callingconvention.stdcall)]    public static extern bool CreateProcessAsUser (IntPtr htoken, String lpapplicationname, String lpcommandline, Ref security_attributes Lpprocessattributes, ref security_attributes lpthreadattributes, bool BInheritHandle, Int dwCreationFlags, IntPtr lpenvrionment, string lpcurrentdirectory, ref startupinfo Lpstartupinfo, ref proces S_information lpprocessinformation); [DllImport ("advapi32.dll", SetLastError = True)]public static extern bool Duplicatetokenex (IntPtr Hexistingtoken, I    Nt32 dwdesiredaccess, ref security_attributes lpthreadattributes, Int32 impersonationlevel, Int32 Dwtokentype, Ref INTPTR Phnewtoken); [DllImport ("Wtsapi32.dll", setlasterror=true)]public static extern bool Wtsqueryusertoken (Int32 sessionId, out IntPtr Token);     [DllImport ("Userenv.dll", SetLastError = True)]static extern bool Createenvironmentblock (out IntPtr lpenvironment, INTPTR Htoken, bool binherit);

The CreateProcess function also involves the use of Duplicatetokenex, Wtsqueryusertoken, and Createenvironmentblock functions, and interested friends can learn through MSDN. Once the CreateProcess function is created, you can actually invoke the application through it, and go back to Service1.cs and modify OnStart to open a CMD window. The following code:

protected override void OnStart (string[] args) {    interop.createprocess ("cmd.exe", @ "C:\Windows\System32\");}

Recompile the program and start the Alertservice service to see the interface. At this point, we have been able to solve the session 0 isolation problem through some simple methods. You can also use technologies such as WCF to complete a number of more complex cross-session communication methods, in Windows 7 and Vista systems to serve the interaction with desktop users.

[Go] address Vista and Win7 Interactive desktop permissions issues in Windows Services: Penetrating Session 0 isolation

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.