JavaScript-Obfuscator4.0.0字符串阵列化Bug及修复方法

JavaScript-Obfuscator4.0.0字符串阵列化Bug及修复方法

Javascript-obfuscator是全球知名的开源JavaScript代码混淆加密工具,由俄罗斯程序员Timofey Kachalov开发维护。

在2022年2月15日发布的4.0.0版本中,其存在一个字符串阵列化Bug,某些情况下会导致混淆结果异常。本文对Bug情况进行说明并提供修复方法。

注:此bug由JShaman团队发现,并已提交作者修复。

JShaman是国内专业的javascript源代码安全研究组织,与Javascript-obfuscator保持着友好联络与技术交流。

Bug描述:


Javascript-obfuscator4.0.0,其字符串阵列功能,对async函数中的成员对象进行阵列化处理,会导致代码异常。

例如,一段NodeJS代码:

async function waitPage(page) {
    await page.evaluateHandle(function(){
        return window.renderdone;
    });
 }
 
 (async () => {
     const puppeteer = require('puppeteer');
     puppeteer.launch().then(
         async browser => {
             console.log('...');
             const [page] = await browser.pages();
             await page.goto('https://www.baidu.com');
             await waitPage(page);
         }
     )
 })();

使用Javascript-obfuscator进行混淆加密,保护选项只选择了字符串阵列化这一个功能:

混淆加密后的代码,运行时发生异常,提示有变量未定义:

注意图中命令行中所显示,第一次执行是在未加密前,可正常使用。第二次是执行加密后的代码,出现错误。

Bug原因:

上述JS代码混淆加密后出现错误的原因,是由于进行字符串的阵列化处理时,未考虑是否处于async函数中。导致阵列化时MemberExpression字面量放置到了函数不可访问的外部区域中。如下图所示:

注:绿线上方是原始代码,做对比用。参考上面图中的错误提示变量,可以看出错误原因。

Bug修复方案:

阵列化功能,在JavaScript-Obfuscator目录下的StringArrayTransformer.ts文件中。

以下为临时修复代码:

//原始: return this.transformNode(node, parentNode);

//修复bug后的代码:

//是否是异步函数的标识
var in_async_function = false;
//递归函数,检测节点所有上级节点,判断是否处于异步函数中
var point = "-";
function detect_async_function(node:ESTree.Node){
    console.log(point, node.type);
    if(node.type == "FunctionDeclaration"){
        console.log(point, node.id?.name);
    }

    //是函数定义,并且是异步函数
    if((node.type == "ArrowFunctionExpression" || node.type == "FunctionDeclaration" || node.type == "FunctionExpression") && node.async == true){
        in_async_function = true;
        return;
    }
    //是否达到节点顶部。测试中发现node.parentNode永远存在,达顶点后上级顶点依然是Program
    if(node.type == "Program"){
        return;
    }
    
    if(node.parentNode){
        point = point + "-";
        detect_async_function(node.parentNode)
    }else{
        //不能获得父节点,是异常的代码,跳过
        in_async_function = true;
        return;
    }
}
detect_async_function(node);
console.log(node.value,node.loc);

//没有检测出异步函数,正常处理
if(in_async_function == false){
    return this.transformNode(node, parentNode);
}

即:在处理字面量时,判断是否处于async函数体中,如是,则跳过。

用此方法修复后,运行混淆加密后的代码正常,如下图所示:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值