1. 程式人生 > >PCB 一鍵遠程桌面+RDP文件生成

PCB 一鍵遠程桌面+RDP文件生成

truct 成功 內存 wap tex reserve pro .sh 服務

最近在寫個內網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);
    }

PCB 一鍵遠程桌面+RDP文件生成