小言_互联网的博客

C#穿透session隔离———Windows服务启动UI交互程序

273人阅读  评论(0)

 

在Windows服务里面启动其他具有界面的应用程序,需要穿透session隔离,尝试了很多种方法,都可行,现在一一列举下来,并写下几个需要注意的地方。

首先要将服务的Account属性设置为LocalSystem,安装服务后的登录身份则为本地系统账户

  • 再一个需要注意的是不要把Windows服务的程序放在C:\Users\Administrator\目录下运行,不然启动服务的时候会遇到权限问题,如下图

实现代码如下

  • 第一种方法

     调用方法

WinAPI_Interop.CreateProcess(path);//string path=@"C:\Users\Administrator\Text.exe";

    代码片段


  
  1. public class WinAPI_Interop
  2. {
  3. public static IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
  4. /// <summary>
  5. /// 服务程序执行消息提示,前台MessageBox.Show
  6. /// </summary>
  7. /// <param name="message">消息内容</param>
  8. /// <param name="title">标题</param>
  9. public static void ShowServiceMessage(string message, string title)
  10. {
  11. int resp = 0;
  12. WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, WTSGetActiveConsoleSessionId(), title, title.Length, message, message.Length, 0, 0, out resp, false);
  13. }
  14. [ DllImport("kernel32.dll", SetLastError = true)]
  15. public static extern int WTSGetActiveConsoleSessionId();
  16. [ DllImport("wtsapi32.dll", SetLastError = true)]
  17. 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);
  18. #region P/Invoke WTS APIs
  19. private enum WTS_CONNECTSTATE_CLASS
  20. {
  21. WTSActive,
  22. WTSConnected,
  23. WTSConnectQuery,
  24. WTSShadow,
  25. WTSDisconnected,
  26. WTSIdle,
  27. WTSListen,
  28. WTSReset,
  29. WTSDown,
  30. WTSInit
  31. }
  32. [ StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  33. private struct WTS_SESSION_INFO
  34. {
  35. public UInt32 SessionID;
  36. public string pWinStationName;
  37. public WTS_CONNECTSTATE_CLASS State;
  38. }
  39. [ DllImport("WTSAPI32.DLL", SetLastError = true, CharSet = CharSet.Auto)]
  40. static extern bool WTSEnumerateSessions(
  41. IntPtr hServer,
  42. [MarshalAs(UnmanagedType.U4)] UInt32 Reserved,
  43. [MarshalAs(UnmanagedType.U4)] UInt32 Version,
  44. ref IntPtr ppSessionInfo,
  45. [MarshalAs(UnmanagedType.U4)] ref UInt32 pSessionInfoCount
  46. );
  47. [ DllImport("WTSAPI32.DLL", SetLastError = true, CharSet = CharSet.Auto)]
  48. static extern void WTSFreeMemory(IntPtr pMemory);
  49. [ DllImport("WTSAPI32.DLL", SetLastError = true, CharSet = CharSet.Auto)]
  50. static extern bool WTSQueryUserToken(UInt32 sessionId, out IntPtr Token);
  51. #endregion
  52. #region P/Invoke CreateProcessAsUser
  53. /// <summary>
  54. /// Struct, Enum and P/Invoke Declarations for CreateProcessAsUser.
  55. /// </summary>
  56. ///
  57. [ StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  58. struct STARTUPINFO
  59. {
  60. public Int32 cb;
  61. public string lpReserved;
  62. public string lpDesktop;
  63. public string lpTitle;
  64. public Int32 dwX;
  65. public Int32 dwY;
  66. public Int32 dwXSize;
  67. public Int32 dwYSize;
  68. public Int32 dwXCountChars;
  69. public Int32 dwYCountChars;
  70. public Int32 dwFillAttribute;
  71. public Int32 dwFlags;
  72. public Int16 wShowWindow;
  73. public Int16 cbReserved2;
  74. public IntPtr lpReserved2;
  75. public IntPtr hStdInput;
  76. public IntPtr hStdOutput;
  77. public IntPtr hStdError;
  78. }
  79. [ StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  80. struct PROCESS_INFORMATION
  81. {
  82. public IntPtr hProcess;
  83. public IntPtr hThread;
  84. public int dwProcessId;
  85. public int dwThreadId;
  86. }
  87. /// <summary>
  88. /// 以当前登录的windows用户(角色权限)运行指定程序进程
  89. /// </summary>
  90. /// <param name="hToken"></param>
  91. /// <param name="lpApplicationName">指定程序(全路径)</param>
  92. /// <param name="lpCommandLine">参数</param>
  93. /// <param name="lpProcessAttributes">进程属性</param>
  94. /// <param name="lpThreadAttributes">线程属性</param>
  95. /// <param name="bInheritHandles"></param>
  96. /// <param name="dwCreationFlags"></param>
  97. /// <param name="lpEnvironment"></param>
  98. /// <param name="lpCurrentDirectory"></param>
  99. /// <param name="lpStartupInfo">程序启动属性</param>
  100. /// <param name="lpProcessInformation">最后返回的进程信息</param>
  101. /// <returns>是否调用成功</returns>
  102. [ DllImport("ADVAPI32.DLL", SetLastError = true, CharSet = CharSet.Auto)]
  103. static extern bool CreateProcessAsUser(IntPtr hToken, string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes,
  104. bool bInheritHandles, uint dwCreationFlags, string lpEnvironment, string lpCurrentDirectory,
  105. ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
  106. [ DllImport("KERNEL32.DLL", SetLastError = true, CharSet = CharSet.Auto)]
  107. static extern bool CloseHandle(IntPtr hHandle);
  108. #endregion
  109. /// <summary>
  110. /// 以当前登录系统的用户角色权限启动指定的进程
  111. /// </summary>
  112. /// <param name="ChildProcName">指定的进程(全路径)</param>
  113. public static void CreateProcess(string ChildProcName)
  114. {
  115. IntPtr ppSessionInfo = IntPtr.Zero;
  116. UInt32 SessionCount = 0;
  117. if (WTSEnumerateSessions(
  118. (IntPtr)WTS_CURRENT_SERVER_HANDLE, // Current RD Session Host Server handle would be zero.
  119. 0, // This reserved parameter must be zero.
  120. 1, // The version of the enumeration request must be 1.
  121. ref ppSessionInfo, // This would point to an array of session info.
  122. ref SessionCount // This would indicate the length of the above array.
  123. ))
  124. {
  125. for ( int nCount = 0; nCount < SessionCount; nCount++)
  126. {
  127. WTS_SESSION_INFO tSessionInfo = (WTS_SESSION_INFO)Marshal.PtrToStructure(ppSessionInfo + nCount * Marshal.SizeOf( typeof(WTS_SESSION_INFO)), typeof(WTS_SESSION_INFO));
  128. if (WTS_CONNECTSTATE_CLASS.WTSActive == tSessionInfo.State)
  129. {
  130. IntPtr hToken = IntPtr.Zero;
  131. if(WTSQueryUserToken(tSessionInfo.SessionID, out hToken))
  132. {
  133. PROCESS_INFORMATION tProcessInfo;
  134. STARTUPINFO tStartUpInfo = new STARTUPINFO();
  135. tStartUpInfo.cb = Marshal.SizeOf( typeof(STARTUPINFO));
  136. bool ChildProcStarted = CreateProcessAsUser(
  137. hToken, // Token of the logged-on user.
  138. ChildProcName, // Name of the process to be started.
  139. null, // Any command line arguments to be passed.
  140. IntPtr.Zero, // Default Process' attributes.
  141. IntPtr.Zero, // Default Thread's attributes.
  142. false, // Does NOT inherit parent's handles.
  143. 0, // No any specific creation flag.
  144. null, // Default environment path.
  145. null, // Default current directory.
  146. ref tStartUpInfo, // Process Startup Info.
  147. out tProcessInfo // Process information to be returned.
  148. );
  149. if (ChildProcStarted)
  150. {
  151. CloseHandle(tProcessInfo.hThread);
  152. CloseHandle(tProcessInfo.hProcess);
  153. }
  154. else
  155. {
  156. ShowServiceMessage( "CreateProcessAsUser失败", "CreateProcess");
  157. }
  158. CloseHandle(hToken);
  159. break;
  160. }
  161. }
  162. }
  163. WTSFreeMemory(ppSessionInfo);
  164. }
  165. }
  166. }
  • 第二种方法
Interops.CreateProcess(path, @"C:\Windows\System32\");//string path=@"C:\Users\Administrator\Text.exe";

  
  1. public class Interops
  2. {
  3. public static void CreateProcess(string app, string path)
  4. {
  5. bool result;
  6. IntPtr hToken = WindowsIdentity.GetCurrent().Token;
  7. IntPtr hDupedToken = IntPtr.Zero;
  8. PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
  9. SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
  10. sa.Length = Marshal.SizeOf(sa);
  11. STARTUPINFO si = new STARTUPINFO();
  12. si.cb = Marshal.SizeOf(si);
  13. int dwSessionID = 0; // WTSGetActiveConsoleSessionId();
  14. result = WTSQueryUserToken(dwSessionID, out hToken);
  15. if (!result)
  16. {
  17. ShowMessageBox( "WTSQueryUserToken failed", "AlertService Message");
  18. }
  19. result = DuplicateTokenEx(
  20. hToken,
  21. GENERIC_ALL_ACCESS,
  22. ref sa,
  23. ( int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
  24. ( int)TOKEN_TYPE.TokenPrimary,
  25. ref hDupedToken
  26. );
  27. if (!result)
  28. {
  29. ShowMessageBox( "DuplicateTokenEx failed", "AlertService Message");
  30. }
  31. IntPtr lpEnvironment = IntPtr.Zero;
  32. result = CreateEnvironmentBlock( out lpEnvironment, hDupedToken, false);
  33. if (!result)
  34. {
  35. ShowMessageBox( "CreateEnvironmentBlock failed", "AlertService Message");
  36. }
  37. result = CreateProcessAsUser(
  38. hDupedToken,
  39. app,
  40. String.Empty,
  41. ref sa, ref sa,
  42. false, 0, IntPtr.Zero,
  43. null, ref si, ref pi);
  44. if (!result)
  45. {
  46. int error = Marshal.GetLastWin32Error();
  47. string message = String.Format( "CreateProcessAsUser Error: {0}", error);
  48. ShowMessageBox(message, "AlertService Message");
  49. }
  50. if (pi.hProcess != IntPtr.Zero)
  51. CloseHandle(pi.hProcess);
  52. if (pi.hThread != IntPtr.Zero)
  53. CloseHandle(pi.hThread);
  54. if (hDupedToken != IntPtr.Zero)
  55. CloseHandle(hDupedToken);
  56. }
  57. [ StructLayout(LayoutKind.Sequential)]
  58. public struct STARTUPINFO
  59. {
  60. public Int32 cb;
  61. public string lpReserved;
  62. public string lpDesktop;
  63. public string lpTitle;
  64. public Int32 dwX;
  65. public Int32 dwY;
  66. public Int32 dwXSize;
  67. public Int32 dwXCountChars;
  68. public Int32 dwYCountChars;
  69. public Int32 dwFillAttribute;
  70. public Int32 dwFlags;
  71. public Int16 wShowWindow;
  72. public Int16 cbReserved2;
  73. public IntPtr lpReserved2;
  74. public IntPtr hStdInput;
  75. public IntPtr hStdOutput;
  76. public IntPtr hStdError;
  77. }
  78. [ StructLayout(LayoutKind.Sequential)]
  79. public struct PROCESS_INFORMATION
  80. {
  81. public IntPtr hProcess;
  82. public IntPtr hThread;
  83. public Int32 dwProcessID;
  84. public Int32 dwThreadID;
  85. }
  86. [ StructLayout(LayoutKind.Sequential)]
  87. public struct SECURITY_ATTRIBUTES
  88. {
  89. public Int32 Length;
  90. public IntPtr lpSecurityDescriptor;
  91. public bool bInheritHandle;
  92. }
  93. public enum SECURITY_IMPERSONATION_LEVEL
  94. {
  95. SecurityAnonymous,
  96. SecurityIdentification,
  97. SecurityImpersonation,
  98. SecurityDelegation
  99. }
  100. public enum TOKEN_TYPE
  101. {
  102. TokenPrimary = 1,
  103. TokenImpersonation
  104. }
  105. public const int GENERIC_ALL_ACCESS = 0x10000000;
  106. [ DllImport("kernel32.dll", SetLastError = true,
  107. CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
  108. public static extern bool CloseHandle(IntPtr handle);
  109. [ DllImport("advapi32.dll", SetLastError = true,
  110. CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
  111. public static extern bool CreateProcessAsUser(
  112. IntPtr hToken,
  113. string lpApplicationName,
  114. string lpCommandLine,
  115. ref SECURITY_ATTRIBUTES lpProcessAttributes,
  116. ref SECURITY_ATTRIBUTES lpThreadAttributes,
  117. bool bInheritHandle,
  118. Int32 dwCreationFlags,
  119. IntPtr lpEnvrionment,
  120. string lpCurrentDirectory,
  121. ref STARTUPINFO lpStartupInfo,
  122. ref PROCESS_INFORMATION lpProcessInformation);
  123. [ DllImport("advapi32.dll", SetLastError = true)]
  124. public static extern bool DuplicateTokenEx(
  125. IntPtr hExistingToken,
  126. Int32 dwDesiredAccess,
  127. ref SECURITY_ATTRIBUTES lpThreadAttributes,
  128. Int32 ImpersonationLevel,
  129. Int32 dwTokenType,
  130. ref IntPtr phNewToken);
  131. [ DllImport("wtsapi32.dll", SetLastError = true)]
  132. public static extern bool WTSQueryUserToken(
  133. Int32 sessionId,
  134. out IntPtr Token);
  135. [ DllImport("userenv.dll", SetLastError = true)]
  136. static extern bool CreateEnvironmentBlock(
  137. out IntPtr lpEnvironment,
  138. IntPtr hToken,
  139. bool bInherit);
  140. public static IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
  141. public static void ShowMessageBox(string message, string title)
  142. {
  143. int resp = 0;
  144. WTSSendMessage(
  145. WTS_CURRENT_SERVER_HANDLE,
  146. WTSGetActiveConsoleSessionId(),
  147. title, title.Length,
  148. message, message.Length,
  149. 0, 0, out resp, false);
  150. }
  151. [ DllImport("kernel32.dll", SetLastError = true)]
  152. public static extern int WTSGetActiveConsoleSessionId();
  153. [ DllImport("wtsapi32.dll", SetLastError = true)]
  154. public static extern bool WTSSendMessage(
  155. IntPtr hServer,
  156. int SessionId,
  157. String pTitle,
  158. int TitleLength,
  159. String pMessage,
  160. int MessageLength,
  161. int Style,
  162. int Timeout,
  163. out int pResponse,
  164. bool bWait);
  165. }
  • 第三种方法(可以远程)
SessionUtility.CreateProcess(@"C:\Windows\System32\", path, 1);//string path=@"C:\Users\Administrator\Test.exe";

  
  1. /// <summary>
  2. /// 解决vista和win7在windows服务中交互桌面权限问题:穿透Session 0 隔离
  3. /// 用于windows服务 启动外部程序 或者截取图片等
  4. /// 默认windows服务的权限是在session0中
  5. /// </summary>
  6. public class SessionUtility
  7. {
  8. #region 如果服务只是简单的向桌面用户Session 发送消息窗口,则可以使用WTSSendMessage 函数实现
  9. public static IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
  10. public static void ShowMessageBox(string message, string title)
  11. {
  12. int resp = 0;
  13. WTSSendMessage(
  14. WTS_CURRENT_SERVER_HANDLE,
  15. WTSGetActiveConsoleSessionId(),
  16. title, title.Length,
  17. message, message.Length,
  18. 0, 0, out resp, false);
  19. }
  20. [ DllImport("kernel32.dll", SetLastError = true)]
  21. public static extern int WTSGetActiveConsoleSessionId();
  22. [ DllImport("wtsapi32.dll", SetLastError = true)]
  23. public static extern bool WTSSendMessage(
  24. IntPtr hServer,
  25. int SessionId,
  26. String pTitle,
  27. int TitleLength,
  28. String pMessage,
  29. int MessageLength,
  30. int Style,
  31. int Timeout,
  32. out int pResponse,
  33. bool bWait);
  34. //在ShowMessageBox 函数中调用了WTSSendMessage 来发送信息窗口,这样我们就可以在Service 的OnStart 函数中使用,打开Service1.cs 加入下面代码:
  35. //protected override void OnStart(string[] args)
  36. //{
  37. // Interop.ShowMessageBox("This a message from AlertService.",
  38. // "AlertService Message");
  39. //}
  40. #endregion
  41. /*
  42. * 如果想通过服务向桌面用户Session 创建一个复杂UI 程序界面,
  43. * 则需要使用CreateProcessAsUser 函数为用户创建一个新进程用来运行相应的程序。
  44. */
  45. #region 复杂进程
  46. public static void CreateProcess(string app, string para, int sessionID)
  47. {
  48. if (! string.IsNullOrEmpty(para))
  49. {
  50. para = app + @"\" + para;
  51. app = null;
  52. }
  53. bool result;
  54. IntPtr hToken = WindowsIdentity.GetCurrent().Token;
  55. IntPtr hDupedToken = IntPtr.Zero;
  56. var pi = new PROCESS_INFORMATION();
  57. var sa = new SECURITY_ATTRIBUTES();
  58. sa.Length = Marshal.SizeOf(sa);
  59. var si = new STARTUPINFO();
  60. si.cb = Marshal.SizeOf(si);
  61. int dwSessionID = sessionID;
  62. if (sessionID < 0)
  63. dwSessionID = WTSGetActiveConsoleSessionId();
  64. result = WTSQueryUserToken(dwSessionID, out hToken);
  65. if (!result)
  66. {
  67. ShowMessageBox( "WTSQueryUserToken failed", "AlertService Message");
  68. }
  69. result = DuplicateTokenEx(
  70. hToken,
  71. GENERIC_ALL_ACCESS,
  72. ref sa,
  73. ( int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
  74. ( int)TOKEN_TYPE.TokenPrimary,
  75. ref hDupedToken
  76. );
  77. if (!result)
  78. {
  79. ShowMessageBox( "DuplicateTokenEx failed", "AlertService Message");
  80. }
  81. IntPtr lpEnvironment = IntPtr.Zero;
  82. result = CreateEnvironmentBlock( out lpEnvironment, hDupedToken, false);
  83. if (!result)
  84. {
  85. ShowMessageBox( "CreateEnvironmentBlock failed", "AlertService Message");
  86. }
  87. result = CreateProcessAsUser(
  88. hDupedToken,
  89. app,
  90. para,
  91. ref sa, ref sa,
  92. false, 0, IntPtr.Zero,
  93. null, ref si, ref pi);
  94. if (!result)
  95. {
  96. int error = Marshal.GetLastWin32Error();
  97. string message = String.Format( "CreateProcessAsUser Error: {0}", error);
  98. ShowMessageBox(message, "AlertService Message");
  99. }
  100. if (pi.hProcess != IntPtr.Zero)
  101. CloseHandle(pi.hProcess);
  102. if (pi.hThread != IntPtr.Zero)
  103. CloseHandle(pi.hThread);
  104. if (hDupedToken != IntPtr.Zero)
  105. CloseHandle(hDupedToken);
  106. }
  107. [ StructLayout(LayoutKind.Sequential)]
  108. public struct STARTUPINFO
  109. {
  110. public Int32 cb;
  111. public string lpReserved;
  112. public string lpDesktop;
  113. public string lpTitle;
  114. public Int32 dwX;
  115. public Int32 dwY;
  116. public Int32 dwXSize;
  117. public Int32 dwXCountChars;
  118. public Int32 dwYCountChars;
  119. public Int32 dwFillAttribute;
  120. public Int32 dwFlags;
  121. public Int16 wShowWindow;
  122. public Int16 cbReserved2;
  123. public IntPtr lpReserved2;
  124. public IntPtr hStdInput;
  125. public IntPtr hStdOutput;
  126. public IntPtr hStdError;
  127. }
  128. [ StructLayout(LayoutKind.Sequential)]
  129. public struct PROCESS_INFORMATION
  130. {
  131. public IntPtr hProcess;
  132. public IntPtr hThread;
  133. public Int32 dwProcessID;
  134. public Int32 dwThreadID;
  135. }
  136. [ StructLayout(LayoutKind.Sequential)]
  137. public struct SECURITY_ATTRIBUTES
  138. {
  139. public Int32 Length;
  140. public IntPtr lpSecurityDescriptor;
  141. public bool bInheritHandle;
  142. }
  143. public enum SECURITY_IMPERSONATION_LEVEL
  144. {
  145. SecurityAnonymous,
  146. SecurityIdentification,
  147. SecurityImpersonation,
  148. SecurityDelegation
  149. }
  150. public enum TOKEN_TYPE
  151. {
  152. TokenPrimary = 1,
  153. TokenImpersonation
  154. }
  155. public const int GENERIC_ALL_ACCESS = 0x10000000;
  156. [ DllImport("kernel32.dll", SetLastError = true,
  157. CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
  158. public static extern bool CloseHandle(IntPtr handle);
  159. [ DllImport("advapi32.dll", SetLastError = true,
  160. CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
  161. public static extern bool CreateProcessAsUser(
  162. IntPtr hToken,
  163. string lpApplicationName,
  164. string lpCommandLine,
  165. ref SECURITY_ATTRIBUTES lpProcessAttributes,
  166. ref SECURITY_ATTRIBUTES lpThreadAttributes,
  167. bool bInheritHandle,
  168. Int32 dwCreationFlags,
  169. IntPtr lpEnvrionment,
  170. string lpCurrentDirectory,
  171. ref STARTUPINFO lpStartupInfo,
  172. ref PROCESS_INFORMATION lpProcessInformation);
  173. [ DllImport("advapi32.dll", SetLastError = true)]
  174. public static extern bool DuplicateTokenEx(
  175. IntPtr hExistingToken,
  176. Int32 dwDesiredAccess,
  177. ref SECURITY_ATTRIBUTES lpThreadAttributes,
  178. Int32 ImpersonationLevel,
  179. Int32 dwTokenType,
  180. ref IntPtr phNewToken);
  181. [ DllImport("wtsapi32.dll", SetLastError = true)]
  182. public static extern bool WTSQueryUserToken(
  183. Int32 sessionId,
  184. out IntPtr Token);
  185. [ DllImport("userenv.dll", SetLastError = true)]
  186. private static extern bool CreateEnvironmentBlock(
  187. out IntPtr lpEnvironment,
  188. IntPtr hToken,
  189. bool bInherit);
  190. #endregion
  191. }
  • 第四种方法

  
  1. ApplicationLoader.PROCESS_INFORMATION procInfo;
  2. ApplicationLoader.StartProcessAndBypassUAC(path, out procInfo); //string path=@"C:\Users\Administrator\Test.exe";

  
  1. /// <summary>
  2. /// Class that allows running applications with full admin rights. In
  3. /// addition the application launched will bypass the Vista UAC prompt.
  4. /// </summary>
  5. public class ApplicationLoader
  6. {
  7. #region Structrures
  8. [ StructLayout(LayoutKind.Sequential)]
  9. public struct SECURITY_ATTRIBUTES
  10. {
  11. public int Length;
  12. public IntPtr lpSecurityDescriptor;
  13. public bool bInheritHandle;
  14. }
  15. [ StructLayout(LayoutKind.Sequential)]
  16. public struct STARTUPINFO
  17. {
  18. public int cb;
  19. public String lpReserved;
  20. public String lpDesktop;
  21. public String lpTitle;
  22. public uint dwX;
  23. public uint dwY;
  24. public uint dwXSize;
  25. public uint dwYSize;
  26. public uint dwXCountChars;
  27. public uint dwYCountChars;
  28. public uint dwFillAttribute;
  29. public uint dwFlags;
  30. public short wShowWindow;
  31. public short cbReserved2;
  32. public IntPtr lpReserved2;
  33. public IntPtr hStdInput;
  34. public IntPtr hStdOutput;
  35. public IntPtr hStdError;
  36. }
  37. [ StructLayout(LayoutKind.Sequential)]
  38. public struct PROCESS_INFORMATION
  39. {
  40. public IntPtr hProcess;
  41. public IntPtr hThread;
  42. public uint dwProcessId;
  43. public uint dwThreadId;
  44. }
  45. #endregion
  46. #region Enumberation
  47. enum TOKEN_TYPE : int
  48. {
  49. TokenPrimary = 1,
  50. TokenImpersonation = 2
  51. }
  52. enum SECURITY_IMPERSONATION_LEVEL : int
  53. {
  54. SecurityAnonymous = 0,
  55. SecurityIdentification = 1,
  56. SecurityImpersonation = 2,
  57. SecurityDelegation = 3,
  58. }
  59. #endregion
  60. #region Constants
  61. public const int TOKEN_DUPLICATE = 0x0002;
  62. public const uint MAXIMUM_ALLOWED = 0x2000000;
  63. public const int CREATE_NEW_CONSOLE = 0x00000010;
  64. public const int IDLE_PRIORITY_CLASS = 0x40;
  65. public const int NORMAL_PRIORITY_CLASS = 0x20;
  66. public const int HIGH_PRIORITY_CLASS = 0x80;
  67. public const int REALTIME_PRIORITY_CLASS = 0x100;
  68. #endregion
  69. #region Win32 API Imports
  70. [ DllImport("kernel32.dll", SetLastError = true)]
  71. private static extern bool CloseHandle(IntPtr hSnapshot);
  72. [ DllImport("kernel32.dll")]
  73. static extern uint WTSGetActiveConsoleSessionId();
  74. [ DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
  75. public extern static bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes,
  76. ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int dwCreationFlags, IntPtr lpEnvironment,
  77. String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
  78. [ DllImport("kernel32.dll")]
  79. static extern bool ProcessIdToSessionId(uint dwProcessId, ref uint pSessionId);
  80. [ DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")]
  81. public extern static bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess,
  82. ref SECURITY_ATTRIBUTES lpThreadAttributes, int TokenType,
  83. int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);
  84. [ DllImport("kernel32.dll")]
  85. static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);
  86. [ DllImport("advapi32.dll", SetLastError = true), SuppressUnmanagedCodeSecurityAttribute]
  87. static extern bool OpenProcessToken(IntPtr ProcessHandle, int DesiredAccess, ref IntPtr TokenHandle);
  88. //[DllImport("advapi32.dll", SetLastError = true)]
  89. //[return: MarshalAs(UnmanagedType.Bool)]
  90. //static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, ref IntPtr TokenHandle);
  91. #endregion
  92. /// <summary>
  93. /// Launches the given application with full admin rights, and in addition bypasses the Vista UAC prompt
  94. /// </summary>
  95. /// <param name="applicationName">The name of the application to launch</param>
  96. /// <param name="procInfo">Process information regarding the launched application that gets returned to the caller</param>
  97. /// <returns></returns>
  98. public static bool StartProcessAndBypassUAC(String applicationName, out PROCESS_INFORMATION procInfo)
  99. {
  100. uint winlogonPid = 0;
  101. IntPtr hUserTokenDup = IntPtr.Zero,
  102. hPToken = IntPtr.Zero,
  103. hProcess = IntPtr.Zero;
  104. procInfo = new PROCESS_INFORMATION();
  105. // obtain the currently active session id; every logged on user in the system has a unique session id
  106. TSControl.WTS_SESSION_INFO[] pSessionInfo = TSControl.SessionEnumeration();
  107. uint dwSessionId = 100;
  108. for ( int i = 0; i < pSessionInfo.Length; i++)
  109. {
  110. if (pSessionInfo[i].SessionID != 0)
  111. {
  112. try
  113. {
  114. int count = 0;
  115. IntPtr buffer = IntPtr.Zero;
  116. StringBuilder sb = new StringBuilder();
  117. bool bsuccess = TSControl.WTSQuerySessionInformation(
  118. IntPtr.Zero, pSessionInfo[i].SessionID,
  119. TSControl.WTSInfoClass.WTSUserName, out sb, out count);
  120. if (bsuccess)
  121. {
  122. if (sb.ToString().Trim() == "Administrator") //Administrator
  123. {
  124. dwSessionId = ( uint)pSessionInfo[i].SessionID;
  125. }
  126. }
  127. }
  128. catch (Exception ex)
  129. {
  130. //LoaderService.WriteLog(ex.Message.ToString(), "Monitor");
  131. }
  132. }
  133. }
  134. // obtain the process id of the winlogon process that is running within the currently active session
  135. Process[] processes = Process.GetProcessesByName( "explorer");
  136. foreach (Process p in processes)
  137. {
  138. if (( uint)p.SessionId == dwSessionId)
  139. {
  140. winlogonPid = ( uint)p.Id;
  141. }
  142. }
  143. //LoaderService.WriteLog(winlogonPid.ToString(), "Monitor");
  144. // obtain a handle to the winlogon process
  145. hProcess = OpenProcess(MAXIMUM_ALLOWED, false, winlogonPid);
  146. // obtain a handle to the access token of the winlogon process
  147. if (!OpenProcessToken(hProcess, TOKEN_DUPLICATE, ref hPToken))
  148. {
  149. CloseHandle(hProcess);
  150. return false;
  151. }
  152. // Security attibute structure used in DuplicateTokenEx and CreateProcessAsUser
  153. // I would prefer to not have to use a security attribute variable and to just
  154. // simply pass null and inherit (by default) the security attributes
  155. // of the existing token. However, in C# structures are value types and therefore
  156. // cannot be assigned the null value.
  157. SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
  158. sa.Length = Marshal.SizeOf(sa);
  159. // copy the access token of the winlogon process; the newly created token will be a primary token
  160. if (!DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, ref sa, ( int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, ( int)TOKEN_TYPE.TokenPrimary, ref hUserTokenDup))
  161. {
  162. CloseHandle(hProcess);
  163. CloseHandle(hPToken);
  164. return false;
  165. }
  166. // By default CreateProcessAsUser creates a process on a non-interactive window station, meaning
  167. // the window station has a desktop that is invisible and the process is incapable of receiving
  168. // user input. To remedy this we set the lpDesktop parameter to indicate we want to enable user
  169. // interaction with the new process.
  170. STARTUPINFO si = new STARTUPINFO();
  171. si.cb = ( int)Marshal.SizeOf(si);
  172. si.lpDesktop = @"winsta0\default"; // interactive window station parameter; basically this indicates that the process created can display a GUI on the desktop
  173. // flags that specify the priority and creation method of the process
  174. int dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
  175. // create a new process in the current user's logon session
  176. bool result = CreateProcessAsUser(hUserTokenDup, // client's access token
  177. null, // file to execute
  178. applicationName, // command line
  179. ref sa, // pointer to process SECURITY_ATTRIBUTES
  180. ref sa, // pointer to thread SECURITY_ATTRIBUTES
  181. false, // handles are not inheritable
  182. dwCreationFlags, // creation flags
  183. IntPtr.Zero, // pointer to new environment block
  184. null, // name of current directory
  185. ref si, // pointer to STARTUPINFO structure
  186. out procInfo // receives information about new process
  187. );
  188. // invalidate the handles
  189. CloseHandle(hProcess);
  190. CloseHandle(hPToken);
  191. CloseHandle(hUserTokenDup);
  192. //LoaderService.WriteLog("launch Task", "Monitor");
  193. return result; // return the result
  194. }
  195. }

  
  1. public class TSControl
  2. {
  3. /**/
  4. /// <summary>
  5. /// Terminal Services API Functions,The WTSEnumerateSessions function retrieves a list of sessions on a specified terminal server,
  6. /// </summary>
  7. /// <param name="hServer">[in] Handle to a terminal server. Specify a handle opened by the WTSOpenServer function, or specify WTS_CURRENT_SERVER_HANDLE to indicate the terminal server on which your application is running</param>
  8. /// <param name="Reserved">Reserved; must be zero</param>
  9. /// <param name="Version">[in] Specifies the version of the enumeration request. Must be 1. </param>
  10. /// <param name="ppSessionInfo">[out] Pointer to a variable that receives a pointer to an array of WTS_SESSION_INFO structures. Each structure in the array contains information about a session on the specified terminal server. To free the returned buffer, call the WTSFreeMemory function.
  11. /// To be able to enumerate a session, you need to have the Query Information permission.</param>
  12. /// <param name="pCount">[out] Pointer to the variable that receives the number of WTS_SESSION_INFO structures returned in the ppSessionInfo buffer. </param>
  13. /// <returns>If the function succeeds, the return value is a nonzero value. If the function fails, the return value is zero</returns>
  14. [ DllImport("wtsapi32", CharSet = CharSet.Auto, SetLastError = true)]
  15. private static extern bool WTSEnumerateSessions(int hServer, int Reserved, int Version, ref long ppSessionInfo, ref int pCount);
  16. /**/
  17. /// <summary>
  18. /// Terminal Services API Functions,The WTSFreeMemory function frees memory allocated by a Terminal Services function.
  19. /// </summary>
  20. /// <param name="pMemory">[in] Pointer to the memory to free</param>
  21. [ DllImport("wtsapi32.dll")]
  22. public static extern void WTSFreeMemory(System.IntPtr pMemory);
  23. /**/
  24. /// <summary>
  25. /// Terminal Services API Functions,The WTSLogoffSession function logs off a specified Terminal Services session.
  26. /// </summary>
  27. /// <param name="hServer">[in] Handle to a terminal server. Specify a handle opened by the WTSOpenServer function, or specify WTS_CURRENT_SERVER_HANDLE to indicate the terminal server on which your application is running. </param>
  28. /// <param name="SessionId">[in] A Terminal Services session identifier. To indicate the current session, specify WTS_CURRENT_SESSION. You can use the WTSEnumerateSessions function to retrieve the identifiers of all sessions on a specified terminal server.
  29. /// To be able to log off another user's session, you need to have the Reset permission </param>
  30. /// <param name="bWait">[in] Indicates whether the operation is synchronous.
  31. /// If bWait is TRUE, the function returns when the session is logged off.
  32. /// If bWait is FALSE, the function returns immediately.</param>
  33. /// <returns>If the function succeeds, the return value is a nonzero value.
  34. /// If the function fails, the return value is zero.</returns>
  35. [ DllImport("wtsapi32.dll")]
  36. public static extern bool WTSLogoffSession(int hServer, long SessionId, bool bWait);
  37. [ DllImport("Wtsapi32.dll")]
  38. public static extern bool WTSQuerySessionInformation(
  39. System.IntPtr hServer,
  40. int sessionId,
  41. WTSInfoClass wtsInfoClass,
  42. out StringBuilder ppBuffer,
  43. out int pBytesReturned
  44. );
  45. public enum WTSInfoClass
  46. {
  47. WTSInitialProgram,
  48. WTSApplicationName,
  49. WTSWorkingDirectory,
  50. WTSOEMId,
  51. WTSSessionId,
  52. WTSUserName,
  53. WTSWinStationName,
  54. WTSDomainName,
  55. WTSConnectState,
  56. WTSClientBuildNumber,
  57. WTSClientName,
  58. WTSClientDirectory,
  59. WTSClientProductId,
  60. WTSClientHardwareId,
  61. WTSClientAddress,
  62. WTSClientDisplay,
  63. WTSClientProtocolType
  64. }
  65. /**/
  66. /// <summary>
  67. /// The WTS_CONNECTSTATE_CLASS enumeration type contains INT values that indicate the connection state of a Terminal Services session.
  68. /// </summary>
  69. public enum WTS_CONNECTSTATE_CLASS
  70. {
  71. WTSActive,
  72. WTSConnected,
  73. WTSConnectQuery,
  74. WTSShadow,
  75. WTSDisconnected,
  76. WTSIdle,
  77. WTSListen,
  78. WTSReset,
  79. WTSDown,
  80. WTSInit,
  81. }
  82. /**/
  83. /// <summary>
  84. /// The WTS_SESSION_INFO structure contains information about a client session on a terminal server.
  85. /// if the WTS_SESSION_INFO.SessionID==0, it means that the SESSION is the local logon user's session.
  86. /// </summary>
  87. public struct WTS_SESSION_INFO
  88. {
  89. public int SessionID;
  90. [ MarshalAs(UnmanagedType.LPTStr)]
  91. public string pWinStationName;
  92. public WTS_CONNECTSTATE_CLASS state;
  93. }
  94. /**/
  95. /// <summary>
  96. /// The SessionEnumeration function retrieves a list of
  97. ///WTS_SESSION_INFO on a current terminal server.
  98. /// </summary>
  99. /// <returns>a list of WTS_SESSION_INFO on a current terminal server</returns>
  100. public static WTS_SESSION_INFO[] SessionEnumeration()
  101. {
  102. //Set handle of terminal server as the current terminal server
  103. int hServer = 0;
  104. bool RetVal;
  105. long lpBuffer = 0;
  106. int Count = 0;
  107. long p;
  108. WTS_SESSION_INFO Session_Info = new WTS_SESSION_INFO();
  109. WTS_SESSION_INFO[] arrSessionInfo;
  110. RetVal = WTSEnumerateSessions(hServer, 0, 1, ref lpBuffer, ref Count);
  111. arrSessionInfo = new WTS_SESSION_INFO[ 0];
  112. if (RetVal)
  113. {
  114. arrSessionInfo = new WTS_SESSION_INFO[Count];
  115. int i;
  116. p = lpBuffer;
  117. for (i = 0; i < Count; i++)
  118. {
  119. arrSessionInfo[i] =
  120. (WTS_SESSION_INFO)Marshal.PtrToStructure( new IntPtr(p),
  121. Session_Info.GetType());
  122. p += Marshal.SizeOf(Session_Info.GetType());
  123. }
  124. WTSFreeMemory( new IntPtr(lpBuffer));
  125. }
  126. else
  127. {
  128. //Insert Error Reaction Here
  129. }
  130. return arrSessionInfo;
  131. }
  132. public TSControl()
  133. {
  134. //
  135. // TODO: 在此处添加构造函数逻辑
  136. //
  137. }
  138. }

 

 

 


转载:https://blog.csdn.net/m0_37137902/article/details/117334498
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场