Windows服务——Session0穿透

前言

    做WindowsAPI编程最重要的就是要多查MSDN。

    当然,如果没有找到前辈们提供的代码,再怎么查都是白搭。

Session0隔离

    简单来说就是,Windows将应用程序根据Windows账户分为了多个Session,比如:Administor打开的进程可能属于Session1,而另一个账户Civilian打开的进程就属于Session2。

    系统中还存在一种特殊的Session,那就是Windows服务进程,它属于Session0。在在Windows Vista及以后的操作系统中,服务进程无法再与用户进程有交互式操作,也就是Windows服务里无法打开带有UI界面的程序。因此就存在了Session隔离问题。

    之前的两篇介绍了Windows服务与守护进程,那么如何将他们结合在一起呢?这就需要实现Session0穿透。

Session0穿透

    在网上查找关于Session0的信息,会有很多详尽的代码和介绍,但大多都是原封不动的转载。转来转去都是同一篇文章。

    我也使用过流传最广的那套代码,但是没有成功。

    后来我发现了另一种令牌获取策略,并且在Windows10系统上实现了该功能。需要说明的是,代码中的令牌获取函数,CreateProcessAsUser函数,都需要对Windows账户提权。不然,你使用Marshal.GetLastWin32Error()函数时,会经常得到“2”、“1314”等错误值,表面上是文件未找到,实际上是用户权限不足。

    用户权限可以再用户策略中直接设置,也可以通过编程的方式提权…

权限对应关系:

  • SE_INCREASE_QUOTA_NAME:调整进程的内存配额
  • SE_ASSIGNPRIMARYTOKEN_NAME:替换进程级令牌

以下是对CreateProcessAsUser函数的介绍:

Creates a new process and its primary thread. The new process runs in the security context of the user represented by the specified token.

Typically, the process that calls the CreateProcessAsUser function must have the SE_INCREASE_QUOTA_NAME privilege and may require the SE_ASSIGNPRIMARYTOKEN_NAME privilege if the token is not assignable. If this function fails with ERROR_PRIVILEGE_NOT_HELD (1314), use the CreateProcessWithLogonW function instead. CreateProcessWithLogonW requires no special privileges, but the specified user account must be allowed to log on interactively. Generally, it is best to use CreateProcessWithLogonW to create a process with alternate credentials.

常用调试策略

  1. 在每个WindowsAPI调用之后,判断成功与否,使用Marshal.GetLastWin32Error()函数获取错误码。

     bool result = CreateProcessAsUser(hUserTokenDup, // client's access token
             null, // file to execute
             applicationName, // command line
             ref sa, // pointer to process SECURITY_ATTRIBUTES
             ref sa, // pointer to thread SECURITY_ATTRIBUTES
             false, // handles are not inheritable
             dwCreationFlags, // creation flags
             IntPtr.Zero, // pointer to new environment block 
             null, // name of current directory 
             ref si, // pointer to STARTUPINFO structure
             out procInfo // receives information about new process
         );
    
         if (!result)
         {
             int errorCode = Marshal.GetLastWin32Error();
             Console.WriteLine("error{0}",errorCode);
         }
    
  2. 观察获取到的句柄的值,如果值为0x00000000000,这种一般都是权限不足导致。

  3. 多百度,最好能翻墙。

结语

    代码没有太多,我就不做解释给大家了。分享几个链接,以及我的代码。

https://www.cnblogs.com/buli93/p/7086440.html

https://www.cnblogs.com/KevinSong/p/5102365.html

https://www.codeproject.com/Articles/4863/LSA-Functions-Privileges-and-Impersonation

源码:https://pan.baidu.com/s/1Dtl_YS5mzhIEqoiK5v1-VA

猜你喜欢

转载自blog.csdn.net/qq_40404477/article/details/100799878