zoukankan      html  css  js  c++  java
  • C# winIO32位,64位的使用(运行时要用管理员身份)

    下载地址:
    http://www.internals.com/utilities/WinIo.zip

    一个按键的消息产生流程如下:

    1)硬件中断/硬件端口数据
    WinIO能模拟,或者修改IDT是在这一层
    2)键盘Port驱动(USB or PS/2)
    Filter驱动在此
    KeyboardClassServiceCallback也在这一层被调用
    3)kbdclass驱动
    处理键盘布局和键盘语言
    4)Windows内核边界(zwCreate/zwReadFile)
    ———————-(系统调用)———————-
    5)Windows内核边界(zwCreate/zwReadFile)
    6)csrss.exe的win32k!RawInputThread读取,完成scancode和vk的转换
    SetWindowHook工作在这里(全局)
    kbd_event工作在这里
    7)csrss.exe调用DispatchMessage等函数分发消息
    SetWindowHook工作在这里(进程)
    PostMessage和SendMessage在这里
    8)各个进程处理消息

    winIO可以模拟最底层的按键消息,借此可以绕过没有从消息循环读取消息的安全控件。在这只讲下64位系统下的用法,我的系统是win10 64位企业版。

    1.64位系统,C#使用WinIO64

    需要的文件:WinIo64.dll,WinIo64.sys
    a.首先安装WinIo64.sys的数字签名,
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述
    由于winIO64只有测试版的签名,我们需要把windows的测试模式打开。
    win键+R cmd:bcdedit /set testsigning on
    b.将整两个文件复制到跟exe同一目录。
    c.c#代码

    using System;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    
    namespace WinIOTest
    {
        public class WinIO
        {
            private const int KBC_KEY_CMD = 0x64;
            private const int KBC_KEY_DATA = 0x60;
    
            [DllImport("WinIo64.dll")]
            public static extern bool InitializeWinIo();
    
            [DllImport("WinIo64.dll")]
            public static extern bool GetPortVal(IntPtr wPortAddr, out int pdwPortVal, byte bSize);
    
            [DllImport("WinIo64.dll")]
            public static extern bool SetPortVal(uint wPortAddr, IntPtr dwPortVal, byte bSize);
    
            [DllImport("WinIo64.dll")]
            public static extern byte MapPhysToLin(byte pbPhysAddr, uint dwPhysSize, IntPtr PhysicalMemoryHandle);
    
            [DllImport("WinIo64.dll")]
            public static extern bool UnmapPhysicalMemory(IntPtr PhysicalMemoryHandle, byte pbLinAddr);
    
            [DllImport("WinIo64.dll")]
            public static extern bool GetPhysLong(IntPtr pbPhysAddr, byte pdwPhysVal);
    
            [DllImport("WinIo64.dll")]
            public static extern bool SetPhysLong(IntPtr pbPhysAddr, byte dwPhysVal);
    
            [DllImport("WinIo64.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;
                }
                else
                    MessageBox.Show("Load WinIO Failed!");
            }
            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);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107

    使用:

     WinIO.Initialize(); // 注册
     WinIO.KeyDown(Keys.A); // 按下A
     WinIO.KeyUp(Keys.A); // 松开A
     WinIO.Shutdown(); // 用完后注销
    • 1
    • 2
    • 3
    • 4

    2.64位系统,C#使用WinIO32
    切换成WinIO32,只需要[DllImport(“WinIo64.dll”)]改成[DllImport(“WinIo32.dll”)],WinIo32.dll复制到exe同一目录,运行时要用管理员身份。其他与winIO64一致。

    运行时要用管理员身份

    运行时要用管理员身份

    运行时要用管理员身份

    运行时要用管理员身份

    运行时要用管理员身份

  • 相关阅读:
    kubernetes安装记录
    nginx ssl 客户端认证配置调研
    centos 6 docker 安装(通过yum)
    elk docker 部署实战
    react 技术栈项目轻量化方案调研
    service worker 实战
    记一次 node-fetch 使用时踩的坑
    那些年使用npm进行依赖管理所踩的坑
    ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
    linux 环境变量设置错误导致 command not found
  • 原文地址:https://www.cnblogs.com/smallfa/p/5746854.html
Copyright © 2011-2022 走看看