// WIP,光大网银很多javascript代码貌似在ff下就有问题,这里只是说ActiveX的问题
光大网银用了ActiveX,于是看上去很难在别的系统/浏览器下用。
但其实就结果来说,那个ActiveX控件没啥用……
页面上有三个<object>,其中一个啥sign貌似啥都没干,另外俩负责加密密码/提交。
提交登录表单的时候,多数域都是空的。根据观察,控件就填了一个域:Password
为了观察那个控件都调了啥加密函数,找了个很好用的工具,叫WinAPIOverride。粗粗一看调了若干Crypt* API,于是缩小范围到各个Crypt*函数上。分析记录在 http://wiki.henryhu.net/wiki/CEB。
最后发现这个控件很匮乏,在用公钥加密了密码之后(公钥在JS里……),它蛋疼的生成了一个随机数加密了一下,之后有解密了一把,最后完全没用…… 而那个Password域,内容其实就是密码加密结果反过来之后base64一把……
分析的时候有个地方很奇怪。看上去CryptEncrypt()的输入每次都一样,但是结果每次不同…… 后来自己写了个程序试试发现的确每次不同…… 再次看见网上说,加密时候会随机pad到block长度,才理解……
接下来嘛,写个Greasemonkey脚本来帮助登录。第一步就是把那几个控件替换成我们的对象。替换完之后,可以登录过第一步了,之后手机短信验证还是不成。看console里有个错说HiddenSubmitArea不存在,于是插入一个进去…… 这货找遍各个地方都没找到,貌似也没啥用。
这样就可以过短信验证了…… 进去之后貌似还是有一些js错误,慢慢来…… 反正可以登录了。
作为库调用跟踪工具,WinAPIOverride还是挺好用的,功能上类似于ltrace,还有调试器的一部分功能,可以在库函数调用前后断下来,观察内存/寄存器等。IEinspector作为分析IE数据包的工具也不错,看上去比HttpFox功能更多…… 只是要收钱。
Greasemonkey代码:
// ==UserScript== // @name cebbank // @namespace net.henryhu // @description ceb bank // @include https://www.cebbank.com/per/perlogin* // @include https://www.cebbank.com/per/prePerlogin.do?_locale=zh_CN // @version 1 // @grant none // ==/UserScript== function reset() { console.log('reset'); } function publicKeyBlob(blob) { console.log('blob: ' + blob); } function commit(field) { console.log("commit: " + field); } function submit(formName) { console.log('submit: ' + formName); form = document.forms[formName]; form.Password.value = ''; form.submit(); } function HiddenSubmitArea(foo) { console.log('HiddenSubmitArea: ' + foo); } oldpc = document.getElementById('powercommit'); newpc = document.createElement('div'); newpc.id = 'powercommit'; newpc.reset = reset; newpc.submit = submit; oldpp = document.getElementById('powerpassword'); newpp = document.createElement('input'); newpp.id = 'powerpassword'; newpp.type = 'password'; newpp.publicKeyBlob = publicKeyBlob; newpp.commit = commit; counter = document.createElement('input'); counter.value = 1; counter.id = 'counter'; document.body.appendChild(counter); if (oldpc) { oldpc.parentNode.replaceChild(newpc, oldpc); console.log("replaced pc"); } if (oldpp) { oldpp.parentNode.replaceChild(newpp, oldpp); console.log("replaced pp"); } window.HiddenSubmitArea = HiddenSubmitArea; |