• C# 实现对接电信交费易自动缴费 续(winio/winring0 自动填密码)


    自动填密码大家可能都不莫生,最有名的应该是 按键精灵 只要是一个可以输入的地方都可以能过按键精灵来完成输入.我今天要讲的是使用 winio/winring0来完成类似的功能

    如果要自动填充密码方式基本上有 消息级的模拟 和 驱动级的模拟,

    消息级的模拟如 C# 直接使用 SendKeys 就可以完成 API下可以使用 SendMessage完成 即有了这个神器为什么还要用三方?

    答案:现在一些网都使用了ActiveX安全插件,如网银,支付宝,等,还有我们上一次说到的 翼支付和手机支付 它们基本上屏蔽了 SendMessage 有些就算可以使用但是不能得到正确的加密数据.还有更可气的是 在服务器远程操作中手动输入都不能输入密码.

    驱动级的就是硬盘的模拟 模拟键盘,大牛们可以直接操作  I/O 我这里讲的是使用三方类库来完成,

    第一个是 winIO 在XP时候我一直使用它,但到了  win7+64位模式下使用有点小问题,winIO 64位下驱动数字签名有点问题不能直接运行,需要将 win7转到测试模式下,安装数字证书而用程序还要在测试模式使用,如果是自己有可以凑合着,如果是给客户去使用,客户绝对会说你脑残,我运行个程序还要调这调那,当然是不愿意了.

    我现在就以 32位模式下来演示如何使用 winIO,首先是下载winIO 最新版本为 3.0 网官下载地址 http://www.internals.com/

    解压后,得到上图所示的文件 这个地方有用的 就是最后4个文件其它的是源文件和例子帮助文件之类的,

    跟据系统的不同来使用不同的文件 如果是  32位的就使用32结尾的两个.呵呵 直接把这两个放到你开发目录下的 bin/release 或 bin/debug下面就行了

    然后就是调用

     public class WinIO {
            public const int KBC_KEY_CMD = 0x64;//输入键盘按下消息的端口
    
            public const int KBC_KEY_DATA = 0x60;//输入键盘弹起消息的端口
    
            [DllImport("WinIo32.dll")]
            public static extern bool InitializeWinIo();
    
            [DllImport("WinIo32.dll")]
            public static extern bool GetPortVal(IntPtr wPortAddr, out int pdwPortVal, byte bSize);
    
    
    
            [DllImport("WinIo32.dll")]
            public static extern bool SetPortVal(uint wPortAddr, IntPtr dwPortVal, byte bSize);
    
    
    
            [DllImport("WinIo32.dll")]
            public static extern byte MapPhysToLin(byte pbPhysAddr, uint dwPhysSize, IntPtr PhysicalMemoryHandle);
    
    
    
            [DllImport("WinIo32.dll")]
            public static extern bool UnmapPhysicalMemory(IntPtr PhysicalMemoryHandle, byte pbLinAddr);
    
    
            [DllImport("WinIo32.dll")]
            public static extern bool GetPhysLong(IntPtr pbPhysAddr, byte pdwPhysVal);
    
            [DllImport("WinIo32.dll")]
            public static extern bool SetPhysLong(IntPtr pbPhysAddr, byte dwPhysVal);
    
            [DllImport("WinIo32.dll")]
            public static extern void ShutdownWinIo();
    
            [DllImport("user32.dll")]
            public static extern int MapVirtualKey(uint Ucode, uint uMapType);
    
    
    
    
            private WinIO() {
                IsInitialize = true;
            }
            public static void Initialize() {
                if (InitializeWinIo()) {
                    KBCWait4IBE();
                    IsInitialize = true;
                }
            }
            public static void Shutdown() {
                if (IsInitialize)
                    ShutdownWinIo();
                IsInitialize = false;
            }
    
            private static bool IsInitialize { get; set; }
    
            ///等待键盘缓冲区为空
            private static void KBCWait4IBE() {
                int dwVal = 0;
                do {
                    bool flag = GetPortVal((IntPtr)0x64, out dwVal, 1);
                }
                while ((dwVal & 0x2) > 0);
            }
            /// 模拟键盘标按下
            public static void KeyDown(Keys vKeyCoad) {
                if (!IsInitialize) return;
    
                int btScancode = 0;
                btScancode = MapVirtualKey((uint)vKeyCoad, 0);
                KBCWait4IBE();
                SetPortVal(KBC_KEY_CMD, (IntPtr)0xD2, 1);
                KBCWait4IBE();
                SetPortVal(KBC_KEY_DATA, (IntPtr)0x60, 1);
                KBCWait4IBE();
                SetPortVal(KBC_KEY_CMD, (IntPtr)0xD2, 1);
                KBCWait4IBE();
                SetPortVal(KBC_KEY_DATA, (IntPtr)btScancode, 1);
            }
            /// 模拟键盘弹出
            public static void KeyUp(Keys vKeyCoad) {
                if (!IsInitialize) return;
    
                int btScancode = 0;
                btScancode = MapVirtualKey((uint)vKeyCoad, 0);
                KBCWait4IBE();
                SetPortVal(KBC_KEY_CMD, (IntPtr)0xD2, 1);
                KBCWait4IBE();
                SetPortVal(KBC_KEY_DATA, (IntPtr)0x60, 1);
                KBCWait4IBE();
                SetPortVal(KBC_KEY_CMD, (IntPtr)0xD2, 1);
                KBCWait4IBE();
                SetPortVal(KBC_KEY_DATA, (IntPtr)(btScancode | 0x80), 1);
            }
        }

    上面这个类也是网上搜出来的,感觉前辈们的分享.此处只模拟了键盘的 按下和弹起

    使用实例

     String pass = "123456";
            foreach (char chr in pass) {
                WinIO.KeyDown((Keys)chr);
                Thread.CurrentThread.Join(100);
                WinIO.KeyUp((Keys)chr);
                Thread.CurrentThread.Join(100);
            }
            Thread.CurrentThread.Join(100);
            WinIO.Shutdown();

    这个地方按下的时候,稍停下,弹起也一样
    这样的话 winIO 的调用就完成了

    另一个神器就是 WinRing0 这个是一个开源的项目,可以通杀 32 64位系统, 不需要为驱动安装数字签名,自从发现了这个以后,我所有的需要自动填密码的项目都使用了它

    虽说开源,但是这个在网上的使用文档还是比较少,有的都是自带的一些文档和使用实例没有特殊意义的例子,说实话,这项目的找了好久才找到下载地址,大家如需要就留个邮箱,

    我看到后就发给你

    我们打开 release目录,

    复制相关的文件到你的工作开发目录下.

    sourcesampleCsOpenLibSys.cs 找到这个cs文件,这个是官方的所有的功能的封装,包括 I/O PCI CPU 等操作.把它加到我们的工程项目中

    新建一个类 WinRing 代码如下

    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    using System.Text;
    using OpenLibSys;
    
    class WinRing {
    
        public enum Key {
            ABSOLUTE = 0x8000,
            LEFTDOWN = 2,
            LEFTUP = 4,
            MIDDLEDOWN = 0x20,
            MIDDLEUP = 0x40,
            MOVE = 1,
            RIGHTDOWN = 8,
            RIGHTUP = 0x10,
            VIRTUALDESK = 0x4000,
            VK_A = 0x41,
            VK_ADD = 0x6b,
            VK_B = 0x42,
            VK_BACK = 8,
            VK_C = 0x43,
            VK_CANCEL = 3,
            VK_CAPITAL = 20,
            VK_CLEAR = 12,
            VK_CONTROL = 0x11,
            VK_D = 0x44,
            VK_DECIMAL = 110,
            VK_DELETE = 0x2e,
            VK_DIVIDE = 0x6f,
            VK_DOWN = 40,
            VK_E = 0x45,
            VK_END = 0x23,
            VK_ESCAPE = 0x1b,
            VK_EXECUTE = 0x2b,
            VK_F = 70,
            VK_F1 = 0x70,
            VK_F10 = 0x79,
            VK_F11 = 0x7a,
            VK_F12 = 0x7b,
            VK_F2 = 0x71,
            VK_F3 = 0x72,
            VK_F4 = 0x73,
            VK_F5 = 0x74,
            VK_F6 = 0x75,
            VK_F7 = 0x76,
            VK_F8 = 0x77,
            VK_F9 = 120,
            VK_G = 0x47,
            VK_H = 0x48,
            VK_HELP = 0x2f,
            VK_HOME = 0x24,
            VK_I = 0x49,
            VK_INSERT = 0x2d,
            VK_J = 0x4a,
            VK_K = 0x4b,
            VK_L = 0x4c,
            VK_LBUTTON = 1,
            VK_LEFT = 0x25,
            VK_M = 0x4d,
            VK_MBUTTON = 4,
            VK_MENU = 0x12,
            VK_N = 0x4e,
            VK_NEXT = 0x22,
            VK_NULTIPLY = 0x6a,
            VK_NUM0 = 0x30,
            VK_NUM1 = 0x31,
            VK_NUM2 = 50,
            VK_NUM3 = 0x33,
            VK_NUM4 = 0x34,
            VK_NUM5 = 0x35,
            VK_NUM6 = 0x36,
            VK_NUM7 = 0x37,
            VK_NUM8 = 0x38,
            VK_NUM9 = 0x39,
            VK_NUMLOCK = 0x90,
            VK_NUMPAD0 = 0x60,
            VK_NUMPAD1 = 0x61,
            VK_NUMPAD2 = 0x62,
            VK_NUMPAD3 = 0x63,
            VK_NUMPAD4 = 100,
            VK_NUMPAD5 = 0x65,
            VK_NUMPAD6 = 0x66,
            VK_NUMPAD7 = 0x67,
            VK_NUMPAD8 = 0x68,
            VK_NUMPAD9 = 0x69,
            VK_O = 0x4f,
            VK_P = 80,
            VK_PAUSE = 0x13,
            VK_PRINT = 0x2a,
            VK_PRIOR = 0x21,
            VK_Q = 0x51,
            VK_R = 0x52,
            VK_RBUTTON = 2,
            VK_RETURN = 13,
            VK_RIGHT = 0x27,
            VK_S = 0x53,
            VK_SCROLL = 0x91,
            VK_SELECT = 0x29,
            VK_SEPARATOR = 0x6c,
            VK_SHIFT = 0x10,
            VK_SNAPSHOT = 0x2c,
            VK_SPACE = 0x20,
            VK_SUBTRACT = 0x6d,
            VK_T = 0x54,
            VK_TAB = 9,
            VK_U = 0x55,
            VK_UP = 0x26,
            VK_V = 0x56,
            VK_W = 0x57,
            VK_X = 0x58,
            VK_Y = 0x59,
            VK_Z = 90,
            WHEEL = 0x800,
            XDOWN = 0x80,
            XUP = 0x100
        }
    
    
    
        static OpenLibSys.Ols ols = null;
    
        [DllImport("user32.dll")]
        public static extern int MapVirtualKey(uint Ucode, uint uMapType);
    
        public static Boolean init() {
            ols = new OpenLibSys.Ols();
            return ols.GetStatus() == (uint)Ols.Status.NO_ERROR;
        }
    
        private static void KBCWait4IBE() {
            byte dwVal = 0;
            do {
                ols.ReadIoPortByteEx(0x64, ref dwVal);
            }
            while ((dwVal & 0x2) > 0);
        }
        public static void KeyDown(Char ch) {
            int btScancode = MapVirtualKey((uint)(Key)ch, 0);
            KBCWait4IBE();
            ols.WriteIoPortByte(0x64, 0xd2);
            KBCWait4IBE();
            ols.WriteIoPortByte(0x60, (byte)btScancode);
        }
    
        public static void KeyUp(Char ch) {
            int btScancode = MapVirtualKey((uint)(Key)ch, 0);
            KBCWait4IBE();
            ols.WriteIoPortByte(0x64, 0xd2);
            KBCWait4IBE();
            ols.WriteIoPortByte(0x60, (byte)(btScancode | 0x80));
        }
    }

    也只是模拟了 按下和弹起 以下为调用方式

    String pwd = "123456";
            foreach (char chr in pwd) {
                WinRing.init();
                WinRing.KeyDown(chr);
                Thread.Sleep(100);
                WinRing.KeyUp(chr);
            }
            Thread.CurrentThread.Join(100);


    到此 这两个类库的使用就介绍完了,但是在真正项目中可能会遇到各种问题,这就需我们的经验和处理问题的能力了.

    注:这两个类库有一个通病就是不支持 USB键盘的模拟.估计是我没有研究出来吧

    --幸福海

    博客地址:http://www.cnblogs.com/ningqhai/

    --幸福海 微信号:ningqhai
  • 相关阅读:
    Requests 库
    Mac下终端配置(item2 + oh-my-zsh + solarized配色方案)
    中文名文件上传到linux服务器上以后文件名会乱码(openoffice)
    scp
    请求https前缀的网站验证SSL证书的解决方案之一
    jupyter notebook更换主题 步骤详解。
    jupyter nbextensions的 安装
    装饰器的学习 高级版-- 语法糖参数
    装饰器的学习 初级版-- 高阶函数,嵌套函数,闭包
    Python数据可视化的完整版操作指南(建议收藏)
  • 原文地址:https://www.cnblogs.com/ningqhai/p/4236398.html
Copyright © 2020-2023  润新知