首页
社区
课程
招聘
[原创]akamai动态参数ver--ast学习
发表于: 22小时前 157

[原创]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、结果展示



传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 22小时前 被小灰灰爬虫编辑 ,原因:
收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回