安全控件文本的输入

来源:互联网 发布:dos下运行java程序 编辑:程序博客网 时间:2024/04/29 07:46
老大让用webbrowser控件来自动输入银行登陆界面,webbrowser结合HtmlDocument可以搞定普通文本框的输入。
#region 输入用户名abc            HtmlDocument cd = webBrowser1.Document;            HtmlElement element = webBrowser1.Document.GetElementById("txt_username_79443");            if (element != null)            {                element.InnerText = "abc";            }            #endregion

但是密码框是安全控件,思考了半天,经高人指点,发现只能通过两种方法来输入:第一种是分析http协议(感觉就超级累的活,所以就放弃了)。


第二种就是现在我用的方法,就是用窗口探测器探测窗口,分析清楚层级关系之后,用winapi函数来控制。

模拟键盘输入需要的api函数,主要就是获取句柄,操作句柄,以及发消息的方法。

#region 模拟键盘输入密码用到的api函数        private IntPtr pwdHandle;                [DllImport("User32.dll", EntryPoint = "FindWindow")]//EntryPoint为要调用的dll的入口点名称        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);//extern用于声明在外部实现的方法        [DllImport("User32.dll", EntryPoint = "FindWindowEx")]//找子窗体        private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpsazClass, string lpszWindow);        [DllImport("User32.dll", EntryPoint = "SendMessage")]//用于发送消息给窗体        private static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, string lParam);        /// <summary>        /// 用于枚举子窗体的委托        /// </summary>        /// <param name="WindowHandle">窗体句柄</param>        /// <param name="num">自定义</param>        /// <returns></returns>        public delegate bool EnumChildWindow(IntPtr WindowHandle, string num);        /// <summary>        /// 获取指定窗体的所有子窗体        /// </summary>        /// <param name="WinHandle">窗体句柄</param>        /// <param name="ecw">回调委托</param>        /// <param name="name">自定义</param>        /// <returns></returns>        [DllImport("User32.dll")]        public static extern int EnumChildWindows(IntPtr WinHandle, EnumChildWindow ecw, string name);        [DllImport("user32.dll")]        public static extern int GetClassName(IntPtr WinHandle, StringBuilder Type, int size);        IntPtr mainHwnd = IntPtr.Zero;//登录窗口句柄        string typeName = string.Empty;//启动程序的窗口标题        /// <summary>        /// 枚举窗体的回调函数        /// </summary>        /// <param name="handle"></param>        /// <param name="num"></param>        /// <returns></returns>        private bool EnumChild(IntPtr handle, string num)        {            pwdHandle = handle;            return true;        }        #endregion
注意这里的枚举函数,需要用一个代理,然后写个回调函数(终于基本弄清楚代理的含义了)

下面就是使用这些函数来查找窗体句柄,并用sendmessage发送消息来控制了。

#region 输入密码            var ctl = FindWindowEx(webBrowser1.Handle, IntPtr.Zero, "Shell Embedding", null);            if (ctl == IntPtr.Zero) { MessageBox.Show("获取句柄失败!"); return; }            ctl = FindWindowEx(ctl, IntPtr.Zero, "Shell DocObject View", null);            if (ctl == IntPtr.Zero) { MessageBox.Show("获取句柄失败!"); return; }            ctl = FindWindowEx(ctl, IntPtr.Zero, "Internet Explorer_Server", null);            if (ctl == IntPtr.Zero) { MessageBox.Show("获取句柄失败!"); return; }            //枚举子窗体            EnumChildWindow ecw = EnumChild;            EnumChildWindows(ctl, ecw, "");            if (ctl == IntPtr.Zero) { MessageBox.Show("获取句柄失败!"); return; }            //弹出classname,看句柄是否正确            var cn = new StringBuilder(100);            GetClassName(pwdHandle, cn, 100);            MessageBox.Show(cn.ToString(), "密码控件classname");            //点击左键,获取输入焦点            SendMessage(pwdHandle, 0x201, IntPtr.Zero, null);//0x201鼠标左键点击            //输入密码(abc)            SendMessage(pwdHandle, 0x0100, (IntPtr)0x41, null);//0x0100是按键的意思,ox41是a,后面的依次类推            SendMessage(pwdHandle, 0x0100, (IntPtr)0x42, null);            SendMessage(pwdHandle, 0x0100, (IntPtr)0x43, null);            #endregion
注意,不能再webbrowser的completed事件里面写,不然始终找不到安全控件的句柄。。。
好了,大功告成。

其实想一想,如果能够破解验证码的话,就可以写个穷举循环,暴力破解登录页面了。呵呵。

0 0
原创粉丝点击