ua.js文件load事件自定义处理函数功能解析
actionlog_js_ua.js混淆编程形式与执行主流程
ua.js中mousedown和mousemove事件自定义函数功能解析
ua.js中JSocket.getlso和JSocket.setlso代码分析
ua.js中arguments.callee.caller的应用
经过前两篇文章的分析可知,ua.js首先会检测DOM加载完成并执行指定函数,该功能靠函数jwhs实现,不依赖Jquery。那ua.js文件在DOM加载完成后要做的第一件事是什么呢?这就是本文讨论的主题:执行load事件自定义处理函数。
为各种事件绑定自定义处理函数
在actionlog_js_ua.js混淆编程形式与执行主流程中,我给出了hp6函数的反混淆代码,代码表明函数t6k负责为鼠标键盘等各种事件分配自定义处理函数,我们先来看函数t6k的反混淆代码:
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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
t6k = function (vq4) { var zp6 = new window["Object"]; zp6["mousemove"] = qe; zp6["keydown"] = u4; zp6["mousedown"] = bc; zp6["focus"] = yl; zp6["blur"] = yl; zp6["load"] = n8x; zp6["beforeunload"] = cr64; zp6["unload"] = cr64; var vo = vq4["document"]; var lzle = function (e, bgo) { if (e == 'focus') { if(bgo["attachEvent"]){ bgo["attachEvent"]("onfocusin", zp6[e], false); } else if(bgo["addEventListener"]){ bgo["addEventListener"](e, zp6[e], true); } } else if(e == "blur"){ if(bgo["attachEvent"]){ var qn = 0; while(!qn){ if(qn + 1){ bgo["attachEvent"]("onfocusout", zp6[e], false); qn = qn + 1; continue; } xkf = target.xclient; } } else if(bgo["addEventListener"]){ bgo["addEventListener"](e, zp6[e], true); } } else{ if(bgo["attachEvent"]){ var gb9 = 2; if(gb9){ bgo["attachEvent"]("on" + e, zp6[e], false); }else{ oi.nm = "uxa"; } } else if(bgo["addEventListener"]){ bgo["addEventListener"](e, zp6[e], false); } } }; jwhs["add"](n8x);//设置DOM加载完成后执行函数n8x,函数n8x是load事件处理函数 if(UA_Opt["EnableMCLog"]){ lzle("mousedown", vo); } if (UA_Opt["EnableKSLog"]) { lzle("keydown", vo); } if (UA_Opt["EnableMPLog"]) { lzle("mousemove", vo); } if (UA_Opt["FocusInfo"]) { lzle("focus", vo); lzle("blur", vo); } if ((UA_Opt["SendMethod"] & 2) > 0) { if(typeof vq4["onbeforeunload"] != "undefined"){ lzle("beforeunload", vq4); } if(typeof vq4["onunload"] != "undefined"){ lzle("unload", vq4); } } };////t6k |
关于鼠标键盘等事件绑定自定义处理函数后续会有专门的文章来分析。今天我们先来关注代码 jwhs[“add”](n8x),结合jwhs函数的反混淆代码可知该语句的意义为:DOM加载完成后,将首先执行函数n8x,该函数就是ua.js文件中用于处理load事件的自定义函数。
load事件自定义处理函数功能解析
函数n8x神通广大,它会获取当前用户所使用的操作系统,屏幕分辨率,浏览器名称与主版本号,浏览器窗口尺寸,当前用户的浏览器是否开启调试功能,当前网页URL与refer等等信息,这些信息均属于固定信息,当用户首次加载或访问过程中刷新时这些信息各位参与一次更新UA。下图是按照代码执行顺序整理的n8x的功能与各功能的执行条件。
下面根据函数n8x的执行顺序来逐一说明ua.js都获取了哪些信息用于生成UA,其中比较常见的信息获取方式这里就不详述了,部分信息的获取方式后续将分篇讲解。在看下面的分析时,大家会发现函数wql和vq4频繁且成对出现,wql和vq4这两个函数在生成UA中扮演着非常重要的角色,后续会分别讲述这两个函数的原理,这里大家先暂时认为它们是用于生成UA的工具就好。另外大家会发现isvz的属性值会频繁用作函数的执行条件,也就是UA_Opt的设定值决定着大量函数的走向。
1. 初始化各种变量,这里不逐一详述,着重说明一下ID为UA_InputId的元素的初始化
ID为UA_InputId的元素的初始化在函数fj4中完成,下面截取并反混淆和简化相关代码进行分析。若满足条件,将会判断当前网页中是否包含ID为UA_InputId的元素,若包含,那么将其值清空;若不包含,则创建该元素,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
if((ivsz["SendMethod"] & 1) > 0) { var v3 =window ["document"]["createElement"]("input"); v3["type"] = "hidden"; v3["name"] = "ua"; v3["id"] = "UA_InputId"; var ekw = document.getElementById("FormId"); ekw["insertBefore"](v3,ekw["firstChild"]); } if(((ivsz["SendMethod"] & 8) > 0) &&(ivsz["LogVal"])) { ivsz["LogVal"]=""; window["eval"](ivsz[LogVal]="";) } |
2. 定时调用页面访问信息的统计函数
页面访问信息统计函数对于我而言是一个新鲜事物,我必须单独用一篇文章来记录。所以这里暂时只给出该功能在n8x中的调用形式,然后要挖一个坑,等到后面来填补。这里可以看到页面访问信息统计函数的调用间隔时间也有isvz的设定值来决定,这个函数不参与更新UA,但是会搜集相关信息回传给服务器。
1 2 3 4 |
if((ivsz["SendMethod"] & 2) > 0) { setInterval(dzfg,ivsz["SendTimer"]); } |
3. 判断当前用户浏览器是否开启调试功能并用此信息更新UA
这段代码其实也是ua.js混淆编程的一个代表,for循环中的每一个if分支都会被执行,只是它们的次序并不是一眼就能判断的。其中函数mb的参数两个参数意义特殊,xjct记录着用户的浏览器是否开启调试功能,而rn5t则指向ua.js文件中最外层的匿名函数。函数mb将这两个信息用来更新UA,这也是整个文件中第一个用于更新UA的信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
var piq = (0x3e8 * 0144 & 79);//var piq = 0 // var oq = 0; oq <= 7; piq = ++oq + oq++ + oq) { for (var oq = (0x3e8 * 0252 & 77); oq <= (0x409 * 0457 & 87); piq = ++oq + oq++ + oq) { //第一次循环结果:输入piq=0, oq=0; 输出piq=4, oq=2; //第二次循环结果:输入piq=4, oq=2; 输出piq=10, oq=4; //第三次循环结果:输入piq=10, oq=4;输出piq=19, oq=7; //第四次循环结果:输入piq=19, oq=7;输出piq=25, oq=9; if (oq == piq) {//第一次循环成立 wql(); continue; } if (2 * oq == piq - 5) {//第四次循环成立 var o7w = 1; break; } if (2 * oq == piq - 2) {//第三次循环成立 wql("20"); oq++; } if (3 * oq == piq + 2) {//第二次循环成立 mb(xjct, rn5t); } } |
4. 记录ua.js文件调用的时间并用于更新UA
1 2 |
vq4([1, ghj]);//ghj:ua.js文件被调用的时间 wql("1"); |
5. 获取当前用户使用浏览器名称,浏览器版本号,操作系统名称等参数更新UA
函数ihd获取浏览器和操作系统信息,并用于更新UA,后续会专门有文章详述其获取方法。
1 2 3 4 5 |
if(ivsz["BrowserInfo"]) { ihd(); } wql("2"); |
6. 用TokenStr来更新UA
有抓取淘宝登录数据的同学对“TokenStr”应该比较眼熟,这里isvz[“TokenStr“]是从变量UA_Opt中获取得到的,ua.js并没有相关代码生成“TokenStr“。
1 2 3 4 5 |
if(((ivsz["SendMethod"] & 1) > 0) || ((ivsz["SendMethod"] & 8) > 0)) { vq4([12, ivsz['TokenStr']]); } wql(12); |
7. 与鼠标,键盘处理函数相关的四个随机数更新UA
这是一个大坑,因为这里我暂时没看懂,所有这个坑我很有可能没有能力填起来,但是我后续会有文章把该函数的反混淆及简化形式列出,等待高人来破解。
1 2 |
nx6j();// vq4(19,[]), []中为四个随机数组成的数组 wql(19); |
8. GetMacAddr和ProxyInfo
从执行条件来看,ib9i()函数与当前用户电脑的Mac地址有关,而函数vfp4()应该与ProxInfo有关。但是实际上函数ib9i()并没有获取Mac地址的动作,vfp4()也没有获取ProxInfo的动作,它们最终都只是用了空字符来更新UA。
1 2 3 4 5 6 7 8 9 10 11 |
if(ivsz["GetMacAddr"]) { ib9i(); ////////vq4([8, ""]); } wql(8); if(ivsz["ProxyInfo"]) { vfp4(); ////////vq4([9, ""]); } wql(9); |
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 |
ib9i = function () { var lw = (0x3e8 % 0360 & 81);//0 for (var s2t = ((0x3f3 | 0457) % 93); s2t <= (0x435 * 01413 & 55); lw = ++s2t + s2t++ + s2t) { if (s2t == lw) { var rkht = irt;//irt是一个全局变量,是一个空字符串 continue; } if (2 * s2t == lw - (0x3f3 * 01375 & 77)) { b0z([8, rkht]);//vq4([8, ""]); break; } if (2 * s2t == lw - 2) { var b0z = vq4; s2t++; } if (((0x3f3 | 0574) % 85) * s2t == lw + 2) { // arguments[callee] arguments[callee] su(wjt(ovh("" + arguments[jj('leeWllacm', 4, 1)])), "" + arguments[m2('meevllacf', 4, 1)]); } } }; vfp4 = function () { var l6z = ""; var ulqc = [9, l6z]; // callee callee su(wjt(ovh("" + arguments[k1('peenllacV', 4, 1)])), "" + arguments[eb('veeVllacz', 4, 1)]); vq4(ulqc); }; |
9. 获取当前页面的URL地址和referer
如下代码以及注释所示,iqp函数获取当前页面的URL地址与referer后,将其作为Vq4函数的参数传入并调用,用于更新UA。
1 2 3 4 5 6 |
if(ivsz["Location"]) { /// vq4([11, [window.encodeURI(window.location.toString()), window.encodeURI(window.document.referer.toString())]]; iqp(); /// } wql("11"); |
10. 获取屏幕尺寸信息,浏览器窗口信息
1 2 3 4 5 6 |
if(ivsz["ScreenInfo"]) { //vq4[3, [screenTop, screenLeft, document.body.clientWidth,document.body.clientHeight, screen.width, screen.height, screen.availWidth, screen.availHeight]]; bqx3();////////// } wql("3"); |
11. 获取JSocket.swf的相关信息用于更新UA。
1 2 3 4 5 |
if(ivsz["FlashInfo"]) { jl(); ///// vq4(13, [document.JSocket.getos(), document.JSocket.getversion()]); } wql("13"); |
12. 这里涉及getlso和setlso,后续会深入讲解。
1 2 3 4 5 6 |
if(ivsz["PCIDInfo"]) {//此部分涉及到getlso和setlso q(); setTimeout(aqi, 100); } wq1("10"); |