评论

收藏

[C++] C# winIO32位,64位的使用(运行时要用管理员身份)

编程语言 编程语言 发布于:2021-07-26 15:30 | 阅读数:519 | 评论:0

下载地址:
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的数字签名,
DSC0000.png
DSC0001.png
DSC0002.png
DSC0003.png
由于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一致。
运行时要用管理员身份
运行时要用管理员身份
运行时要用管理员身份
运行时要用管理员身份
运行时要用管理员身份


关注下面的标签,发现更多相似文章