网络知识 娱乐 JavaScript-Obfuscator4.0.0字符串阵列化Bug及修复方法

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

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

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

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


在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) {n await page.evaluateHandle(function(){n return window.renderdone;n });n }n n (async () => {n const puppeteer = require('puppeteer');n puppeteer.launch().then(n async browser => {n console.log('...');n const [page] = await browser.pages();n await page.goto('https://www.baidu.com');n await waitPage(page);n }n )n })();nJavaScript-Obfuscator4.0.0字符串阵列化Bug及修复方法

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

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

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

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

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

Bug原因:

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

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

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

Bug修复方案:

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

以下为临时修复代码:

//原始: return this.transformNode(node, parentNode);nn//修复bug后的代码:nn//是否是异步函数的标识nvar in_async_function = false;n//递归函数,检测节点所有上级节点,判断是否处于异步函数中nvar point = "-";nfunction detect_async_function(node:ESTree.Node){n console.log(point, node.type);n if(node.type == "FunctionDeclaration"){n console.log(point, node.id?.name);n }nn //是函数定义,并且是异步函数n if((node.type == "ArrowFunctionExpression" || node.type == "FunctionDeclaration" || node.type == "FunctionExpression") && node.async == true){n in_async_function = true;n return;n }n //是否达到节点顶部。测试中发现node.parentNode永远存在,达顶点后上级顶点依然是Programn if(node.type == "Program"){n return;n }n n if(node.parentNode){n point = point + "-";n detect_async_function(node.parentNode)n }else{n //不能获得父节点,是异常的代码,跳过n in_async_function = true;n return;n }n}ndetect_async_function(node);nconsole.log(node.value,node.loc);nn//没有检测出异步函数,正常处理nif(in_async_function == false){n return this.transformNode(node, parentNode);n}JavaScript-Obfuscator4.0.0字符串阵列化Bug及修复方法

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

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

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