PCB 一键远程桌面+RDP文件生成
最近在写个内网INCAM内网授权工具中,在服务端监听客户端请求后,后台自动处理客户端请求并远程客户端
这里记录3个点。
一.运行RDP文件后,正常会有下图2个弹窗,怎么可以关闭这2个弹窗呢,
通过模拟按键ALT+N,ALT+Y
二.客户端与服务端状态如何控制的,客户端发起请求:状态流程图
三.实现部份代码:
private bool DeskLink(string IPAddress, string Domain, string UserName, string Password) { bool isOK = false; DelMstsc(); string address = IPAddress; string domain = Domain; string username = UserName; string password = Password; string filename = "incam专用.rdp"; var TemplateStr = RDPdemo.Properties.Resources.TemplateRDP;//获取RDP模板字符串 var pwstr = BitConverter.ToString(DataProtection.ProtectData(Encoding.Unicode.GetBytes(password), "")); pwstr = pwstr.Replace("-", ""); var NewStr = TemplateStr.Replace("{#domain}", domain).Replace("{#address}", address).Replace("{#username}", username).Replace("{#password}", pwstr); StreamWriter sw = new StreamWriter(filename); sw.Write(NewStr); sw.Close(); ProcCmd("mstsc " + filename); Thread.Sleep(1000); bool isWinExist2 = isWindowsExistSleep("远程桌面连接", "是(&Y)", 200); if (!isWinExist2) { bool isWinExist1 = isWindowsExistSleep("远程桌面连接", "连接(&N)", 3000); if (isWinExist1) { Thread.Sleep(20); API.OpenIcon(hwnd); API.SetForegroundWindow(hwnd); Thread.Sleep(20); SendKeys.SendWait("%n"); //Shift + Ctrl ^ Alt % //API.keybd_event((int)Keys.Alt, API.MapVirtualKeyA((int)Keys.Alt, 0), 0, 0); //API.keybd_event((int)Keys.N, API.MapVirtualKeyA((int)Keys.N, 0), 0, 0); //API.keybd_event((int)Keys.N, API.MapVirtualKeyA((int)Keys.N, 0), 2, 0); //API.keybd_event((int)Keys.Alt, API.MapVirtualKeyA((int)Keys.Alt, 0), 2, 0); Thread.Sleep(1000); } } isWinExist2 = isWindowsExistSleep("远程桌面连接", "是(&Y)", 5000); if (isWinExist2) { Thread.Sleep(20); API.OpenIcon(hwnd); API.SetForegroundWindow(hwnd); Thread.Sleep(20); SendKeys.SendWait("%y"); //Shift + Ctrl ^ Alt % //API.keybd_event((int)Keys.Alt, API.MapVirtualKeyA((int)Keys.Alt, 0), 0, 0); //API.keybd_event((int)Keys.Y, API.MapVirtualKeyA((int)Keys.Y, 0), 0, 0); //API.keybd_event((int)Keys.Y, API.MapVirtualKeyA((int)Keys.Y, 0), 2, 0); //API.keybd_event((int)Keys.Alt, API.MapVirtualKeyA((int)Keys.Alt, 0), 2, 0); Thread.Sleep(20); } bool isWinDesk = isWindowsExistSleep($"incam专用 - {address} - 远程桌面连接", "", 10000); isOK = isWinDesk; if (isWinDesk) API.ShowWindow(hwnd, 2); return isOK; }
public IntPtr hwnd = IntPtr.Zero; public IntPtr hwndChild = IntPtr.Zero; public bool isWindowsExistSleep(string WindowName, string ChildWindowName, int SleepCountTime) { int SleepTime = SleepCountTime / 100; int i = 0; bool isWinExist = isWindowsExist(WindowName, ChildWindowName); while (i < SleepTime && !isWinExist) { Thread.Sleep(100); isWinExist = isWindowsExist(WindowName, ChildWindowName); i++; } return isWinExist; } /// <summary> /// 主窗体和子存体名同时存在 则为true /// </summary> /// <param name="WindowName"></param> /// <param name="ChildWindowName"></param> /// <returns></returns> public bool isWindowsExist(string WindowName, string ChildWindowName) { hwnd = API.FindWindowAPI(null, WindowName); if (hwnd == IntPtr.Zero) return false; if (!string.IsNullOrEmpty(ChildWindowName)) { hwndChild = API.FindWindowEx(hwnd, IntPtr.Zero, null, ChildWindowName); if (hwndChild == IntPtr.Zero) return false; } return true; }
[Serializable()] public sealed class DataProtection { [Flags()] public enum CryptProtectPromptFlags { CRYPTPROTECT_PROMPT_ON_UNPROTECT = 0x01, CRYPTPROTECT_PROMPT_ON_PROTECT = 0x02, CRYPTPROTECT_PROMPT_RESERVED = 0x04, CRYPTPROTECT_PROMPT_STRONG = 0x08, CRYPTPROTECT_PROMPT_REQUIRE_STRONG = 0x10 } [Flags()] public enum CryptProtectDataFlags { CRYPTPROTECT_UI_FORBIDDEN = 0x01, CRYPTPROTECT_LOCAL_MACHINE = 0x04, CRYPTPROTECT_CRED_SYNC = 0x08, CRYPTPROTECT_AUDIT = 0x10, CRYPTPROTECT_NO_RECOVERY = 0x20, CRYPTPROTECT_VERIFY_PROTECTION = 0x40, CRYPTPROTECT_CRED_REGENERATE = 0x80 } #region 加密数据 public static string ProtectData(string data, string name) { return ProtectData(data, name, CryptProtectDataFlags.CRYPTPROTECT_UI_FORBIDDEN | CryptProtectDataFlags.CRYPTPROTECT_LOCAL_MACHINE); } public static byte[] ProtectData(byte[] data, string name) { return ProtectData(data, name, CryptProtectDataFlags.CRYPTPROTECT_UI_FORBIDDEN | CryptProtectDataFlags.CRYPTPROTECT_LOCAL_MACHINE); } public static string ProtectData(string data, string name, CryptProtectDataFlags flags) { byte[] dataIn = Encoding.Unicode.GetBytes(data); byte[] dataOut = ProtectData(dataIn, name, flags); if (dataOut != null) return (Convert.ToBase64String(dataOut)); else return null; } /// <summary> /// 加密数据 /// </summary> /// <param name="data">要加密的明文数据</param> /// <param name="name">有意义的描述,此描述会加到加密后的数据中</param> /// <param name="dwFlags">flags的位标志</param> /// <returns></returns> private static byte[] ProtectData(byte[] data, string name, CryptProtectDataFlags dwFlags) { byte[] cipherText = null; // copy data into unmanaged memory //DATA_BLOB结构,用于CryptProtectData参数 DPAPI.DATA_BLOB din = new DPAPI.DATA_BLOB(); din.cbData = data.Length; //Marshal类的作用:提供了一个方法集,这些方法用于分配非托管内存、复制非托管内存块、将托管类型转换为非托管类型, //此外还提供了在与非托管代码交互时使用的其他杂项方法。 //为din.pbData分配内存 din.pbData = Marshal.AllocHGlobal(din.cbData); //InPtr结构:用于表示指针或句柄的平台特定类型 //分配内存错误,抛出内存不足异常 //IntPtr.Zero:一个只读字段,代表已初始化为零的指针或句柄 if (din.pbData.Equals(IntPtr.Zero)) throw new OutOfMemoryException("Unable to allocate memory for buffer."); //将data数组中的数据复制到pbData内存指针中 Marshal.Copy(data, 0, din.pbData, din.cbData); //声明DPAPI类的DATA_BLOB公共结构类型 DPAPI.DATA_BLOB dout = new DPAPI.DATA_BLOB(); try { //加密数据 bool cryptoRetval = DPAPI.CryptProtectData(ref din, name, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, dwFlags, ref dout); //判断加密是否成功 if (cryptoRetval) // 成功 { int startIndex = 0; //分配cipherText数据元素大小为dout.cbData cipherText = new byte[dout.cbData]; //从dout.pbData内存指针指向的内容拷贝到byte数组cipherText中 Marshal.Copy(dout.pbData, cipherText, startIndex, dout.cbData); //从内存中释放指针指向的数据I DPAPI.LocalFree(dout.pbData); } else { //加密失败,获得错误信息 int errCode = Marshal.GetLastWin32Error(); StringBuilder buffer = new StringBuilder(256); //显示错误信息 Win32Error.FormatMessage(Win32Error.FormatMessageFlags.FORMAT_MESSAGE_FROM_SYSTEM, IntPtr.Zero, errCode, 0, buffer, buffer.Capacity, IntPtr.Zero); } } finally { // 如果din.pbData非空,则释放din.pbData使用的内存 if (!din.pbData.Equals(IntPtr.Zero)) Marshal.FreeHGlobal(din.pbData); } //返回加密后的数据 return cipherText; } #endregion //解密数据 internal static void InitPromptstruct(ref DPAPI.CRYPTPROTECT_PROMPTSTRUCT ps) { ps.cbSize = Marshal.SizeOf(typeof(DPAPI.CRYPTPROTECT_PROMPTSTRUCT)); ps.dwPromptFlags = 0; ps.hwndApp = IntPtr.Zero; ps.szPrompt = null; } } //允许托管代码不经过堆栈步即调入非托管代码 [SuppressUnmanagedCodeSecurityAttribute()] internal class DPAPI { [DllImport("crypt32")] public static extern bool CryptProtectData(ref DATA_BLOB dataIn, string szDataDescr, IntPtr optionalEntropy, IntPtr pvReserved, IntPtr pPromptStruct, DataProtection.CryptProtectDataFlags dwFlags, ref DATA_BLOB pDataOut); [DllImport("crypt32")] public static extern bool CryptUnprotectData(ref DATA_BLOB dataIn, StringBuilder ppszDataDescr, IntPtr optionalEntropy, IntPtr pvReserved, IntPtr pPromptStruct, DataProtection.CryptProtectDataFlags dwFlags, ref DATA_BLOB pDataOut); [DllImport("Kernel32.dll")] public static extern IntPtr LocalFree(IntPtr hMem); [StructLayout(LayoutKind.Sequential)] public struct DATA_BLOB { public int cbData; public IntPtr pbData; } [StructLayout(LayoutKind.Sequential)] public struct CRYPTPROTECT_PROMPTSTRUCT { public int cbSize; // = Marshal.SizeOf(typeof(CRYPTPROTECT_PROMPTSTRUCT)) public int dwPromptFlags; // = 0 public IntPtr hwndApp; // = IntPtr.Zero public string szPrompt; // = null } } internal class Win32Error { [Flags()] public enum FormatMessageFlags : int { FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x0100, FORMAT_MESSAGE_IGNORE_INSERTS = 0x0200, FORMAT_MESSAGE_FROM_STRING = 0x0400, FORMAT_MESSAGE_FROM_HMODULE = 0x0800, FORMAT_MESSAGE_FROM_SYSTEM = 0x1000, FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x2000, FORMAT_MESSAGE_MAX_WIDTH_MASK = 0xFF, } [DllImport("Kernel32.dll")] public static extern int FormatMessage(FormatMessageFlags flags, IntPtr source, int messageId, int languageId, StringBuilder buffer, int size, IntPtr arguments); }
作者:pcbren 微信号:yadnfku QQ号: 254566449
博客地址:https://www.cnblogs.com/pcbren/
声明:本博客原创文字只代表本人工作中在某一时间内总结的观点或结论,与本人所在单位没有直接利益关系。非商业,未授权,贴子请以现状保留,转载时必须保留此段声明,且在文章页面明显位置给出原文连接。
如果大家感觉我的博文对大家有帮助,请推荐支持一把。