-
-
[原创]akamai动态参数ver--ast学习
-
发表于: 22小时前 157
-
作者声明:文章仅供学习交流与参考!严禁用于任何商业与非法用途!否则由此产生的一切后果均与作者无关!如有侵权,请联系作者本人进行删除!
1、代码预处理
用 @babel/parser 把源码字符串变成 AST(抽象语法树)。如果解析失败(语法错误),catch 里直接打印警告并原样返回代码。收集所有自执行函数,只处理第二个函数,取出这个函数体里的所有语句。
let bodyStatements = [];
if (t.isBlockStatement(funcExpr.body)) {
bodyStatements = funcExpr.body.body;
} else {
bodyStatements = [t.expressionStatement(funcExpr.body)];
}然后把 return 语句“降格”成普通表达式,其它语句原样保留。用剥壳后的代码替换掉原来的代码。代码:secondIIFE.replaceWithMultiple(processed)。
const processed = bodyStatements .map(stmt => t.isReturnStatement(stmt) && stmt.argument ? t.expressionStatement(stmt.argument) : stmt) .filter(Boolean);
2、AST 解析:定位核心函数与调用逻辑
在本地打开文件,先定位目标的位置,找到特征。可以发现3个动态变量都在FI函数中,所以先定位FI,对比FI作用域的其他函数会发现FI的代码所站行数明显比其他的多,可以通过这个定位该函数。



将代码放到ast解析网站,定位逻辑:var语句、右侧是函数、里面有一个switch、整个函数占用行数最多。

进一步获取switch中的case,定位疑似目标代码,拿到所有case里面第一层的var赋值语句,且右侧是"CallExpression",得到一个列表,这里面会有ver和动态常量的代码。
function get_case(max_node){
const case_list = [];
if (max_node.body && max_node.body.type === 'BlockStatement'){
for (let statement of max_node.body.body) {
if (statement.type === 'SwitchStatement') {
for (let switchCase of statement.cases) {
case_list.push(switchCase);
}
}
}
}
return case_list
}
获取疑似动态字符串代码:type是"ExpressionStatement"、expression.type是'CallExpression'且有3个参数。

经过多次测试发现,3个动态参数的特征。动态常量:number类型且下一行一定是ver;ver:长度一定是44;动态字符串:长度在1000到2000之间。
let result_str_1 = null
let result_str_2 = null
let result_str_3 = null
for (let index = 0; index < call_list.length; index++) {
if (result_str_1 !== null && result_str_2 !== null, result_str_3!=null) break;
const value = call_list[index];
try {
let str_1 = dom.window.eval(value);
if (typeof str_1 === 'number') {
if (index + 1 < call_list.length) {
let str_2 = dom.window.eval(call_list[index + 1]);
if (typeof str_2 === 'string' && str_2.length === 44) {
result_str_1 = str_1;
result_str_2 = str_2;
}
}
} else if (str_1.length > 1000 && str_1.length < 2000) {
result_str_3 = str_1
}
} catch (err) {
// console.debug(`处理索引 ${index} 时出错:`, err.message);
}
}
return [result_str_1, result_str_2, result_str_3]3、模拟环境执行:获取参数实际值
整个代码里面有很多浏览器环境,直接执行会报错,我这里是通过 jsdom 创建虚拟 DOM 环境,模拟浏览器上下文。先使用html获取初始化dom,然后eval预处理后的js文件,后续定位到目标代码就可以使用eval进行还原了。
function createDOM(html_data) {
const virtualConsole = new VirtualConsole();
return new JSDOM(html_data || '<!DOCTYPE html>', {
runScripts: "dangerously",
resources: new ResourceLoader({
fetch: (url, options) => {
return Promise.reject(new Error("External resources are disabled"));
}
}),
virtualConsole,
pretendToBeVisual: true
});
}4、ast学习小结
- 代码简化:通过 AST 解析剥离自执行函数包装结构,暴露核心逻辑;
- 节点定位:遍历 AST 找到核心函数、switch 分支及关键调用表达式;
- 环境模拟:基于 jsdom 构建虚拟浏览器环境,执行代码获取运行时参数;
- 参数筛选:根据参数特征(类型、长度)提取目标值。
- ast解析网站:5c8K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6S2M7%4c8W2P5s2m8D9L8%4u0W2M7W2)9J5k6h3&6W2N6q4)9J5c8R3`.`.
5、结果展示
