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函数体中,如是,则跳过。
用此方法修复后,运行稠浊加密后的代码正常,如下图所示: