在 NightTeam微信公众号上看见大佬一篇文章听说你碰到这种反爬就歇菜了?手把手教你秒杀它!
大佬具体扣代码没写,很是受伤,于是自己摸索了大半天,捋顺了大部分逻辑,写出来分享一下
ps:发送消息「隐式Style-CSS」到大佬微信公众号「NightTeam」即可获取样例地址~
前面分析,大神写的非常详细,具体看大神写的就好
977处代码
定义了变量_0xa12e
,1133处代码
是一段for循环
,经过观察1133处代码较为复杂,有许多未知变量:words,_0xea12, document,打上断点调试一下for (var i = 0x0; i < words[_0xea12('0x18')]; i++) {
i
和words[_0xea12('0x18')]
明显为数字,用来控制函数循环次数words
是被替换的单词数组
跳转之后的函数var _0xea12 = function (_0x56430f, _0x7f6841)
_0x56430f, _0x7f6841
又定义了一个变量 _0x4f7a0f
接受 _0xa12e
函数_0x56430f
处理的结果var _0x4f7a0f = _0xa12e[_0x56430f]
最后返回 _0x4f7a0f
。_0xa12e
words[_0xea12('0x18')]
0x18
结果为24,之后_0xea12
函数(返回结果为数组)取下标为24的元素,结果为length
,之后words数组调用length方法,取得words数组的长度结果为24
for (var i = 0x0; i < 24; i++) {
for (var i = 0x0; i <24; i++) {
try {
document["styleSheets"][0x0]["addRule"]('.context_kw' + i + "::before", 'content:\x20\x22' + words[i] + '\x22');
} catch (_0x527f83) {
document['styleSheets'][0x0]['insertRule'](".context_kw" + i + "::before{content: "" + words[i] + '\x22}', document["styleSheets"][0x0]["cssRules"]["length"]);
}
}
此处CSSStyleSheet.insertRule
()方法用来给当前样式表插入新的样式规则. 语法:stylesheet.insertRule(rule, index)
参数
rule
: 一个包含了将要插入的规则的 DOMString。规则字符串必须包含的内容取决于它的类型
For rule-sets, both a selector and a style declaration.
For at-rules, both an at-identifier and the rule content.
index
可选
小于或等于stylesheet.cssrules.length的正整数,表示新插入的规则在cssstylesheet.cssrules中的位置。默认值为0。(在旧的实现中,这是必需的。有关详细信息,请参见浏览器兼容性。)
ps:此处我没有搞懂catch (_0x527f83) 是怎么触发的。。知道的请务必留言告诉我
words
参数var words = new Array(secWords[_0xea12('0x18')]);
_0xea12('0x18')
为lenght
,secWords
为长度24的数组
所以此处代码意思为:定义一个名为words 长度为24的 空数组
调试代码
条件语句中,secWords[_0xea12('0x18')]
调试结果为24
函数体中:
var _0x5420ee = '3|5|2|4|0|1'[_0xea12('0x17')]('|')
调试结果为["3", "5", "2", "4", "0", "1"]
_0x9ff9d9 = 0x0
--> _0x9ff9d9 = 0
while (!![]) {
--> while (true) {
显然是死循环
接下来看循环内部:
内部是一个switch case 语句,case值为0,1,2,3,4,5。而每一句都有结束时都有一个continue关键字
switch case 语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支
switch case 执行时,一定会先进行匹配,匹配成功返回当前 case 的值,再根据是否有 break,判断是否继续输出,或是跳出判断
break 语句用于跳出循环。
continue 用于跳过循环中的一个迭代。
switch (_0x5420ee[_0x9ff9d9++]) {
,上方定义了 _0x9ff9d9 = 0,而后面 带有++ 自增 显然是循环 将值赋给_0x5420ee( 数组 --> [“3”, “5”, “2”, “4”, “0”, “1”]),获得其对应下标的值。
综上所诉,我们知道了循环处理顺序:3,5,2,4,0,1
逐步分析case语句
case '3':var _0x423190 = secWords[i];
第一次循环时i = 0,此时 _0x423190 = secWords[i] = 65291
case '5':
var _0x3e8e1e = function (_0xd024e1) {
var _0x3e40d1 = {
'mPDrG': function _0x411e6f(_0xa8939, _0x278c20) {
return _0xa8939 % _0x278c20;
},
'DWwdv': function _0x1e0293(_0x5b15eb, _0x443876) {
return _0x5b15eb - _0x443876;
}
};
return _0x3e40d1[_0xea12('0x28')](_0xd024e1, 0x2) ? _0x3e40d1[_0xea12('0x29')](_0xd024e1, 0x2) : _0xd024e1 - 0x4;
};
continue;
先从return看起,分析得出_0x3e40d1[_0xea12('0x28')]
--> mPDrG;
_0x3e40d1[_0xea12('0x29')]
--> DWwdv,所以 此处返回的是自身定义的函数处理结果。将变量带入,来看看
case '5':
var _0x3e8e1e = function (_0xd024e1) {
var _0x3e40d1 = {
'mPDrG': function _0x411e6f(_0xd024e1, 0x2) {
return _0xd024e1 % 0x2;
},
'DWwdv': function _0x1e0293(_0xd024e1, 0x2) {
return _0xd024e1 - 0x2;
}
};
return mPDrG(_0xd024e1, 0x2) ? DWwdv(_0xd024e1, 0x2) : _0xd024e1 - 0x4;
};
continue;
结果清晰明了,case5 是将传入的参数_0xd024e1
进行处理从而得出结果。此处暂无参数 ,继续看循环case2:
case '2':
var _0x5796d9 = function (_0x490c80) {
var _0x1532b6 = {
'ifLSL': function _0x256992(_0x118bb, _0x36aa09) {
return _0x118bb + _0x36aa09;
}
};
return _0x1532b6[_0xea12('0x26')](_0x490c80, 0x3 * + !(typeof document === _0xea12('0x27')));
};
依旧先从return看起,_0x1532b6[_0xea12('0x26')]
结果为 ifLSL,由于不懂!(typeof document === _0xea12('0x27'))
。利用console进行测试。得到结果为true
。true为1 所以处理函数,将其变换为
case '2':
var _0x5796d9 = function (_0x490c80) {
var _0x1532b6 = {
'ifLSL': function _0x256992(_0x490c80, 0x3 * + 1) {
return _0x490c80 + 0x3 * + 1;
}
};
return ifLSL(_0x490c80, 0x3 * + 1);
};
逻辑与case5 类型得到一个关于_0x490c80参数的函数,继续看循环4:
case '4':
_0x423190 = _0x3e8e1e(_0x423190);
经过case3 我们知道_0x423190 = secWords[i] = 65291
,case5中我们知道了_0x3e8e1e函数的处理数字的方式,运算过程如下:
// 将_0x423190代入函数
return('mPDrG')(65291, 0x2) ?_0x3e40d1('DWwdv')(65291, 0x2) : 65291 - 0x4;
return 1 ?65289 : 65287;
// console 调试 1 ?65289 : 65287
所以得到结果_0x423190 = 65289
。继续循环,看case0:
case '0':
_0x423190 = _0x5796d9(_0x423190);
将case4结果_0x423190 = 65289
代入,console调试得到结果_0x423190 = 65292
。最后一个case1:
case '1':
words[i] = String[_0xea12('0x25')](_0x423190);
显而易见,此处是给word(24位空数组)赋值,此时第一次while循环 i = 0,
case '1':
words[0] = String[_0xea12('0x25')](65292);
最后,写作不易,点个关注,点个赞呗5555