下载地址:
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一致。

运行时要用管理员身份

运行时要用管理员身份

运行时要用管理员身份

运行时要用管理员身份

运行时要用管理员身份

C# winIO32位,64位的使用(运行时要用管理员身份)的更多相关文章

  1. VC++运行库 集32位/64位整合版

    运行程序时,win7/win10(x86和x64)常会遇到缺少什么缺少msvc***.dll问题 安装下面链接提供的程序,安装后,便可解决. [2016-10-10]Microsoft Visual ...

  2. dll文件32位64位检测工具以及Windows文件夹SysWow64的坑

    自从操作系统升级到64位以后,就要不断的需要面对32位.64位的问题.相信有很多人并不是很清楚32位程序与64位程序的区别,以及Program Files (x86),Program Files的区别 ...

  3. 最新Internet Download Manager (IDMan) 6.25 Build 20 32位 64位注册破解补丁

    0x00 IDMan介绍 Internet Download Manager提升你的下载速度最多达5倍,安排下载时程,或续传一半的软件.Internet Download Manager的续传功能可以 ...

  4. dll文件32位64位检测工具以及Windows文件夹SysWow64的坑(很详细,还有自动动手编程探测dll)

    阅读目录 dll文件不匹配导致数据库无法启动 究竟是System32还是SysWow64 区分dll文件32位64位的程序让我倍感迷惑 再次判断究竟是System32还是SysWow64——意想不到的 ...

  5. SQLite在.NET中自适应32位/64位系统

    如果一个.NET应用要自适应32位/64位系统,只需要在项目的“目标平台”设置为“Any CPU”.但是如果应用中使用了SQLite,情况就不同了. SQLite的.NET开发包来自是System.D ...

  6. dll文件32位64位检测工具以及Windows文件夹SysWow64的坑【转发】

    原文地址:http://www.cnblogs.com/hbccdf/archive/2014/03/09/3590916.html 自从操作系统升级到64位以后,就要不断的需要面对32位.64位的问 ...

  7. 让使用SQLite的.NET应用自适应32位/64位系统

    如果一个.NET应用要自适应32位/64位系统,只需要在项目的“目标平台”设置为“Any CPU”.但是如果应用中使用了SQLite,情况就不同了. SQLite的.NET开发包来自是System.D ...

  8. SQLite的.NET应用自适应32位/64位系统 z

    如果一个.NET应用要自适应32位/64位系统,只需要在项目的“目标平台”设置为“Any CPU”.但是如果应用中使用了SQLite,情况就不同了. SQLite的.NET开发包来自是System.D ...

  9. [转载]使用32位64位交叉编码混淆来打败静态和动态分析工具 - wildsator

    0×00 摘要 混淆是一种能增加二进制分析和逆向工程难度与成本的常用技术.主流的混淆技术都是着眼于使用与目标CPU相同的机器代码,在相同的处理器模式下,隐藏代码并进行控制.本文中引入了一种新的混淆方法 ...

随机推荐

  1. eclipse 创建注释模板

    使用  Alt+Shift+J 可以快速注释. 我们每次手动敲入作者,时间,版本等信息,有一些重复,可通过设置eclipse注释模板,减少工作量. Window -> preference -& ...

  2. 8 python time$datetime

    1.表示时间的方式 (1)时间戳 时间戳(timestamp)的方式:通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量. 我们运行“type(time.time())” ...

  3. Swift - JPush极光推送的使用3(根据Alias别名,给某个指定用户发推送)(转)

    一.别名(alias)介绍 (1)我们可以给每一个安装了应用程序的用户,取不同别名来标识(比如可以使用用户账号的 userid 来作为别名). (2)以后给某个特定用户推送消息时,就可以用此别名来指定 ...

  4. mysql创建定时器(event),查看定时器,打开定时器,设置定时器时间

    由于项目需要创建定时器(evevt),所以就百度了一下,发现基本都是来源于一个模板,有些功能还不全,现在自己总结一下. 注:mysql版本是从5.1开始才支持event的.如果你的版本低于5.1就先升 ...

  5. nmap扫描工具

    1.NMap工具 主要功能:探测主机是否在线.扫描主机开放端口和嗅探网络服务,用于网络探测和安全扫描. NMap支持很多扫描技术,例如:UDP.TCPconnect().TCPSYN(半开扫描).ft ...

  6. Hibernate 的Ehache学习

    Hibernate默认二级缓存是不启动的,启动二级缓存(以EHCache为例)需要以下步骤: 1.添加相关的包: Ehcache.jar和commons-logging.jar,如果hibernate ...

  7. base和this

    base//只能继承其直接基类成员 常用于对象初始化时和基类通信1.base局限于构造函数.实例方法.实例属性访问其中2.base调用直接基类已被重写的方法,或者所有父类的非重载方法3.base制定创 ...

  8. C# 窗口页面卡的处理方案-异步编程委托

    今天用winform做了一个小程序,主要是用于远程数据的登录采集,因为数据量非常大,到时每次点击按钮执行程序的时候界面都会出现假死状态,具体表现是无法拖动窗口,无法最小化或关闭等,只能任务管理进程结束 ...

  9. 实现Action的三种方式

    实现Action的三种方式: 1.普通类  一般采用此种方法 2.实现Action接口 3.继承ActionSupport类

  10. jquery clone 获取文本框值得问题

    1 clone 出来的文本框 默认不会把原来的事件也带过去 如果使用 $("#").clone(true);   true  可以将原来的事件带过去 获取文本框的值 可以使用事件 ...