论坛首页 漏洞分析研究区 阅读主题

[原创]akamai动态参数ver--ast学习

195 浏览 1 回复
#1 楼主 2026-06-01 21:09:08
作者声明:文章仅供学习交流与参考!严禁用于任何商业与非法用途!否则由此产生的一切后果均与作者无关!如有侵权,请联系作者本人进行删除!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
#2 2026-06-01 21:09:08
tql

请登录后参与讨论

立即登录 注册账号