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

boyanx3个月前技术教程20

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函数体中,如是,则跳过。

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

相关文章

字符串既然直接可以用+相加,那要concat干什么?ES6之后又用什么

今天我们来学习下JavaScript的一种字符串方法, 字符串方法_concat()方法 concat()用于连接两个不同的字符串,返回一个新字符串,不改变原字符串示例对比:如果是连接两个字符串分别使...

js中字符串转base64以及base64转字符串原理及实现

今天刷codewars的题目的时候碰到一个通过js来实现字符串转base64的题目,base64虽然在js或nodejs中经常用,但是我还真没有仔细去看过原理以及如何实现,这回绕不过去了,赶紧找了找资...

学用系列|如何搞定word批量替换修改和格式转换?这里一站搞定

想必不少朋友都会碰到批量修改word文档内容、压缩文档图片、文件格式转换等重复性文档处理工作的需要,今天胖胖老师就推荐给大家一个免费工具XCLWinKits,一站搞定你所有的需要。什么是XCLWinK...

新增忘记按钮,火狐浏览器Firefox33.1官方下载

IT之家(www.ithome.com):新增忘记按钮,火狐浏览器Firefox33.1官方下载IT之家讯:今日,火狐浏览器Firefox正式更新至33.1版本。新版火狐浏览器增加了一个全新的“忘记”...

sql中常用的字符串函数详解_sql字符串是什么意思

在日常开发中遇到处理最多的可能字符串要算其中一个了,什么替换啊 截取啊 大小写转换啊、删除空格啊等等,这些操作我们可以在前端操作,也可以直接在数据库的sql中操作,那么我们来看一下sql中处理字符串的...

在javascript中如何将字符串转成变量或可执行的代码?

有这样一个需求:当前作用域内有未知的一些变量,其中一个函数中可以拿到某个变量名字符串,怎么能在函数内通过传进来的字符串取到作用域链中的变量值,示例小 demo 如下:const name = '...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。