在Windows服务里面启动其他具有界面的应用程序,需要穿透session隔离,尝试了很多种方法,都可行,现在一一列举下来,并写下几个需要注意的地方。
首先要将服务的Account属性设置为LocalSystem,安装服务后的登录身份则为本地系统账户
- 再一个需要注意的是不要把Windows服务的程序放在C:\Users\Administrator\目录下运行,不然启动服务的时候会遇到权限问题,如下图
实现代码如下
- 第一种方法
调用方法
WinAPI_Interop.CreateProcess(path);//string path=@"C:\Users\Administrator\Text.exe";
代码片段
-
public
class
WinAPI_Interop
-
{
-
public
static IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
-
/// <summary>
-
/// 服务程序执行消息提示,前台MessageBox.Show
-
/// </summary>
-
/// <param name="message">消息内容</param>
-
/// <param name="title">标题</param>
-
public static void ShowServiceMessage(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);
-
#region P/Invoke WTS APIs
-
private
enum WTS_CONNECTSTATE_CLASS
-
{
-
WTSActive,
-
WTSConnected,
-
WTSConnectQuery,
-
WTSShadow,
-
WTSDisconnected,
-
WTSIdle,
-
WTSListen,
-
WTSReset,
-
WTSDown,
-
WTSInit
-
}
-
-
[
StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
-
private
struct WTS_SESSION_INFO
-
{
-
public UInt32 SessionID;
-
public
string pWinStationName;
-
public WTS_CONNECTSTATE_CLASS State;
-
}
-
-
[
DllImport("WTSAPI32.DLL", SetLastError = true, CharSet = CharSet.Auto)]
-
static extern bool WTSEnumerateSessions(
-
IntPtr hServer,
-
[MarshalAs(UnmanagedType.U4)] UInt32 Reserved,
-
[MarshalAs(UnmanagedType.U4)] UInt32 Version,
-
ref IntPtr ppSessionInfo,
-
[MarshalAs(UnmanagedType.U4)] ref UInt32 pSessionInfoCount
-
);
-
-
[
DllImport("WTSAPI32.DLL", SetLastError = true, CharSet = CharSet.Auto)]
-
static extern void WTSFreeMemory(IntPtr pMemory);
-
-
[
DllImport("WTSAPI32.DLL", SetLastError = true, CharSet = CharSet.Auto)]
-
static extern bool WTSQueryUserToken(UInt32 sessionId, out IntPtr Token);
-
#endregion
-
-
#region P/Invoke CreateProcessAsUser
-
/// <summary>
-
/// Struct, Enum and P/Invoke Declarations for CreateProcessAsUser.
-
/// </summary>
-
///
-
-
[
StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
-
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 dwYSize;
-
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, CharSet = CharSet.Auto)]
-
struct PROCESS_INFORMATION
-
{
-
public IntPtr hProcess;
-
public IntPtr hThread;
-
public
int dwProcessId;
-
public
int dwThreadId;
-
}
-
-
/// <summary>
-
/// 以当前登录的windows用户(角色权限)运行指定程序进程
-
/// </summary>
-
/// <param name="hToken"></param>
-
/// <param name="lpApplicationName">指定程序(全路径)</param>
-
/// <param name="lpCommandLine">参数</param>
-
/// <param name="lpProcessAttributes">进程属性</param>
-
/// <param name="lpThreadAttributes">线程属性</param>
-
/// <param name="bInheritHandles"></param>
-
/// <param name="dwCreationFlags"></param>
-
/// <param name="lpEnvironment"></param>
-
/// <param name="lpCurrentDirectory"></param>
-
/// <param name="lpStartupInfo">程序启动属性</param>
-
/// <param name="lpProcessInformation">最后返回的进程信息</param>
-
/// <returns>是否调用成功</returns>
-
[
DllImport("ADVAPI32.DLL", SetLastError = true, CharSet = CharSet.Auto)]
-
static extern bool CreateProcessAsUser(IntPtr hToken, string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes,
-
bool bInheritHandles,
uint dwCreationFlags,
string lpEnvironment,
string lpCurrentDirectory,
-
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
-
-
[
DllImport("KERNEL32.DLL", SetLastError = true, CharSet = CharSet.Auto)]
-
static extern bool CloseHandle(IntPtr hHandle);
-
#endregion
-
-
/// <summary>
-
/// 以当前登录系统的用户角色权限启动指定的进程
-
/// </summary>
-
/// <param name="ChildProcName">指定的进程(全路径)</param>
-
public static void CreateProcess(string ChildProcName)
-
{
-
IntPtr ppSessionInfo = IntPtr.Zero;
-
UInt32 SessionCount =
0;
-
if (WTSEnumerateSessions(
-
(IntPtr)WTS_CURRENT_SERVER_HANDLE,
// Current RD Session Host Server handle would be zero.
-
0,
// This reserved parameter must be zero.
-
1,
// The version of the enumeration request must be 1.
-
ref ppSessionInfo,
// This would point to an array of session info.
-
ref SessionCount
// This would indicate the length of the above array.
-
))
-
{
-
for (
int nCount =
0; nCount < SessionCount; nCount++)
-
{
-
WTS_SESSION_INFO tSessionInfo = (WTS_SESSION_INFO)Marshal.PtrToStructure(ppSessionInfo + nCount * Marshal.SizeOf(
typeof(WTS_SESSION_INFO)),
typeof(WTS_SESSION_INFO));
-
if (WTS_CONNECTSTATE_CLASS.WTSActive == tSessionInfo.State)
-
{
-
IntPtr hToken = IntPtr.Zero;
-
if(WTSQueryUserToken(tSessionInfo.SessionID,
out hToken))
-
{
-
PROCESS_INFORMATION tProcessInfo;
-
STARTUPINFO tStartUpInfo =
new STARTUPINFO();
-
tStartUpInfo.cb = Marshal.SizeOf(
typeof(STARTUPINFO));
-
bool ChildProcStarted = CreateProcessAsUser(
-
hToken,
// Token of the logged-on user.
-
ChildProcName,
// Name of the process to be started.
-
null,
// Any command line arguments to be passed.
-
IntPtr.Zero,
// Default Process' attributes.
-
IntPtr.Zero,
// Default Thread's attributes.
-
false,
// Does NOT inherit parent's handles.
-
0,
// No any specific creation flag.
-
null,
// Default environment path.
-
null,
// Default current directory.
-
ref tStartUpInfo,
// Process Startup Info.
-
out tProcessInfo
// Process information to be returned.
-
);
-
if (ChildProcStarted)
-
{
-
CloseHandle(tProcessInfo.hThread);
-
CloseHandle(tProcessInfo.hProcess);
-
}
-
else
-
{
-
ShowServiceMessage(
"CreateProcessAsUser失败",
"CreateProcess");
-
}
-
CloseHandle(hToken);
-
break;
-
}
-
}
-
}
-
WTSFreeMemory(ppSessionInfo);
-
}
-
}
-
}
- 第二种方法
Interops.CreateProcess(path, @"C:\Windows\System32\");//string path=@"C:\Users\Administrator\Text.exe";
-
public
class
Interops
-
{
-
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 =
0;
// 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,
-
null,
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);
-
-
public
static IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
-
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);
-
}
- 第三种方法(可以远程)
SessionUtility.CreateProcess(@"C:\Windows\System32\", path, 1);//string path=@"C:\Users\Administrator\Test.exe";
-
/// <summary>
-
/// 解决vista和win7在windows服务中交互桌面权限问题:穿透Session 0 隔离
-
/// 用于windows服务 启动外部程序 或者截取图片等
-
/// 默认windows服务的权限是在session0中
-
/// </summary>
-
public
class
SessionUtility
-
{
-
#region 如果服务只是简单的向桌面用户Session 发送消息窗口,则可以使用WTSSendMessage 函数实现
-
-
public
static IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
-
-
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");
-
//}
-
-
#endregion
-
-
/*
-
* 如果想通过服务向桌面用户Session 创建一个复杂UI 程序界面,
-
* 则需要使用CreateProcessAsUser 函数为用户创建一个新进程用来运行相应的程序。
-
*/
-
-
#region 复杂进程
-
-
public static void CreateProcess(string app, string para, int sessionID)
-
{
-
if (!
string.IsNullOrEmpty(para))
-
{
-
para = app +
@"\" + para;
-
app =
null;
-
}
-
bool result;
-
IntPtr hToken = WindowsIdentity.GetCurrent().Token;
-
IntPtr hDupedToken = IntPtr.Zero;
-
-
var pi =
new PROCESS_INFORMATION();
-
var sa =
new SECURITY_ATTRIBUTES();
-
sa.Length = Marshal.SizeOf(sa);
-
-
var si =
new STARTUPINFO();
-
si.cb = Marshal.SizeOf(si);
-
-
int dwSessionID = sessionID;
-
if (sessionID <
0)
-
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,
-
para,
-
ref sa,
ref sa,
-
false,
0, IntPtr.Zero,
-
null,
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)]
-
private static extern bool CreateEnvironmentBlock(
-
out IntPtr lpEnvironment,
-
IntPtr hToken,
-
bool bInherit);
-
-
#endregion
-
}
- 第四种方法
-
ApplicationLoader.PROCESS_INFORMATION procInfo;
-
ApplicationLoader.StartProcessAndBypassUAC(path,
out procInfo);
//string path=@"C:\Users\Administrator\Test.exe";
-
/// <summary>
-
/// Class that allows running applications with full admin rights. In
-
/// addition the application launched will bypass the Vista UAC prompt.
-
/// </summary>
-
public
class
ApplicationLoader
-
{
-
-
-
#region Structrures
-
-
[
StructLayout(LayoutKind.Sequential)]
-
public
struct SECURITY_ATTRIBUTES
-
{
-
public
int Length;
-
public IntPtr lpSecurityDescriptor;
-
public
bool bInheritHandle;
-
}
-
-
-
[
StructLayout(LayoutKind.Sequential)]
-
public
struct STARTUPINFO
-
{
-
public
int cb;
-
public String lpReserved;
-
public String lpDesktop;
-
public String lpTitle;
-
public
uint dwX;
-
public
uint dwY;
-
public
uint dwXSize;
-
public
uint dwYSize;
-
public
uint dwXCountChars;
-
public
uint dwYCountChars;
-
public
uint dwFillAttribute;
-
public
uint dwFlags;
-
public
short wShowWindow;
-
public
short 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
uint dwProcessId;
-
public
uint dwThreadId;
-
}
-
-
#endregion
-
-
-
#region Enumberation
-
enum TOKEN_TYPE :
int
-
{
-
TokenPrimary =
1,
-
TokenImpersonation =
2
-
}
-
-
enum SECURITY_IMPERSONATION_LEVEL :
int
-
{
-
SecurityAnonymous =
0,
-
SecurityIdentification =
1,
-
SecurityImpersonation =
2,
-
SecurityDelegation =
3,
-
}
-
-
#endregion
-
-
-
-
-
#region Constants
-
-
public
const
int TOKEN_DUPLICATE =
0x0002;
-
public
const
uint MAXIMUM_ALLOWED =
0x2000000;
-
public
const
int CREATE_NEW_CONSOLE =
0x00000010;
-
-
public
const
int IDLE_PRIORITY_CLASS =
0x40;
-
public
const
int NORMAL_PRIORITY_CLASS =
0x20;
-
public
const
int HIGH_PRIORITY_CLASS =
0x80;
-
public
const
int REALTIME_PRIORITY_CLASS =
0x100;
-
-
#endregion
-
-
-
-
#region Win32 API Imports
-
-
[
DllImport("kernel32.dll", SetLastError = true)]
-
private static extern bool CloseHandle(IntPtr hSnapshot);
-
-
[
DllImport("kernel32.dll")]
-
static extern uint WTSGetActiveConsoleSessionId();
-
-
[
DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
-
public extern static bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes,
-
ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int dwCreationFlags, IntPtr lpEnvironment,
-
String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
-
-
[
DllImport("kernel32.dll")]
-
static extern bool ProcessIdToSessionId(uint dwProcessId, ref uint pSessionId);
-
-
[
DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")]
-
public extern static bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess,
-
ref SECURITY_ATTRIBUTES lpThreadAttributes,
int TokenType,
-
int ImpersonationLevel,
ref IntPtr DuplicateTokenHandle);
-
-
[
DllImport("kernel32.dll")]
-
static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);
-
-
[
DllImport("advapi32.dll", SetLastError = true), SuppressUnmanagedCodeSecurityAttribute]
-
static extern bool OpenProcessToken(IntPtr ProcessHandle, int DesiredAccess, ref IntPtr TokenHandle);
-
-
//[DllImport("advapi32.dll", SetLastError = true)]
-
//[return: MarshalAs(UnmanagedType.Bool)]
-
//static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, ref IntPtr TokenHandle);
-
-
#endregion
-
-
-
-
-
/// <summary>
-
/// Launches the given application with full admin rights, and in addition bypasses the Vista UAC prompt
-
/// </summary>
-
/// <param name="applicationName">The name of the application to launch</param>
-
/// <param name="procInfo">Process information regarding the launched application that gets returned to the caller</param>
-
/// <returns></returns>
-
public static bool StartProcessAndBypassUAC(String applicationName, out PROCESS_INFORMATION procInfo)
-
{
-
uint winlogonPid =
0;
-
IntPtr hUserTokenDup = IntPtr.Zero,
-
hPToken = IntPtr.Zero,
-
hProcess = IntPtr.Zero;
-
procInfo =
new PROCESS_INFORMATION();
-
-
// obtain the currently active session id; every logged on user in the system has a unique session id
-
TSControl.WTS_SESSION_INFO[] pSessionInfo = TSControl.SessionEnumeration();
-
uint dwSessionId =
100;
-
for (
int i =
0; i < pSessionInfo.Length; i++)
-
{
-
if (pSessionInfo[i].SessionID !=
0)
-
{
-
try
-
{
-
int count =
0;
-
IntPtr buffer = IntPtr.Zero;
-
StringBuilder sb =
new StringBuilder();
-
-
bool bsuccess = TSControl.WTSQuerySessionInformation(
-
IntPtr.Zero, pSessionInfo[i].SessionID,
-
TSControl.WTSInfoClass.WTSUserName,
out sb,
out count);
-
-
if (bsuccess)
-
{
-
if (sb.ToString().Trim() ==
"Administrator")
//Administrator
-
{
-
dwSessionId = (
uint)pSessionInfo[i].SessionID;
-
}
-
}
-
}
-
catch (Exception ex)
-
{
-
//LoaderService.WriteLog(ex.Message.ToString(), "Monitor");
-
}
-
}
-
}
-
-
// obtain the process id of the winlogon process that is running within the currently active session
-
Process[] processes = Process.GetProcessesByName(
"explorer");
-
foreach (Process p
in processes)
-
{
-
if ((
uint)p.SessionId == dwSessionId)
-
{
-
winlogonPid = (
uint)p.Id;
-
}
-
}
-
-
//LoaderService.WriteLog(winlogonPid.ToString(), "Monitor");
-
-
// obtain a handle to the winlogon process
-
hProcess = OpenProcess(MAXIMUM_ALLOWED,
false, winlogonPid);
-
-
// obtain a handle to the access token of the winlogon process
-
if (!OpenProcessToken(hProcess, TOKEN_DUPLICATE,
ref hPToken))
-
{
-
CloseHandle(hProcess);
-
return
false;
-
}
-
-
// Security attibute structure used in DuplicateTokenEx and CreateProcessAsUser
-
// I would prefer to not have to use a security attribute variable and to just
-
// simply pass null and inherit (by default) the security attributes
-
// of the existing token. However, in C# structures are value types and therefore
-
// cannot be assigned the null value.
-
SECURITY_ATTRIBUTES sa =
new SECURITY_ATTRIBUTES();
-
sa.Length = Marshal.SizeOf(sa);
-
-
// copy the access token of the winlogon process; the newly created token will be a primary token
-
if (!DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED,
ref sa, (
int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, (
int)TOKEN_TYPE.TokenPrimary,
ref hUserTokenDup))
-
{
-
CloseHandle(hProcess);
-
CloseHandle(hPToken);
-
return
false;
-
}
-
-
// By default CreateProcessAsUser creates a process on a non-interactive window station, meaning
-
// the window station has a desktop that is invisible and the process is incapable of receiving
-
// user input. To remedy this we set the lpDesktop parameter to indicate we want to enable user
-
// interaction with the new process.
-
STARTUPINFO si =
new STARTUPINFO();
-
si.cb = (
int)Marshal.SizeOf(si);
-
si.lpDesktop =
@"winsta0\default";
// interactive window station parameter; basically this indicates that the process created can display a GUI on the desktop
-
-
// flags that specify the priority and creation method of the process
-
int dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
-
-
// create a new process in the current user's logon session
-
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
-
);
-
-
// invalidate the handles
-
CloseHandle(hProcess);
-
CloseHandle(hPToken);
-
CloseHandle(hUserTokenDup);
-
//LoaderService.WriteLog("launch Task", "Monitor");
-
-
return result;
// return the result
-
}
-
-
}
-
public
class
TSControl
-
{
-
/**/
-
/// <summary>
-
/// Terminal Services API Functions,The WTSEnumerateSessions function retrieves a list of sessions on a specified terminal server,
-
/// </summary>
-
/// <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>
-
/// <param name="Reserved">Reserved; must be zero</param>
-
/// <param name="Version">[in] Specifies the version of the enumeration request. Must be 1. </param>
-
/// <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.
-
/// To be able to enumerate a session, you need to have the Query Information permission.</param>
-
/// <param name="pCount">[out] Pointer to the variable that receives the number of WTS_SESSION_INFO structures returned in the ppSessionInfo buffer. </param>
-
/// <returns>If the function succeeds, the return value is a nonzero value. If the function fails, the return value is zero</returns>
-
[
DllImport("wtsapi32", CharSet = CharSet.Auto, SetLastError = true)]
-
private static extern bool WTSEnumerateSessions(int hServer, int Reserved, int Version, ref long ppSessionInfo, ref int pCount);
-
-
/**/
-
/// <summary>
-
/// Terminal Services API Functions,The WTSFreeMemory function frees memory allocated by a Terminal Services function.
-
/// </summary>
-
/// <param name="pMemory">[in] Pointer to the memory to free</param>
-
[
DllImport("wtsapi32.dll")]
-
public static extern void WTSFreeMemory(System.IntPtr pMemory);
-
-
/**/
-
/// <summary>
-
/// Terminal Services API Functions,The WTSLogoffSession function logs off a specified Terminal Services session.
-
/// </summary>
-
/// <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>
-
/// <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.
-
/// To be able to log off another user's session, you need to have the Reset permission </param>
-
/// <param name="bWait">[in] Indicates whether the operation is synchronous.
-
/// If bWait is TRUE, the function returns when the session is logged off.
-
/// If bWait is FALSE, the function returns immediately.</param>
-
/// <returns>If the function succeeds, the return value is a nonzero value.
-
/// If the function fails, the return value is zero.</returns>
-
[
DllImport("wtsapi32.dll")]
-
public static extern bool WTSLogoffSession(int hServer, long SessionId, bool bWait);
-
-
-
[
DllImport("Wtsapi32.dll")]
-
public static extern bool WTSQuerySessionInformation(
-
System.IntPtr hServer,
-
int sessionId,
-
WTSInfoClass wtsInfoClass,
-
out StringBuilder ppBuffer,
-
out int pBytesReturned
-
);
-
-
public
enum WTSInfoClass
-
{
-
WTSInitialProgram,
-
WTSApplicationName,
-
WTSWorkingDirectory,
-
WTSOEMId,
-
WTSSessionId,
-
WTSUserName,
-
WTSWinStationName,
-
WTSDomainName,
-
WTSConnectState,
-
WTSClientBuildNumber,
-
WTSClientName,
-
WTSClientDirectory,
-
WTSClientProductId,
-
WTSClientHardwareId,
-
WTSClientAddress,
-
WTSClientDisplay,
-
WTSClientProtocolType
-
}
-
-
/**/
-
/// <summary>
-
/// The WTS_CONNECTSTATE_CLASS enumeration type contains INT values that indicate the connection state of a Terminal Services session.
-
/// </summary>
-
public
enum WTS_CONNECTSTATE_CLASS
-
{
-
WTSActive,
-
WTSConnected,
-
WTSConnectQuery,
-
WTSShadow,
-
WTSDisconnected,
-
WTSIdle,
-
WTSListen,
-
WTSReset,
-
WTSDown,
-
WTSInit,
-
}
-
-
-
/**/
-
/// <summary>
-
/// The WTS_SESSION_INFO structure contains information about a client session on a terminal server.
-
/// if the WTS_SESSION_INFO.SessionID==0, it means that the SESSION is the local logon user's session.
-
/// </summary>
-
public
struct WTS_SESSION_INFO
-
{
-
public
int SessionID;
-
[
MarshalAs(UnmanagedType.LPTStr)]
-
public
string pWinStationName;
-
public WTS_CONNECTSTATE_CLASS state;
-
}
-
-
/**/
-
/// <summary>
-
/// The SessionEnumeration function retrieves a list of
-
///WTS_SESSION_INFO on a current terminal server.
-
/// </summary>
-
/// <returns>a list of WTS_SESSION_INFO on a current terminal server</returns>
-
public static WTS_SESSION_INFO[] SessionEnumeration()
-
{
-
//Set handle of terminal server as the current terminal server
-
int hServer =
0;
-
bool RetVal;
-
long lpBuffer =
0;
-
int Count =
0;
-
long p;
-
WTS_SESSION_INFO Session_Info =
new WTS_SESSION_INFO();
-
WTS_SESSION_INFO[] arrSessionInfo;
-
RetVal = WTSEnumerateSessions(hServer,
0,
1,
ref lpBuffer,
ref Count);
-
arrSessionInfo =
new WTS_SESSION_INFO[
0];
-
if (RetVal)
-
{
-
arrSessionInfo =
new WTS_SESSION_INFO[Count];
-
int i;
-
p = lpBuffer;
-
for (i =
0; i < Count; i++)
-
{
-
arrSessionInfo[i] =
-
(WTS_SESSION_INFO)Marshal.PtrToStructure(
new IntPtr(p),
-
Session_Info.GetType());
-
p += Marshal.SizeOf(Session_Info.GetType());
-
}
-
WTSFreeMemory(
new IntPtr(lpBuffer));
-
}
-
else
-
{
-
//Insert Error Reaction Here
-
}
-
return arrSessionInfo;
-
}
-
-
public TSControl()
-
{
-
//
-
// TODO: 在此处添加构造函数逻辑
-
//
-
-
}
-
-
-
}
转载:https://blog.csdn.net/m0_37137902/article/details/117334498
查看评论