⛳️ 实战场景
本文带给大家的是一篇理论课程,而这些理论经常被用在 X-Bogus,signature 加密算法中,如果你碰到了如下代码段,那么欢迎入坑,这是一个另类的解谜世界。
var w0_0xa406bf = 'undefined' == typeof window ? global : window;
w0_0xa406bf['_$webrt_1645197018'] = function(_0x29b2b8, _0x2b18a2, _0x1a7e33) {
function _0xa52d25() {
if ('undefined' == typeof Reflect || !Reflect['construct'])
return !(0x3 * 0x6b1 + 0x2 * -0x79 + -0x1320);
if (Reflect['construct']['sham'])
return !(0x50c * -0x7 + -0x9 * -0x391 + 0x33c);
if ('function' == typeof Proxy)
return !(-0x22f8 + 0x78 + 0x2280);
try {
return Date['prototype']['toString']['call'](Reflect['construct'](Date, [], function() {})),
!(-0x1daa + 0x18e3 * 0x1 + 0x4c7 * 0x1);
} catch (_0x2d9e5a) {
return !(0x19d4 + -0x1 * -0xd8a + 0xd1f * -0x3);
}
}
复制代码
上述代码是典型的 ob 混淆 JS 代码,利用的 AST 技术,这些属于爬虫工程师常见的一种加密方式,当然有人会把它放到逆向破解相关技术栈中去,也没啥问题。
⛳️ AST 理论铺垫
AST,全名 Abstract Syntax Tree,即抽象语法树,用树形表现编程语法的语法结构,树上每个节点都是源代码中的结构。
在接下来的学习中,你将用到一个测试站点,地址为 astexplorer.net
下面正向学习一下 AST 的加密过程,假设有如下代码:
查看其树结构如下图所示。
其中 type 关键字的值是关键参数,包含 Program
, VariableDeclarator
, Identifier
、 Literal
,这些 AST 的结构类型,其它更多结构,可以参考下表。
⛳️ AST 常见的节点
Literal
:字面量,就是变量值类型,例如数字字面量 NumericLiteral
,布尔字面量 BooleanLiteral
,字符串字面量 StringLiteral
,正则表达式字面量 RegExpLiteral
;
Identifier
:标识符,变量名,属性名,参数名都是该节点类型;
Statement
:语句,独立执行的单位,例如 break
,continue
,return
等内容;
Declaration
:声明语句,表示在作用于内声明一个变量,函数,类等内容;
Expression
:表达式节点,执行完毕有返回值;
Class
:类相关,例如属性是 ClassProperty
,方法是 ClassMethod
;
Program
:整个程序节点
AST 的公共属性
了解上述内容,便于编写爬虫时,对 JS 混淆后的代码进行还原。
AST 混淆逆向实战
首先我们准备一段自己知道的代码,然后进行混淆。
function func(a, b) {
var num1 = 1 + 3;
var num2 = a * b;
return num1 + num2;
}
console.log(func(55, 66));
复制代码
将上述代码在 www.obfuscator.io 站点进行加密,得到 AST 混淆代码。
(function (_0xee606e, _0x16e55f) {
var _0xa3ca2f = _0x32f5,
_0x41f3a7 = _0xee606e();
while (!![]) {
try {
var _0x991da5 =
-parseInt(_0xa3ca2f(0xf2)) / 0x1 +
(parseInt(_0xa3ca2f(0xeb)) / 0x2) * (parseInt(_0xa3ca2f(0xf0)) / 0x3) +
(-parseInt(_0xa3ca2f(0xed)) / 0x4) * (parseInt(_0xa3ca2f(0xea)) / 0x5) +
(parseInt(_0xa3ca2f(0xf1)) / 0x6) * (parseInt(_0xa3ca2f(0xf3)) / 0x7) +
(-parseInt(_0xa3ca2f(0xe9)) / 0x8) *
(-parseInt(_0xa3ca2f(0xee)) / 0x9) +
-parseInt(_0xa3ca2f(0xec)) / 0xa +
-parseInt(_0xa3ca2f(0xef)) / 0xb;
if (_0x991da5 === _0x16e55f) break;
else _0x41f3a7["push"](_0x41f3a7["shift"]());
} catch (_0x2d0064) {
_0x41f3a7["push"](_0x41f3a7["shift"]());
}
}
})(_0x313f, 0x7f042);
function _0x313f() {
var _0x2bc0dd = [
"649663FPFtOd",
"8ldAjWQ",
"5rEymRn",
"4kkmYos",
"2258010xSWThD",
"331772cItYCu",
"1575162YsYbXq",
"8207276CVOiDo",
"1474164UGtjUk",
"66zXcDEH",
"603575iGQzOe",
];
_0x313f = function () {
return _0x2bc0dd;
};
return _0x313f();
}
function func(_0x2e8110, _0x433be5) {
var _0x4c778b = 0x1 + 0x3,
_0x5777a2 = _0x2e8110 * _0x433be5;
return _0x4c778b + _0x5777a2;
}
function _0x32f5(_0x3f57f9, _0x39d0d7) {
var _0x313fb8 = _0x313f();
return (
(_0x32f5 = function (_0x32f505, _0x17f682) {
_0x32f505 = _0x32f505 - 0xe9;
var _0xea531f = _0x313fb8[_0x32f505];
return _0xea531f;
}),
_0x32f5(_0x3f57f9, _0x39d0d7)
);
}
console["log"](func(0x37, 0x42));
复制代码
然后在 astexplorer.net 查看其结构。
还可以将上述加密之后的 JS 代码,放到 HTML 文件中,查看运行结果。
代码可以正常运行,此时你在对比着原代码进行学习,就能形象的理解混淆之后的代码结构了。
逆向的过程你可以结合 astexplorer.net 查看的结构,一点点还原,当然也可以通过工具,这里有一款还不错的浏览器插件。插件名称是:v_jstools js hook 工具,可以在谷歌商店直接下载安装。
下载地址
安装插件之后,直接使用可以直接解决简单的混淆,注意下图最后【解密 ob 高级混淆】之后的代码。
function func(_0x2e8110, _0x433be5) {
var _0x4c778b = 4;
var _0x5777a2 = _0x2e8110 * _0x433be5;
return _0x4c778b + _0x5777a2;
}
console.log(func(55, 66));
复制代码
这段代码跟我们开始写好的代码,可以说是一模一样。
如果无法直接解析,也可以选择【仅变量压缩】
希望本文能让你对 AST 有所了解~
评论