随笔-键盘驱动级别模拟

前言

上个月央行征信改版导致登陆需要安装密码控件,这一改可把我折腾坏了,还是第一次处理控件登陆的问题,临时学习了很多,踩了很多坑,目前终于稳定能使用了,这里大概记一下经历

ActiveX控件

我等日常最常用都接触过的浏览器控件就是Flash,全名是Adobe Flash Player,我记得这个空间的身板还不小,大概二百兆,而且不同浏览器还要下载不同的版本,之前还曝光说他有不少安全漏洞,再加上总是不定期升级,可以说是用户体验极差了,感觉Flash控件之后一定会慢慢被H5取代

其实ActiveX控件这东西人如其名,就类似windows桌面程序中的各种控件,微软之前把他设计为可以嵌入在浏览器中,并给这个方向的控件起了个名字OCX 对象类别扩充组件(Object Linking and Embedding (OLE) Control Extension),后来随着网络越来越发达,逐渐发展为ActiveX,关于这个过程可以参考OLE、OCX和ActiveX控件之间的比较 - OlawonZhu - 博客园

从ActiveX的设计初衷来看,还是很有想法的,把浏览器页面当做载体,然后在页面内部启用控件,相当于浏览器里面嵌入一个自定义的程序,而其他网站也可以引用这个控件,不止实现了复用,更重要的是把丰富浏览器行为这个权利分配给了所有开发者,是一个不错的方向

然而时代日新月异,面对新的浏览器甚至新的操作系统以及移动端的兴起,更重要的是Web的性质变化-Web必须承载更多的使命。ActiveX控件的弊端慢慢变得越来越尖锐,尖锐的无法接受,我觉得最大的弊端有两点:1无法跨平台
2必须安装后才可以使用

ActiveX技术已经变成了时代的眼泪,现在很多控件也就只有IE浏览器还可以支持使用。央行征信这次改为控件输入密码也是够狠的,意味着以后查征信报告必须要在windows平台使用IE浏览器才可以

JS分析

以下是央行登陆页面部分JS代码

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
<script type="text/javascript">
var pgeditor = new $.pge({
pgePath : "http://file.zhongdengwang.com/ocx/",//控件下载目录,可以指定绝对路径,如"http://www.baidu.com/download/"
pgeId : "pass",//控件id
pgeEdittype : 0,//控件显示类型,0(星号),1(明文)
pgeEreg1 : "[\\s\\S]*",//输入过程中字符类型限制,如"[0-9]*"表示只能输入数字
pgeEreg2 : "[\\s\\S]{6,12}",//输入完毕后字符类型判断条件,与pgeditor.pwdValid()方法对应
pgeMaxlength : 20,//允许最大输入长度
pgeTabindex : 2,//tab键顺序
//pgeCert : "3081890281810092D9D8D04FB5F8EF9B8374F21690FD46FDBF49B40EECCDF416B4E2AC2044B0CFE3BD67EB4416B26FD18C9D3833770A526FD1AB66A83ED969AF74238D6C900403FC498154EC74EAF420E7338675CAD7F19332B4A56BE4FF946B662A3C2D217EFBE4DC646FB742B8C62BFE8E25FD5DC59E7540695FA8B9CD5BFD9F92DFAD009D230203010001",
pgeCert:"3082010A0282010100A5875466E166609505D3BB4C51B03F8722F59FA317A2CDC94D83F85335F01EF986DA43C0FC02FDB056DE0DCD24D70F7755CF4D130D92B0AC347CD3AE69434E74212B57819867BC3AF6CFB5D343544082AA72A4751843305EF83417635D93CDE2B5DF8572FADB1CB56491D41368020AE787B2F6DE1D42193BF57B041198AF54A3878941F68ACE018634663D6E211D587BC373954A8C00425838493CB828E2493DF3DB2653C8E46399F88AB453D217A7FFD628A3F12BD0C4BAB9555C095C1013C60F2ADF1DCEF1845D764EFD2A25084A27B3FEC5B8121B08F8F94F4F14146F43BC2AF93C406EDE8F1DAE717FC512FF4B08E0D05A7223A5F8548FC14A6D9CF6E4030203010001",
pgeClass : "ocx_style",//控件css样式
pgeInstallClass : "ocx_style",//针对安装或升级的css样式
pgeOnkeydown :"FormSubmit()",//回车键响应函数,需焦点在控件中才能响应
//tabCallback : "input2",//火狐tab键回调函数,设置要跳转到的对象ID
pgeOnfocus:"pgeFocus()",//监控光标切入密码控件框
pgeOnblur:"pgeBlur()",//监控光标切出密码控件框
//windows10 edge&Chrome42+相关
pgeWindowID:"password"+new Date().getTime()+1,
pgeRZRandNum:"24116953564831466890207747235682",
pgeRZDataB:"zQhsRAHO06GuBFEIdZVOZw7Ro3biBdTHnARJruWMYi4="
});
window.pgeCtrl = pgeditor;
var i = 0;
//密码控件获得焦点时,提示一下
function pgeFocus(){
$("#tishi").css('display','block');
$("#passwordInfo").css('display','none');
}
//密码控件失去焦点时获得密码强度,并展示出来
function pgeBlur(){
$("#tishi").css('display','none');
$("#passwordInfo").css('display','block');
checkPassword();
}
window.onload = function(){
$("#login").focus();
pgeditor.pgInitialize();
$("lic").html(pgeditor.setLicense());
}

//登录集成演示页面提交表单的方法
function FormSubmit() {
$.ajax({
cache:false,
type:"post",
async:false,
url:basepath+"userReg.do?method=getSrandNum&num="+Math.random(),
dataType:"text",
success:function(result){
//alert("*****"+result);
pgeditor.pwdSetSk(result);//给控件设置随机因子
}
});
var pwdResult = pgeditor.pwdResultRSA();//获取密码AES+RSA密文
var machineNetwork = pgeditor.machineNetwork();//获取网卡信息密文
var machineDisk = pgeditor.machineDisk();//获取硬盘信息密文
var machineCPU = pgeditor.machineCPU();//获取CPU信息密文
$("#password").val(pwdResult);//将密码密文赋值给表单
$("#pass").val(pwdResult);
}
</script>

从它页面JS可以看出来应该是通过先填充几个ID之类的字段获取一个随机因子,给控件初始化用掉随机因子,然后几个字段和密码组合在调用控件的加密方法,赋值给密码input标签,最后提交表单

键盘驱动级别模拟

在ActiveX控件中使用C# 的SendInput或者是调win32.dll的 keybd_event 都是无法输入的,因为ActiveX控件本质就是windows小程序,他的权限其实是非常大的,这里推测是他在底层挂了键盘钩子,然后把消息中断了,使按键无法被上层其他程序捕获,猜测依据就是他在web的JS文件中的密码窗体获取焦点和失去焦点事件中操作了一个Interval调用了一个控件的intervlOut方法

关于windows键盘消息队列相关内容请看引用,这里不在赘述,也不打算继续深入

目前网络上能找的驱动级别键盘模拟dll有三个,WinIO、WinRang0以及DD

  • WinIO及WinRang0是国外很早流传的两个dll,年代大概在2006年左右,网上相关资料已经非常少了,使用条件极其苛刻,需要在windows测试模式下安装一个驱动证书,依赖 i8042prt.sys 驱动-PS/2键盘驱动,而且这个驱动还是即插即启动的那种,意味着要想使用必须连着PS/2键盘
  • DD是国人开发的一个dll,下载包内甚至包含了C#,Java,Python等语言使用Demo,内部实现了自己的驱动数字签名,可以直接加载使用,但是缺点是免费版会篡改IE主页,加载使用时必须要联网初始化,安全性不一定多可靠

因为要在服务器发布,可以只能使用后者了,但是键盘驱动模拟有个很有意思的坑,就是远程连接上去发布退出时无效的-键盘模拟输入无效,但是通过服务器控制台登陆再退出就可以正常使用,这点我推测和连接原理有关系,可能不同的连接后再退出后是服务器保持了不同的状态,这点确实很坑

后记

  • 当程序实现后发现也没有多少代码,主要是寻找可靠地解决方案,不停地查资料比较费时间和脑力,这种问题没有相关经验真的是不到最后一刻稳定运行都不能确定能否成功解决
  • 感觉自己解决问题的途径太少,以后还需要积累

引用

驱动级键盘模拟(C#)(高手请飘过) - 程晨 - 博客园
Windows键盘驱动结构与消息机制