vista和win7在windows服务中交互桌面权限问题解决方法:穿透Sessi

2019-12-30 12:10:23于丽

WTSSendMessage 函数

如果服务只是简单的向桌面用户Session 发送消息窗口,则可以使用WTSSendMessage 函数实现。首先,在上一篇下载的代码中加入一个Interop.cs 类,并在类中加入如下代码:


public static void ShowMessageBox(string message, string title)
{
 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);

在ShowMessageBox 函数中调用了WTSSendMessage 来发送信息窗口,这样我们就可以在Service 的OnStart 函数中使用,打开Service1.cs 加入下面代码:


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

编译程序后在服务管理器中重新启动AlertService 服务,从下图中可以看到消息窗口是在当前用户桌面显示的,而不是Session 0 中。

vista,win7,桌面权限,Session

CreateProcessAsUser 函数

如果想通过服务向桌面用户Session 创建一个复杂UI 程序界面,则需要使用CreateProcessAsUser 函数为用户创建一个新进程用来运行相应的程序。打开Interop 类继续添加下面代码:


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_IMPERSONATION_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,
 SecurityDelegation
}

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,
 Int32 dwCreationFlags,
 IntPtr lpEnvrionment,
 string lpCurrentDirectory,
 ref STARTUPINFO lpStartupInfo,
 ref PROCESS_INFORMATION lpProcessInformation);

[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool DuplicateTokenEx(
 IntPtr hExistingToken,
 Int32 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);