华域联盟 .Net asp.net中穿透Session 0 隔离(二)

asp.net中穿透Session 0 隔离(二)

对于简单的交互,服务可以通过WTSSendMessage 函数,在用户Session 上显示消息窗口。对于一些复杂的UI 交互,必须调用CreateProcessAsUser 或其他方法(WCF、.NET远程处理等)进行跨Session 通信,在桌面用户上创建一个应用程序界面。

WTSSendMessage 函数

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

复制代码 代码如下:

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");

}

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

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);

在CreateProcess 函数中同时也涉及到DuplicateTokenEx、WTSQueryUserToken、CreateEnvironmentBlock 函数的使用,有兴趣的朋友可通过MSDN 进行学习。完成CreateProcess 函数创建后,就可以真正的通过它来调用应用程序了,回到Service1.cs 修改一下OnStart 我们来打开一个CMD 窗口。如下代码:

复制代码 代码如下:

protected override void OnStart(string[] args)

{

Interop.CreateProcess("cmd.exe",@"C:\Windows\System32\");

}

重新编译程序,启动AlertService 服务便可看到下图界面。至此,我们已经可以通过一些简单的方法对Session 0 隔离问题进行解决。大家也可以通过WCF 等技术完成一些更复杂的跨Session 通信方式,实现在Windows 7 及Vista 系统中服务与桌面用户的交互操作。

参考资料

1. WTSSendMessage Function
http://msdn.microsoft.com/en-us/library/aa383842(VS.85).aspx

2. CreateProcessAsUser Function
http://msdn.microsoft.com/en-us/library/ms682429(v=VS.85).aspx

3. WTSSendMessage (wtsapi32)
http://www.pinvoke.net/default.aspx/wtsapi32/WTSSendMessage.html

4. WTSQueryUserToken Function
http://msdn.microsoft.com/en-us/library/aa383840(VS.85).aspx

5. http://www.pinvoke.net/

代码下载 AlertService2_jb51.rar

作者:李敬然(Gnie)
出处:{GnieTech} (http://www.cnblogs.com/gnielee/)

您可能感兴趣的文章:

  • asp.net中穿透Session 0 隔离(一)

本文由 华域联盟 原创撰写:华域联盟 » asp.net中穿透Session 0 隔离(二)

转载请保留出处和原文链接:https://www.cnhackhy.com/44738.htm

本文来自网络,不代表华域联盟立场,转载请注明出处。

作者: sterben

发表回复

联系我们

联系我们

2551209778

在线咨询: QQ交谈

邮箱: [email protected]

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部