Windows游戏自动化-02Windows虚拟驱动

为什么要使用虚拟驱动?

1、虚拟一个或多个人机交互设备,如键盘、鼠标、摇杆等
2、通过尝试,发现使用python自带的win32接口、UIA接口,在游戏客户端中进行操作,会完全没有反应。这和游戏客户端是实现、安全等方面有关。

虚拟驱动运行原理、流程

项目分析

为了在python中方便使用各种操作接口,需要将实现的虚拟驱动的各种操作进行封装,实现python层的接口(leftclick、input、doubleclick等),供脚本使用

驱动层关键函数

BOOL vmulti_connect(pvmulti_client vmulti)

连接

void vmulti_disconnect(pvmulti_client vmulti)

断开连接

BOOL vmulti_update_mouse(pvmulti_client vmulti, BYTE button, USHORT x, USHORT y, BYTE wheelPosition)

更新鼠标

BOOL vmulti_update_keyboard(pvmulti_client vmulti, BYTE shiftKeyFlags, BYTE keyCodes[KBD_KEY_CODES])

更新键盘

编译、安装驱动

1.编译 - 安装WDK

点击链接下载Windows Driver Kit,下载、解压、安装
默认装在C盘 C:/WinDDK/7600.16385.1
安装Windows Kit

2.设置电脑环境

只有在测试模式虚拟驱动才会显示成功安装,所以这一步是必须的。
(1)修改为test环境
打开cmd,运行命令 bcdedit /set testsigning on:

1
2
C:\Users\***> bcdedit /set testsigning on
操作已完成。

输出操作已完成 说明成功
(2)重启电脑(重要)
一定要重启电脑测试模式才会生效
电脑右下角会出现:

3.编译、安装驱动

(1) build

打开X64 free build environment(或者X64 checked build environment)命令行工具:
进入到vmulti-master项目根目录
运行命令 build -wgc 进行编译

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
> build -wgc
path contains nonexistant %java_home\jre\bin, removing
BUILD: Compile and Link for AMD64
BUILD: Loading c:\winddk\7600.16385.1\build.dat...
BUILD: Computing Include file dependencies:
BUILD: Start time: Tue Jan 22 10:05:16 2019
BUILD: Examining d:\jynnezhang\desktop\uieasytest\virtualkeyboard\vmulti-master\vmulti-master directory tree for files to compile.
BUILD: Saving c:\winddk\7600.16385.1\build.dat...
1>BUILD: Building generated files in d:\jynnezhang\desktop\uieasytest\virtualkeyboard\vmulti-master\vmulti-master\sys directory
Configuring OACR for 'root:amd64chk' - <OACR on>
BUILD: Examining d:\jynnezhang\desktop\uieasytest\virtualkeyboard\vmulti-master\vmulti-master directory tree for files to compile. (2nd Pass)
d:\jynnezhang\desktop\uieasytest\virtualkeyboard\vmulti-master\vmulti-master\client - 1 source files (627 lines)
d:\jynnezhang\desktop\uieasytest\virtualkeyboard\vmulti-master\vmulti-master\test - 2 source files (424 lines)
BUILD: Saving c:\winddk\7600.16385.1\build.dat...
Total of 3 source files (1,051 lines) to compile in 2 directories

1>BUILD: Compiling (NoSync) d:\jynnezhang\desktop\uieasytest\virtualkeyboard\vmulti-master\vmulti-master\client directory
2>BUILD: Compiling (NoSync) d:\jynnezhang\desktop\uieasytest\virtualkeyboard\vmulti-master\vmulti-master\test directory
1>Compiling - client\client.c
2>Compiling - test\testvmulti.c
2>warnings in directory d:\jynnezhang\desktop\uieasytest\virtualkeyboard\vmulti-master\vmulti-master\test
2>d:\jynnezhang\desktop\uieasytest\virtualkeyboard\vmulti-master\vmulti-master\test\testvmulti.c(135) : warning C4242: 'function' : conversion from 'int' to 'BYTE', possible loss of data
2>d:\jynnezhang\desktop\uieasytest\virtualkeyboard\vmulti-master\vmulti-master\test\testvmulti.c(135) : warning C4242: 'function' : conversion from 'int' to 'USHORT', possible loss of data
2>d:\jynnezhang\desktop\uieasytest\virtualkeyboard\vmulti-master\vmulti-master\test\testvmulti.c(135) : warning C4242: 'function' : conversion from 'int' to 'USHORT', possible loss of data
2>d:\jynnezhang\desktop\uieasytest\virtualkeyboard\vmulti-master\vmulti-master\test\testvmulti.c(135) : warning C4242: 'function' : conversion from 'int' to 'BYTE', possible loss of data
2>d:\jynnezhang\desktop\uieasytest\virtualkeyboard\vmulti-master\vmulti-master\test\testvmulti.c(168) : warning C4242: 'function' : conversion from 'int' to 'USHORT', possible loss of data
2>d:\jynnezhang\desktop\uieasytest\virtualkeyboard\vmulti-master\vmulti-master\test\testvmulti.c(168) : warning C4242: 'function' : conversion from 'int' to 'USHORT', possible loss of data
2>d:\jynnezhang\desktop\uieasytest\virtualkeyboard\vmulti-master\vmulti-master\test\testvmulti.c(172) : warning C4242: 'function' : conversion from 'int' to 'USHORT', possible loss of data
2>d:\jynnezhang\desktop\uieasytest\virtualkeyboard\vmulti-master\vmulti-master\test\testvmulti.c(172) : warning C4242: 'function' : conversion from 'int' to 'USHORT', possible loss of data
2>Building Library - test\test\objchk_win7_amd64\amd64\testvmulti.lib
1>Building Library - client\client\objchk_win7_amd64\amd64\vmulticlient.lib
1>BUILD: Compiling and Linking d:\jynnezhang\desktop\uieasytest\virtualkeyboard\vmulti-master\vmulti-master\hidmapper directory
2>BUILD: Compiling and Linking d:\jynnezhang\desktop\uieasytest\virtualkeyboard\vmulti-master\vmulti-master\sys directory
3>BUILD: Linking for d:\jynnezhang\desktop\uieasytest\virtualkeyboard\vmulti-master\vmulti-master\test directory
2>Compiling resources - sys\vmulti.rc
1>Compiling resources - hidmapper\hidkmdf.rc
3>Compiling resources - test\testvmulti.rc
3>Linking Executable - test\test\objchk_win7_amd64\amd64\testvmulti.dll
1>Compiling - hidmapper\hidkmdf.c
2>Compiling - sys\vmulti.c
1>Linking Executable - hidmapper\hidmapper\objchk_win7_amd64\amd64\hidkmdf.sys
2>Linking Executable - sys\sys\objchk_win7_amd64\amd64\vmulti.sys
BUILD: Finish time: Tue Jan 22 10:05:18 2019
BUILD: Done

15 files compiled - 9 Warnings
2 libraries built
3 executables built

生成的vmulti.infvmulti.sys文件在sys\objchk_win7_amd64\amd64(或sys\objfre_win7_amd64\amd64)文件夹中(与之前选择的free、checked版本命令行工具有关)
hidmapper\objchk_win7_amd64\amd64(或hidmapper\objfre_win7_amd64\amd64)文件夹中生成了hidkmdf.sys文件
供python调用的testvmulti.dll文件在 test\objchk_win7_amd64\amd64(或test\objfre_win7_amd64\amd64)文件夹中

(2) 验证inf文件

注意:在根目录的bin文件夹下,有很多的exe文件,都是后续会用到的。这些文件都是从WDK中拷贝过来的,方便使用。
使用命令infverif.exe /v /u vmulti.inf检查inf文件的有效性:

1
2
3
4
5
6
7
8
9
10
11
12
13
> infverif.exe /v /u vmulti.inf
Running in Verbose
Running Universal INF check
Running in Console output mode

Checking D:\JynneZhang\Desktop\UIEasyTest\VirtualKeyboard\vmulti-master(1)\vmulti-master\bin\vmulti.inf
ERROR(1209) in D:\JynneZhang\Desktop\UIEasyTest\VirtualKeyboard\vmulti-master(1)\vmulti-master\bin\vmulti.inf, line 9: Section [sourcedisksfiles] is defined multiple times.
ERROR(1209) in D:\JynneZhang\Desktop\UIEasyTest\VirtualKeyboard\vmulti-master(1)\vmulti-master\bin\vmulti.inf, line 16: Section [destinationdirs] is defined multiple times.
ERROR(1209) in D:\JynneZhang\Desktop\UIEasyTest\VirtualKeyboard\vmulti-master(1)\vmulti-master\bin\vmulti.inf, line 46: Section [copyfunctiondriver] is defined multiple times.
vmulti.inf is NOT VALID: 0000065B


Checked 1 INF(s) in 0 m 0 s 12 ms

这里提示的的是inf文件中存在重复定义的地方。
解决这个问题需要奥inf文件中,将多个[sourcedisksfiles]等修改至一个
【这里不修改也不影响后续的使用】

(3) Inf2Cat,生成适用于指定 Windows 版本的未签名的目录文件

单独这个exe运行会报错,因为它依赖了其他的库和文件:

再次运行Inf2Cat.exe /driver:. /os:7_X64/driver:后是inf文件的路径,./代表当前目录:

1
2
3
4
5
6
7
8
9
10
11
12
> Inf2Cat.exe /driver:./ /os:7_X64
........................................
Signability test complete.

Errors:
None

Warnings:
None

Catalog generation complete.
D:\JynneZhang\Desktop\UIEasyTest\VirtualKeyboard\vmulti-master\vmulti-master\bin\kmdfsamples.cat

bin目录下生成kmdfsamples.cat文件

(4) 创建证书

参数:-r 创建自签名证书-ss 指定证书存储位置CN=公司名称Test20190122.cer是指定生成的证书的文件名:

1
2
>makecert -r -pe -ss PrivateCertStore -n "CN=Contoso.com(Test)" Test20190122.cer
Succeeded

MakeCert 命令会生成一个名为“Contoso.com(Test)”的自签名测试证书,将测试证书安装在 PrivateCertStore 证书存储中并创建包含测试证书副本的 Test20190122.cer 文件

(5) 注册测试数字证书:将测试证书添加到证书存储区

1
2
>CertMgr.exe /add Test20190122.cer /s /r localMachine root
CertMgr Succeeded

(6) 签名: cat、sys文件

kmdfsamples.cat、vmulti.sys、hidkmdf.sys 三个文件

1
2
3
4
5
6
7
8
9
10
11
12
13
>SignTool.exe sign /v /s PrivateCertStore /n Contoso.com(Test) /t http://timestamp.verisign.com/scripts/timestamp.dll kmdfsamples.cat
The following certificate was selected:
Issued to: Contoso.com(Test)
Issued by: Contoso.com(Test)
Expires: Sun Jan 01 07:59:59 2040
SHA1 hash: E1DA79FA454029FA1758EEE23D26BB14980538C6

Done Adding Additional Store
Successfully signed and timestamped: kmdfsamples.cat

Number of files successfully Signed: 1
Number of warnings: 0
Number of errors: 0

1
2
3
4
5
6
7
8
9
10
11
12
13
>SignTool.exe sign /v /s PrivateCertStore /n Contoso.com(Test) /t http://timestamp.verisign.com/scripts/timestamp.dll vmulti.sys
The following certificate was selected:
Issued to: Contoso.com(Test)
Issued by: Contoso.com(Test)
Expires: Sun Jan 01 07:59:59 2040
SHA1 hash: E1DA79FA454029FA1758EEE23D26BB14980538C6

Done Adding Additional Store
Successfully signed and timestamped: vmulti.sys

Number of files successfully Signed: 1
Number of warnings: 0
Number of errors: 0
1
2
3
4
5
6
7
8
9
10
11
12
13
>SignTool.exe sign /v /s PrivateCertStore /n Contoso.com(Test) /t http://timestamp.verisign.com/scripts/timestamp.dll hidkmdf.sys
The following certificate was selected:
Issued to: Contoso.com(Test)
Issued by: Contoso.com(Test)
Expires: Sun Jan 01 07:59:59 2040
SHA1 hash: E1DA79FA454029FA1758EEE23D26BB14980538C6

Done Adding Additional Store
Successfully signed and timestamped: hidkmdf.sys

Number of files successfully Signed: 1
Number of warnings: 0
Number of errors: 0

(7) 安装驱动

1
>devcon install vmulti.inf djpnewton\vmulti

打开设备管理器

已经新增了刚刚安装的驱动设备
注意:如果在步骤2没有成功修改系统环境为测试模式,则会出现:

驱动安装失败

Attention:
加入log模块:
log.h文件放在了inc文件夹中
client/source文件中加入 log.c文件
使用:
Log.Write(DEBUG, “%s”, “123”) //“%s” 不可缺省
然后编译

驱动dll封装Python接口

在编译完驱动后,一方面得到了安装驱动的文件,另一方面得到了调用驱动的dll文件: testvmulti.dll,文件在 test\objchk_win7_amd64\amd64(或test\objfre_win7_amd64\amd64)文件夹中

load dll库

windll.LoadLibrary(dll_file_path)

dll中的操作接口

Hid_keyboard_send_requests(BYTE resport_[])
发送键盘操作

Hid_mouse_send_requests(MouseResports resport_)
发送鼠标操作

python层接口

_add_keycode_to_report(self, keycode)

拼接发送的数据

press_(self, keycodes)

release_(self, keycodes)

inputKeys(self, key=[], str=””)

组合键

inputString(self, str=””)

字符串

click(self, pt = (0, 0))

rightclick(self, pt=(0, 0))

doubleclick(self, pt=(0, 0))

Keycode:
https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=53
根据USB规定的HID Table给按键编码

参考:
[1] http://catx.me/2014/03/11/build-and-use-virtual-hid-driver/

------------- The End -------------