混淆JavaScript手动替换工作量大,求处理工具或可行方法
Hey there! I’ve wrestled with this exact type of JavaScript obfuscation before—those self-executing anonymous functions that stuff all literals into arguments are brutal to unpack manually, especially when you’re dealing with large files. Let’s walk through practical tools and methods to make this way easier:
If you’re dealing with multiple files or large chunks of code, manual replacement isn’t feasible. These tools/approaches will handle the heavy lifting:
AST-Based Custom Script
This is my go-to for structured obfuscation like this. JavaScript’s Abstract Syntax Tree (AST) lets us parse the code’s structure programmatically, map function parameters to their actual values, and auto-replace everything. Here’s a quick example using popular AST libraries:const esprima = require('esprima'); const estraverse = require('estraverse'); const escodegen = require('escodegen'); function deobfuscate(code) { const ast = esprima.parseScript(code); estraverse.traverse(ast, { enter(node) { // Target self-executing functions prefixed with ! (common pattern here) if (node.type === 'CallExpression' && node.callee.type === 'UnaryExpression' && node.callee.operator === '!') { const anonFunc = node.callee.argument; // Match param count to argument count (key for this obfuscation) if (anonFunc.type === 'FunctionExpression' && anonFunc.params.length === node.arguments.length) { // Create a map: param name → actual value const paramMap = new Map(); anonFunc.params.forEach((param, index) => { paramMap.set(param.name, node.arguments[index]); }); // Replace all param references in the function body anonFunc.body.body.forEach(statement => { replaceIdentifiers(statement, paramMap); }); // Replace the obfuscated function with its deobfuscated body ast.body = ast.body.filter(n => n !== node).concat(anonFunc.body.body); } } } }); return escodegen.generate(ast); } // Helper to recursively replace param identifiers with their actual values function replaceIdentifiers(node, map) { if (node.type === 'Identifier' && map.has(node.name)) { Object.assign(node, map.get(node.name)); } else if (node.type === 'MemberExpression') { replaceIdentifiers(node.object, map); replaceIdentifiers(node.property, map); } else if (node.type === 'CallExpression') { replaceIdentifiers(node.callee, map); node.arguments.forEach(arg => replaceIdentifiers(arg, map)); } } // Test with your sample code const obfuscatedCode = `!function(a, b, c, d, e, f){ a[d] = a[b][c](d); a[d][e]=f;}(this, 'document', 'getElementById', 'a', 'innerHTML', 'hello world');`; console.log(deobfuscate(obfuscatedCode));Run this script on your files, and it’ll automatically convert that obfuscated pattern back to readable code. Just make sure to install the dependencies first (
npm install esprima estraverse escodegen).Specialized Deobfuscation Tools
There are dedicated tools (both desktop and web-based) that detect this exact obfuscation pattern. They’ll parse the argument-param mapping and spit out deobfuscated code in seconds. Just note: never paste sensitive code into untrusted web tools—stick to local tools if your code contains private logic.
If you only have a few lines to fix, you can do this manually with a simple system:
- Map Parameters to Values: Write down the function’s parameter list and their corresponding arguments. For your sample:
a→thisb→'document'c→'getElementById'd→'a'e→'innerHTML'f→'hello world'
- Replace References: Go through each line in the anonymous function body and swap every parameter with its mapped value. For example:
a[d] = a[b][c](d)becomesthis['a'] = this['document']['getElementById']('a')- Clean up the syntax to get
var a = document.getElementById('a'); a[d][e] = fbecomesthis['a']['innerHTML'] = 'hello world', which cleans up toa.innerHTML = 'hello world';
- Remove the Wrapper: Delete the outer self-executing function wrapper, and you’re left with the original readable code.
This pattern is super consistent, so once you get the hang of the mapping, even manual work goes fast for small bits.
内容的提问来源于stack exchange,提问作者qq234853008

