b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

c# 模拟键盘 Windows消息命令一点也不“服从”(图)

电脑杂谈  发布时间:2021-03-08 20:03:17  来源:网络整理

游戏插件通常分为三个级别:主要级别是鼠标和键盘模拟,中间级别是Call游戏的内部功能,读写内存,高级级别是数据包捕获,“数据包的“离线挂起”(完全模拟客户端网络数据,无需运行游戏)。用C#编写的插件很少,其中大多数是C ++。主要原因是MS C#当前不支持内联汇编。因此,使用C ++编写基础库,然后使用C#调用它已成为DONET爱好者开发插件的首选。

对于鼠标和键盘模拟的插件,许认为没有技术上的内容,因为它只不过是SendMessage或Key_event,而更高级的一点是Hook进入了程序的内部操作。我还使用了这项技术来开发一些游戏辅助程序。但是最近我在研究XNA时遇到了一些麻烦,这种经过实践检验的方法实际上失败了。游戏根本不“服从”消息命令。我们有一个问题:它如何识别真实键盘的按键?该程序有判断力吗?

如果您忽略上述问题,请换个角度思考。在DOS时代,您还记得经典的Debug命令来删除BIOS密码吗?原理是使用BIOS中断。实际上,对于键盘按键,无论Windows如何打包,都会调用BIOS中断以最后识别按键。但是,消息发送毕竟是Windows系统的事情。无论在Windows级别上如何判断,我们只需要让BIOS下一个“神圣法令”,看​​看哪个游戏敢于如此傲慢! ! !

在更详细地解释该原理之前,让我们抓住幕后黑手,看看哪个人在支持游戏?让它有胆量违抗Windows message命令。是否判断了实际的键盘信息还是有其他原因?结果,我在DirectX编程中找到了DirectInput API。它绕过Windows的消息机制,其目的是使游戏的实时控制更好,更快。 Windows消息以队列的形式出现,并且传递过程会有所延迟。例如,格斗游戏对实时控制有很高的要求,而窗口消息机制不能满足这一要求。而且DirectInput直接与键盘驱动程序打交道,当然效率要高得多。我认为大多数游戏不响应消息的真正原因是在这里,而不是故意编写反作弊系统。

现在我们知道DirectInput正在解决问题,我们应该怎么做?我们前面提到了一个小想法,所以最实用的方法是直接读写键盘端口以模拟硬件事件。在DOS时代,每按一次键都会生成一个键盘中断,因此程序将跳至BIOS中的键盘中断以处理程序执行。当时,我最好的X是QBasic程序。 QBasic中有一个OUT函数可以将数据写入指定的端口,而INP函数可以从指定的端口读取数据。因此,使用QBasic进行硬件级键盘模拟非常简单。

如果此键的扫描代码为0x51,则首先模拟按下此键:

OUT&H64,&HD2'将数据0xD2发送到端口0x64。

OUT&H60,&H51'将扫描代码0x51发送到端口0x60,这意味着模拟按下扫描代码为0x51的按键

让我们模拟一下再次释放该按钮:

OUT&H64,&HD2'将数据0xD2发送到端口0x64。

OUT&H60,(&H50 OR&H8 0)'或扫描码0x50和数据0x80,这意味着释放此键。

当然,DOS时代已经过去了,但是我只是提到了QBasic的强大功能。如果真的使用QBasic编写模拟程序,则可以在Win98下成功,但是在Win2000之后的版本中将无法使用,因为DOS只是进入NT时代后的虚拟机系统。

现在的问题非常清楚,即如何在Windows环境中执行端口操作。由于级别较低,Windows无法让您如此轻松地成功。通常有两种方法:一种是使用驱动程序,而在驱动程序中还有什么不能做的呢?第二种是使用“呼叫门”从Ring3跳到Ring0来执行相关操作。在Internet上进行搜索应该可以找到相关信息。我听说Grid表示有一个名为“击键向导”的VB似乎还不错。下载并研究后,我发现它使用了外国人的WINIO驱动程序的原理。使用WINIO更加容易,因为我的驾驶能力确实是&* ^%$ ^&*。

因此,在WINIO的基础上,我使用C#进行了一个简单的辅助软件包,使其适合在DONET平台上使用驱动程序级按钮模拟。我的DLL中提供了以下方法:

InitSuperKeys()安装WINIO驱动程序,通常用于在Form_Load事件中调用

CloseSuperKeys()卸载通常用于调用Form_Closed事件的WINIO驱动程序

KeyDown(Key)模拟一个普通的Key键的按下。

KeyDownEx(Key)模拟按下扩展的Key键。

KeyUp(Key)模拟普通Key键的弹出窗口。

KeyUpEx(Key)模拟扩展键的向上键。

KeyPress(Key)模拟一次普通Key键的按下和弹出。按下和弹出之间的默认时间间隔为200毫秒

KeyPress(Key,Int3 2)模拟一次普通Key键的按下和弹出操作。两次按下之间的时间间隔是第二个参数,单位为毫秒。

KeyPressEx(Key)模拟扩展的按键并弹出一次。按下和弹出之间的默认时间间隔为200毫秒,写入扩展键信息的间隔为100毫秒

KeyPressEx(Key,Int3 2)模拟一次扩展键的按下和弹出。按下和弹出之间的时间间隔是第二个参数,单位为毫秒,写入扩展键信息的间隔为100毫秒。

KeyPressEx(Key,Int32,Int3 2)模拟一次扩展键Key的按下和弹出。按下和弹出之间的时间间隔是第二个参数,单位为毫秒,以及编写扩展键的间隔时间information是第三个参数,单位为毫秒。

特殊说明:

1、必须先执行InitSuperKeys()才能安装驱动程序,然后才能执行模拟密钥。最好在关闭窗口后卸载驱动程序。

2、上面方法中的参数Key是WinIoSys类中定义的枚举,而不是DONET系统的Key枚举。

3、普通键是指标准键盘键,例如A,B,C和Space。扩展键指的是诸如“方向键”之类的特殊键,在处理此类扩展键时,系统将首先有时间写入扩展键信息。因此,没有Ex结束的方法用于标准普通密钥,而具有Ex结束的方法用于特殊扩展密钥。它们全部超载,用户可以自行设置间隔。至于按钮的详细分类,请到Google自行搜索。

4、模拟按键事件后,必须让程序休眠几毫秒,否则下一个按键将无法正常模拟。

5、似乎USB占用了一条总线,该总线与端口操作无关,因此从理论上讲该方法不支持USB接口键盘。

6、一些防病毒软件会提醒用户安装驱动程序或将WinIo.sys报告为病毒。实际上,这是正常的。如果您从事此类异常活动,防病毒软件肯定会看不起它。请不要怀疑该程序是否包含病毒或木马,最简单的方法是关闭防病毒软件〜。如果您不担心,请不要使用它。

现在我们有了一个如此方便的界面,让我们尝试写一点东西来看看它的功能如何。让我们以“拳皇”为例。该游戏声称对Window消息绝对无效。

让我们创建一个新的EXE项目并引用我的SuperKeys.dll。定义一个全局变量

WinIoSys m_IoSys =新的WinIoSys();

在Load事件中安装驱动程序

m_IoSys.InitSuperKeys();

在Closed事件中卸载驱动程序

m_IoSys.CloseSuperKeys();

当然,我们可以编写一个全局钩子。当游戏运行时,可以通过按下某个键来模拟一系列按键。但这只是一个DEMO,不需要那么正式,只需编写一个计时器即可触发它。为了节省时间,请在每次单击按钮后三秒钟执行模拟按钮操作。请记住在这三秒钟内激活拳皇游戏窗口。

首先统一键盘设置,如图所示:

我们决定模拟最简单的“ Iori”方法:暗杀(即在地面上生火)。如果“ Iori”在左侧,则键盘操作为:↓↘→+ A或C。这是上图中的SDU或SDJ按钮。以SDJ为例,在模拟此键盘时必须非常小心。我开始像这样模拟它:

m_IoSys.KeyPress(WinIoSys.Key.VK_S);

Thread.Sleep(20 0);

m_IoSys.KeyPress(WinIoSys.Key.VK_D);

Thread.Sleep(20 0);

m_IoSys.KeyPress(WinIoSys.Key.VK_J,20 0);

结果不成功。我仔细研究了。实际上,当我们按下SDJ按钮时,我们首先按下S按钮,然后按下D按钮,然后弹起S按钮,然后是D按钮,最后按下J按钮。然后真实的过程应该这样写:

m_IoSys.KeyDown(WinIoSys.Key.VK_S);

Thread.Sleep(10 0);

m_IoSys.KeyDown(WinIoSys.Key.VK_D);

Thread.Sleep(10 0);

m_IoSys.KeyUp(WinIoSys.Key.VK_S);

Thread.Sleep(10 0);

m_IoSys.KeyUp(WinIoSys.Key.VK_D);

Thread.Sleep(1 0); //这个地方不能相隔太远,如果太大,则无法连接整个动作。

m_IoSys.KeyPress(WinIoSys.Key.VK_J,20 0);

测试后,成功模拟我们想要的操作。您可以看到实际的模拟按键效果。

该程序已在VS2008 + WinXP SP3 + WinKawaks 1. 48XP + KOF 2000 + P / S键盘下调试。

使用系统;

使用System.Collections.Generic;

使用System.Text;

使用System.Runtime.InteropServices;

命名空间lizheAionWG

{

公共类WinIo

模拟键盘软件_模拟键盘_c# 模拟键盘

{

public const int KBC_KEY_CMD = 0x64;

public const int KBC_KEY_DATA = 0x60;

[DllImport(“ winio.dll”)]

公共静态外部布尔InitializeWinIo();

[DllImport(“ winio.dll”)]

公共静态外部布尔GetPortVal(IntPtr wPortAddr,out int pdwPortVal,字节​​bSize);

[DllImport(“ winio.dll”)]

公共静态外部布尔SetPortVal(uint wPortAddr,IntPtr dwPortVal,字节​​bSize);

[DllImport(“ winio.dll”)]

公共静态外部字节MapPhysToLin(byte pbPhysAddr,uint dwPhysSize,IntPtr PhysicalMemoryHandle);

[DllImport(“ winio.dll”)]

公共静态外部布尔UnmapPhysicalMemory(IntPtr PhysicalMemoryHandle,字节pbLinAddr);

[DllImport(“ winio.dll”)]

公共静态外部布尔GetPhysLong(IntPtr pbPhysAddr,byte pdwPhysVal);

[DllImport(“ winio.dll”)]

公共静态外部布尔SetPhysLong(IntPtr pbPhysAddr,字节dwPhysVal);

[DllImport(“ winio.dll”)]

公共静态外部无效ShutdownWinIo();

[DllImport(“ user3 2. dll”)]

公共静态外部int MapVirtualKey(uint Ucode,uint uMapType);

public void sendwinio()

{

如果(InitializeWinIo())

{

KBCWait4IBE();

}

}

///等待缓冲区为空

私有无效KBCWait4IBE()

{

int dwVal = 0;

{

布尔标志= GetPortVal((IntPtr)0x64,出dwVal,1);

}

while(((dwVal&0x 2)> 0);

}

///按下

public void MykeyDown(int vKeyCoad)

{

int btScancode = 0;

btScancode = MapVirtualKey((byte)vKeyCoad,0);

KBCWait4IBE();

SetPortVal(KBC_KEY_CMD,(IntPtr)0xD2,1);

KBCWait4IBE();

SetPortVal(KBC_KEY_DATA,(IntPtr)0xe2,1);


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/bofangqi/article-362919-1.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    热点图片
    拼命载入中...