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一致。

 

運行時要用管理員身份

運行時要用管理員身份

運行時要用管理員身份

運行時要用管理員身份

運行時要用管理員身份

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM