首页
社区
课程
招聘
winio模拟键盘鼠标的输入
2006-4-8 17:07 28919

winio模拟键盘鼠标的输入

2006-4-8 17:07
28919
做一个游戏外挂,发现其屏蔽了sendinput消息。
但是按键精灵能够实现。得知其原理是使用winio.dll,伪装硬件消息。

网上winio关于鼠标键盘模拟极少。

void CIotestDlg::KbcWait4IBE()
{
        DWORD dwRegVal=0;
        do
        {       
                GetPortVal(0x64,&dwRegVal,1);
        }
        while(dwRegVal & 0x00000001);
}

void CIotestDlg::KeyPress(BYTE byScancode)
{
        KbcWait4IBE();//Wait for KBC input buffer empty
        SetPortVal(0x64,0xD2,1);//Send data back to the system command
       
        KbcWait4IBE();//Wait for KBC input buffer empty
        SetPortVal(0x60,(ULONG)byScancode,1);//Send the key down scancode
       
        KbcWait4IBE();//Wait for KBC input buffer empty
        SetPortVal(0x64,0xD2,1);//Send data back to the system command
       
        KbcWait4IBE();//Wait for KBC input buffer empty
        SetPortVal(0x60,(ULONG)(byScancode | 0x80),1);//Send the key up scancode
}

这是找到的键盘模拟片断。
做了一个测试程序,发现没有成功响应虚拟的按键消息。

进行keypress(VK_LBUTTON)的时候,测试的dialog直接自动退出,未知原因。
其他keypress(VK_TAB)则没有响应。

[培训]《安卓高级研修班(网课)》月薪三万计划,掌 握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞7
打赏
分享
最新回复 (30)
雪    币: 216
活跃值: (42)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dezone 2006-4-9 17:37
2
0
以下是采用WinIo直接向ps2键盘(或鼠标)缓冲区写数据的方法。
winxpsp2下测试通过!

procedure SetKey(SCanCode: byte);
begin
  asm
    //无论向0x60,还是0x64写东西前都要等状态寄存器OBF变0
    @Loop1:
    in al, $64
    and al, 01b
    jnz @Loop1
    //向$64端口写命令
    mov al, $D2//写键盘输出缓存命令
    out $64, al

    //无论向0x60,还是0x64写东西前都要等状态寄存器OBF变0
    @Loop2:
    in al, $64
    and al, 01b
    jnz @Loop2
    //向$60端口写参数
    mov al, SCanCode
    out $60, al
  end;
end;

模拟非扩展键:
SetKey($1F);//make codes
Sleep(25);
SetKey($9F);//break code

模拟扩展键:
SetKey($E0);//因为这是一个扩展键
SetKey($4B);//make codes
Sleep(25);
SetKey($E0);//因为这是一个扩展键
SetKey($CB);//break code
模拟鼠标的类似。

你指的是什么游戏,SendInput不太可能被屏蔽,可能你的使用方法有误!
雪    币: 216
活跃值: (42)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dezone 2006-4-9 17:45
3
0
忘了跟你说,不建议采用winio自身的SetPortVal函数,这样效率太慢,而是直接用汇编写端口,当载入winio驱动后就可以直接操作端口了。
载入驱动:InitializeWinIo
卸下驱动:ShutdownWinIo
雪    币: 212
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Morpheus 2006-4-9 19:39
4
0
最初由 dezone 发布
以下是采用WinIo直接向ps2键盘(或鼠标)缓冲区写数据的方法。
winxpsp2下测试通过!

procedure SetKey(SCanCode: byte);
begin
........

非常感谢~试试先!

是一款网络游戏~前面的sendinput操作都能执行(进行游戏的登陆,战斗的开启)~
就是进入游戏战斗界面以后鼠标点击不能(鼠标移动可以)
所以怀疑是在 WM_LBUTTON的地方进行了一下判断.
雪    币: 212
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Morpheus 2006-4-9 19:50
5
0
除了不使用SetPortVal和GetportVal以外!

你程序的主要区别就是增加了扩展键的标识 SetKey($E0)

可能是这个原因造成的我测试的时候不正常!
因为我测试都是使用的 tab return等'扩展键'
雪    币: 179
活跃值: (131)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
WAKU 7 2006-4-9 22:27
6
0
楼主能介绍一下winio.dll吗?
好像不是WINDOWS自带的
雪    币: 212
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Morpheus 2006-4-10 11:51
7
0
是一个个人开发的能直接进行端口读写的库。

网上流传最多的是并口的读写模拟。
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
幻想空间 2006-4-11 15:23
8
0
最初由 dezone 发布
以下是采用WinIo直接向ps2键盘(或鼠标)缓冲区写数据的方法。
winxpsp2下测试通过!

procedure SetKey(SCanCode: byte);
begin
........


我测试在winxp sp2下运行正常,在win2000 sp4下失效,不清楚为什么?
雪    币: 212
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Morpheus 2006-4-12 13:50
9
0
晕~难道是我的测试程序有问题?
我也是XPSP2的~怎么试了好像模拟不了?

我是很简单的VC创建了一个Dialog.

点击"确定" OnOK执行 SetKey() (模拟 Tab键 和 ESC键)

发现1.没变化(我按TAB应该按键选择切换到下一个)
    2.Dialog无反映(ESC应该Dialog退出)
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
幻想空间 2006-4-12 16:03
10
0
经过多台机器测试,此段汇编代码和系统没有关系,只要是NT系统就行,但是和硬件有关系!也就是代码移植性差!

包括直接用winio.dll的函数写端口也一样,有的机器行,有的机器不行!

所谓不行的机器,并不是完全不行,而是向端口写了10个0,可能只显示出来1个0,或者多次运行才显示几个0!就是显示不全!
我怀疑是不是向键盘缓存区输入命令不一样,上面的代码为$D2,能不能解释这个命令是在哪儿查的?搜索了很久没有发现!

我也采用了其他库(如PORTTALK)测试也是这种效果!

对汇编熟悉的能不能说明一下,为什么在有的机器不能执行,或者执行相当的慢?
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
幻想空间 2006-4-12 16:09
11
0
dezone如果看到的话能不能回复一下$D2是怎么来的?谢谢

我对汇编不懂!
雪    币: 212
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Morpheus 2006-4-13 14:28
12
0
最初由 幻想空间 发布
dezone如果看到的话能不能回复一下$D2是怎么来的?谢谢

我对汇编不懂!


D2和是否汇编没关系。

0xD2(写键盘缓冲区),0xD3(写鼠标缓冲区)

----------转至PS/2鼠标键盘协议
雪    币: 212
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Morpheus 2006-4-13 17:24
13
0
终于搞定了

Loop:
in al, 0x64
and al, 10b
jnz Loop
雪    币: 212
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Morpheus 2006-4-14 09:05
14
0
模拟鼠标点击

连续点击效果比较差,延迟很严重。但是移动一下鼠标就能很快响应~不知道什么原因。

鼠标左键点击键值:

SetKey(0x09);//左键按下
SetKey(0x00);
SetKey(0x00);
SetKey(0x08);//左键放开
SetKey(0x00);
SetKey(0x00);
雪    币: 212
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Morpheus 2006-4-14 09:22
15
0
大功告成

SetKey(0x09);//左键按下
SetKey(0x00);
SetKey(0x00);
SetKey(0x00);
SetKey(0x08);//左键放开
SetKey(0x00);
SetKey(0x00);
SetKey(0x00);

原来我的鼠标驱动是要跟3个参数的。。。。
雪    币: 216
活跃值: (42)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dezone 2006-4-14 22:06
16
0
最初由 Morpheus 发布
大功告成


SetKey(0x09);//左键按下
SetKey(0x00);
........

这样直接操作端口最大的问题就是兼容性。
希望楼主能把代码和测试程序公布出来,一来可以让大家帮你测试,二来这是技术性论坛,你在这里学到了东西同时也应该分享自己的知识。
学不定可以拿精华呢
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
幻想空间 2006-4-15 14:56
17
0
最初由 dezone 发布
这样直接操作端口最大的问题就是兼容性。
希望楼主能把代码和测试程序公布出来,一来可以让大家帮你测试,二来这是技术性论坛,你在这里学到了东西同时也应该分享自己的知识。
学不定可以拿精华呢


dezone给出的代码有点问题!

楼主修正后,兼容性大大提高!绝大数的机器上都可以运行

如果直接采用dezone的代码,很容易造成键盘和鼠标失效!

错误在不该是01b而是10b,楼主在上面的贴子中也贴出来了

感谢 dezone和楼主

还有我个人觉得楼主说他的鼠标驱动要跟三个参数,我认为关键可能不是跟几个,而是应该加入一个延时sleep(X),而这个延时的值得看具体的机器,有的机器延时为0也行,有的机器延时为0不会有反应,但加大其值就有效了!
雪    币: 212
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Morpheus 2006-4-15 19:52
18
0
最初由 幻想空间 发布
dezone给出的代码有点问题!

楼主修正后,兼容性大大提高!绝大数的机器上都可以运行

如果直接采用dezone的代码,很容易造成键盘和鼠标失效!
........


应该不是等待的问题!而是2键鼠标和3键鼠标驱动不一致造成的!(4键5键没找到)

2参数是老式的双键鼠标.
3参数则是包含了中间按键(我电脑鼠标使用的就是3键的).

另,此方法对安装的USB鼠标无效.会造成键盘无响应,必须注销重进WINDOWS.

怀疑是PS/2接口冲突.应该是由于PS/2鼠标没有启动的原因
雪    币: 212
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Morpheus 2006-4-15 20:02
19
0
void CWiniotestDlg::SetKey(char SCanCode)
{
    //无论向0x60,还是0x64写东西前都要等状态寄存器OBF变0
        _asm{
    Loop1:
    in al, 0x64
    and al, 10b
    jnz Loop1
    //向$64端口写命令
//        mov al, 0xD2//写键盘输出缓存命令
    mov al, 0xD3//写鼠标输出缓存命令
    out 0x64, al

    //无论向0x60,还是0x64写东西前都要等状态寄存器OBF变0
    Loop2:
    in al, 0x64
    and al, 10b
    jnz Loop2
    //向$60端口写参数
    mov al, SCanCode
    out 0x60, al
        }
}

void CWiniotestDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
        // TODO: Add your message handler code here and/or call default
        CString str;
        str.Format("%d,%d",point.x,point.y);
        AfxMessageBox(str);
        CDialog::OnLButtonDown(nFlags, point);
}

void CWiniotestDlg::OnOK()
{
        // TODO: Add extra validation here
        SetKey(0x09);
        SetKey(0x00);
        SetKey(0x00);
        SetKey(0x00);
        SetKey(0x08);
        SetKey(0x00);
        SetKey(0x00);
        SetKey(0x00);
}

//////////////////////////////////////////////////////////////////

很粗糙的一个测试程序.实现的是一次鼠标左键的点击.
实际运用是通过敲击回车点击"确定"按钮查看模拟情况的

如果需要模拟键盘,则将 0xD3改为0xD2.

我测试时候模拟键盘使用 SetKey(0x01);SetKey(0x81);(模拟ESC点击,成功关闭DLG)
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
magicker 2006-5-12 22:49
20
0
Morpheus,你好,请问该怎么模拟鼠标移动呢?
雪    币: 212
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Morpheus 2006-5-15 11:50
21
0
最初由 magicker 发布
Morpheus,你好,请问该怎么模拟鼠标移动呢?


BOOL SetCursorPos(
  int X,  // horizontal position
  int Y   // vertical position
);

直接鼠标定位
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
magicker 2006-5-17 14:51
22
0
晕死,我说的是如何用WINIO来模拟鼠标移动
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
magicker 2006-5-17 15:07
23
0
还有个我想模拟 End 键,但是用
SetKey(MapVirtualKey(ord(VK_END), 0));
这个输出是却是1,必须要把小键盘的灯关了,才能输出正确。
有没有办法不关小键盘灯就可以输出正确?
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wancb 2006-7-3 00:12
24
0
用WINIO成功产生硬件按键消息,但是开了盛大冒险岛后在运行程序,就出错了
说没有权限,privileged instruction!
不管在哪个应用程序窗口,都说是没有权限。

同样,对国际服冒险岛(也有NP),就成功发送硬件按键消息!

估计是盛大的maplestory.exe运行后,将系统里面其他的用户进程权限降低!

请高手指点!

对于这样的情况,应该怎么解决!

附:
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wancb 2006-7-3 00:13
25
0
程序代码如下:
发送硬件按键消息:
   numlock

procedure TForm1.Button1Click(Sender: TObject);
begin

//具体模拟一个按键的操作可以象下面这样来写.
//  btScancode:=65;
//  btScancode:= MapVirtualKey(VK_F1, 0); //OK
  btScancode:= MapVirtualKey(VK_NUMLOCK, 0);
  Delay(2000);
  SetPortVal($64,$D2,1);
  Delay(1000);
  SetPortVal($60,btScancode,1); //btScancode 是键盘键,笔记本和台试机可能不太一样
  Delay(1000);
  SetPortVal($64,$D2,1);
  Delay(1000);
  SetPortVal($60,btScancode or $80,1);//一次按键完成.

end;
游客
登录 | 注册 方可回帖
返回