作者声明:文章仅供学习交流与参考!严禁用于任何商业与非法用途!否则由此产生的一切后果均与作者无关!如有侵权,请联系作者本人进行删除!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];
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) {
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 构建虚拟浏览器环境,执行代码获取运行时参数
...(已截断)
---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-289964.htm
[原创]akamai动态参数ver--ast学习
195 浏览
1 回复
tql