winio 初始化失败这个怎么在按键了用啊我的一直是加载失败

本帖子已过去太久远了,不再提供回复功能。Win64上底层方式模拟按键制作GTA外挂
问题由来 我比较喜欢玩《 侠盗 猎车:自由城之章》(简称《GTA:EFLC》)。不过本人玩 游戏 的水平 比较菜,经常被 游戏 里的贼和警察狂虐,心里十分不爽,而网上下载的 外挂 不是有病毒就是 不能用, 游戏 内置的作弊器操作很麻烦,于是萌生了自己做一个 外
我比较喜欢玩《侠盗猎车:自由城之章》(简称《GTA:EFLC》)。不过本人玩游戏的水平
比较菜,经常被游戏里的贼和警察狂虐,心里十分不爽,而网上下载的外挂不是有病毒就是
不能用,游戏内置的作弊器操作很麻烦,于是萌生了自己做一个外挂的想法。在游戏里,只
要输入一个十位数的作弊码就能进行一系列的作弊,比如补全生命,获得武器,修复汽车等。
但由于要输入10个毫无规律的数字,让人很是抓狂。而且在进行这一系列操作时,往往还
必须进行其它操作,比如驾车、枪战。往往一个不小心,就GameOver了。利用模拟按键的
方式输入,能节省宝贵的时间。
因为《GTA:EFLC》是 DirectX游戏,所以一切user32.dll提供的模拟按键函数(如
SendInput之流)都失效了,因为DirectX游戏是利用DirectInput绕过Windows的消息机
制直接和硬件打交道来接收按键信息的。因此,我们必须使用驱动级别的模拟按键。但是在
驱动里如何进行模拟按键,我全然不知,一时我的研究就陷入的僵局。后来偶然得知了WinIO
这个神器,于是开始了我的研究历程。
WinIO是一款免费、开源的系统组件,你可以在上面免费下载它的
源码。在最新版本3.0中,增加了对64位 Windows操作系统的支持。我就是利用它的功能,
实现了驱动级模拟按键。在我使用的WinIO 3.0中,里面有四个bin 文件,分别是
WinIO32.dll、WinIO64.dll、WinIO32.sys、WinIO64.sys。sys文件是实现核心功能的驱动,
dll文件是封装驱动功能的接口。由于我的系统是64 位系统,使用了VB做界面编程,所以
仅需要 WinIO32.dll和 WinIO64.sys。dll 文件有 10 个导出函数。在我的模拟按键程序里,
仅需要用到四个:InitializeWinIo、ShutdownWinIo、GetPortVal、SetPortVal。
说到驱动模拟按键,其实就是读写端口。说到读写端口,其实学过16位汇编的人都知
道,用 IN、OUT指令即可。不过可别忘记了,IN、OUT 指令属于特权指令,所以在 Ring 3
下不能调用,必须在驱动里调用。不过WinIO的作者并没有用内联汇编的方法实现读写IO
端口,而是使用了文档化的READ_PORT_UCHAR、READ_PORT_USHORT、READ_PORT_ULONG、
WRITE_PORT_UCHAR、WRITE_PORT_USHORT、WRITE_PORT_ULONG函数来实现。个人认为内联汇
编是一个不好的习惯,因为这样使代码有了很强的平台限制性。网上一些所谓的高手特别喜
欢在代码里内联汇编,以显示所谓的&高手风范&。其实恰恰相反,我在学驱动初期就特别
喜欢在驱动代码里内联汇编模仿&高手&,现在到是能不内联汇编就不内联汇编,以提高代
码的通用程度。
言归正传,我们要用到的四个函数原型和功能如下:
bool _stdcall InitializeWinIo();&&&& &This function initializes the WinIo
void _stdcall ShutdownWinIo();&&&&&& &This function performs cleanup of the
WinIo library.&
bool _stdcall GetPortVal(
&& WORD wPortAddr,&&&&&&&
&& PDWORD pdwPortVal,&&&&
&& BYTE bSize&&&&&&&&&&&&
);&&&&&&&&&&&&&&&&
&&&&&&&&&& This function reads a BYTE/WORD/DWORD
value from an I/O port.&
bool _stdcall SetPortVal(
&& WORD wPortAddr,&&&&&&&
&& DWORD dwPortVal,&&&&&&
&& BYTE bSize&&&&&&&&&&&&
);&&&&&&&&&&&
&&&&&&&&&&&& This function writes a BYTE/WORD/DWORDvalue to an I/O port.
根据 VB 和C代码的互换规则,得到以下声明:
Public Declare Function InitializeWinIo Lib &WinIo.dll& () As Boolean
Public Declare Function ShutdownWinIo Lib &WinIo.dll& () As Boolean
Public Declare Function GetPortVal Lib &WinIo.dll& (ByVal PortAddr As Integer,
ByRef PortVal As Long, ByVal bSize As Byte) As Boolean
Public Declare Function SetPortVal Lib &WinIo.dll& (ByVal PortAddr As Integer,
我比较喜欢玩《侠盗猎车:自由城之章》(简称《GTA:EFLC》)。不过本人玩游戏的水平
比较菜,经常被游戏里的贼和警察狂虐,心里十分不爽,而网上下载的外挂不是有病毒就是
不能用,游戏内置的作弊器操作很麻烦,于是萌生了自己做一个外挂的想法。在游戏里,只
要输入一个十位数的作弊码就能进行一系列的作弊,比如补全生命,获得武器,修复汽车等。
但由于要输入10个毫无规律的数字,让人很是抓狂。而且在进行这一系列操作时,往往还
必须进行其它操作,比如驾车、枪战。往往一个不小心,就GameOver了。利用模拟按键的
方式输入,能节省宝贵的时间。
因为《GTA:EFLC》是 DirectX游戏,所以一切user32.dll提供的模拟按键函数(如
SendInput之流)都失效了,因为DirectX游戏是利用DirectInput绕过Windows的消息机
制直接和硬件打交道来接收按键信息的。因此,我们必须使用驱动级别的模拟按键。但是在
驱动里如何进行模拟按键,我全然不知,一时我的研究就陷入的僵局。后来偶然得知了WinIO
这个神器,于是开始了我的研究历程。
WinIO是一款免费、开源的系统组件,你可以在www.jybase.net下载它的
源码。在最新版本3.0中,增加了对64位 Windows操作系统的支持。我就是利用它的功能,
实现了驱动级模拟按键。在我使用的WinIO 3.0中,里面有四个bin 文件,分别是
WinIO32.dll、WinIO64.dll、WinIO32.sys、WinIO64.sys。sys文件是实现核心功能的驱动,
dll文件是封装驱动功能的接口。由于我的系统是64 位系统,使用了VB做界面编程,所以
仅需要 WinIO32.dll和 WinIO64.sys。dll 文件有 10 个导出函数。在我的模拟按键程序里,
仅需要用到四个:InitializeWinIo、ShutdownWinIo、GetPortVal、SetPortVal。
说到驱动模拟按键,其实就是读写端口。说到读写端口,其实学过16位汇编的人都知
道,用 IN、OUT指令即可。不过可别忘记了,IN、OUT 指令属于特权指令,所以在 Ring 3
下不能调用,必须在驱动里调用。不过WinIO的作者并没有用内联汇编的方法实现读写IO
端口,而是使用了文档化的READ_PORT_UCHAR、READ_PORT_USHORT、READ_PORT_ULONG、
WRITE_PORT_UCHAR、WRITE_PORT_USHORT、WRITE_PORT_ULONG函数来实现。个人认为内联汇
编是一个不好的习惯,因为这样使代码有了很强的平台限制性。网上一些所谓的高手特别喜
欢在代码里内联汇编,以显示所谓的&高手风范&。其实恰恰相反,我在学驱动初期就特别
喜欢在驱动代码里内联汇编模仿&高手&,现在到是能不内联汇编就不内联汇编,以提高代
码的通用程度。
言归正传,我们要用到的四个函数原型和功能如下:
bool _stdcall InitializeWinIo();&&&& &This function initializes the WinIo
void _stdcall ShutdownWinIo();&&&&&& &This function performs cleanup of the
WinIo library.&
bool _stdcall GetPortVal(
&& WORD wPortAddr,&&&&&&&
&& PDWORD pdwPortVal,&&&&
&& BYTE bSize&&&&&&&&&&&&
);&&&&&&&&&&&&&&&&
&&&&&&&&&& This function reads a BYTE/WORD/DWORD
value from an I/O port.&
bool _stdcall SetPortVal(
&& WORD wPortAddr,&&&&&&&
&& DWORD dwPortVal,&&&&&&
&& BYTE bSize&&&&&&&&&&&&
);&&&&&&&&&&&
&&&&&&&&&&&& This function writes a BYTE/WORD/DWORDvalue to an I/O port.
根据 VB 和C代码的互换规则,得到以下声明:
Public Declare Function InitializeWinIo Lib &WinIo.dll& () As Boolean
Public Declare Function ShutdownWinIo Lib &WinIo.dll& () As Boolean
Public Declare Function GetPortVal Lib &WinIo.dll& (ByVal PortAddr As Integer,
ByRef PortVal As Long, ByVal bSize As Byte) As Boolean
Public Declare Function SetPortVal Lib &WinIo.dll& (ByVal PortAddr As Integer,
ByVal PortVal As Long, ByVal bSize As Byte) As Boolean
以下代码实现了模拟按键:
Public Const KBC_KEY_CMD = &H64
Public Const KBC_KEY_DATA = &H60
Public Sub KBCWait4IBE()
&&& Dim dwVal As Long
&&&&&&& GetPortVal KBC_KEY_CMD, dwVal, 1
&&& Loop While (dwVal And &H2)
Public Sub MyKeyDown(ByVal vKeyCode As Long)
&&& KBCWait4IBE
&&& SetPortVal KBC_KEY_CMD, &HD2, 1
&&& KBCWait4IBE
&&& SetPortVal KBC_KEY_DATA, MapVirtualKey(vKeyCode, 0), 1
&&& Sleep 100
&&& KBCWait4IBE
&&& SetPortVal KBC_KEY_CMD, &HD2, 1
&&& KBCWait4IBE
&&& SetPortVal KBC_KEY_DATA, (MapVirtualKey(vKeyCode, 0) Or &H80), 1
比如我要模拟按下小键盘上的0,仅需要以下代码:MyKeyDown VK_NUMPAD0。其中
VK_NUMPAD0是小键盘上0的虚拟键码,这些虚拟键码在winuser.h里有定义。不过不能连
续按下两个相同的键,如果连续按下两个相同的键,会出现只有一个按下的效果。在按下两
个相同的键时,要等待上50 毫秒。比如实现补血的作弊码是,那么代码这么写:&
MyKeyDown VK_NUMPAD3
MyKeyDown VK_NUMPAD6
MyKeyDown VK_NUMPAD2
MyKeyDown VK_NUMPAD5
MyKeyDown VK_NUMPAD5
MyKeyDown VK_NUMPAD5
MyKeyDown VK_NUMPAD0
MyKeyDown VK_NUMPAD1
MyKeyDown VK_NUMPAD0
MyKeyDown VK_NUMPAD0
MyKeyDown VK_RETURN
需要说明的是,WinIO64.sys没有正式的数字签名,只有测试签名。要使它能成功加载,
必须打开测试模式(cmd里切换到 system32目录再输入 bcdedit /set testsigning on),
然后根据以下步骤信任WinIO64.sys的测试签名:
1.打开 WinIO64.sys的属性框,翻到&数字签名&选项卡,点击&详细信息&
2.在新出来的对话框中点击&查看证书&
3.在又新出来的对话框中点击&安装证书&
4.点击&下一步&,然后选择&将所有的证书放入下列存储&
5.点击浏览,选择&受信任的根证书发布机构&
650) this.width=650;" >
6.点击&下一步&,然后点击&完成&
7.在弹出的&安全性警告&对话框中选择&是&,才能导入成功
&& 在我的那个外挂中,除了驱动模拟按键,还有注册热键等代码,因为这个和本文主题无
关,所以就略过不表了。最终实现的效果就是在游戏中按下F1到F6 六个键,实现了六个作
弊功能。要进行测试很简单,先运行我的程序,再打开记事本,分别按下F1至 F6,就能输
入六串数字。当然也可以随便申请一个QQ 号,密码设置为,然后把光标放到密
码框里,按下F1,就会能自动登录了(QQ 的密码框防止了普通方式的模拟按键,一般来说
需要用驱动模拟按键)。
你最喜欢的C#使用WinIo硬件模拟键盘**
下载WinIo的zip包,解压之后会有4个文件,win32.dll win32.sys win64.dll win64.sys。
把dll文件和sys文件放在同一个目录下,一般放在工程debug下。
设置虚拟码
public enum VKKey
VK_A = 65,
VK_B = 66,
VK_C = 67,
VK_D = 68,
VK_E = 69,
VK_F = 70,
VK_G = 71,
VK_H = 72,
VK_I = 73,
VK_J = 74,
VK_K = 75,
VK_L = 76,
VK_M = 77,
VK_N = 78,
VK_O = 79,
VK_P = 80,
VK_Q = 81,
VK_R = 82,
VK_S = 83,
VK_T = 84,
VK_U = 85,
VK_V = 86,
VK_W = 87,
VK_X = 88,
VK_Y = 89,
VK_Z = 90,
VK_LEFT = 37,
VK_UP = 38,
VK_RIGHT = 39,
VK_DOWN = 40,
然后声明各种所需要的dll中的函数
[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();
声明和实现自己编写的按键函数。
public static void Initialize()
if (InitializeWinIo())
KBCWait4IBE(); IsInitialize = true;
System.Console.WriteLine("有问题");
public static void Shutdown()
if (IsInitialize)
ShutdownWinIo();
IsInitialize = false;
private static void KBCWait4IBE()
int dwVal = 0;
bool flag = GetPortVal((IntPtr)0x64, out dwVal, 1);
while ((dwVal & 0x2) & 0);
public static void MykeyDown(VKKey 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)btScancode, 1);
System.Console.WriteLine("按下");
public static void MykeyUp(VKKey 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)(btScancode | 0x80), 1);
System.Console.WriteLine("弹起");
在main函数中,调用自己的按键函数
MykeyDown(VKKey.VK_D)
MykeyUp(VKKey.VK_D)
这样便可以绕过windows消息机制,直接向io端口写消息。
InitializeWinIo()初试化失败。
解决办法: 将dll文件和sys文件放在工程中。
因为会用到驱动,所以应该将windows设置为test mode。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:413次
排名:千里之外

我要回帖

更多关于 winio 初始化失败 的文章

 

随机推荐