Last active
November 8, 2020 23:03
-
-
Save vp777/6a1b04045af111a279f34eefcfb815f8 to your computer and use it in GitHub Desktop.
babeljs plugin that unravels a number of common JS obfuscation patterns
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
babeljs plugin that unravels a number of common obfuscation patterns (originally found in F5 JS obfuscation library). | |
tip: for better results you can feed the output of the below plugin to minify | |
usage: set the plugins in your .babelrc to the path of this script | |
What it does, it gets as input the following obfuscated code: | |
function toBeGone(s, u, m){ | |
return Array.from(arguments).reduce((a,b)=>a+b, 0); | |
} | |
let arg=2; | |
let a=toBeGone(arg,6); | |
let b="\x41B\u0043"; | |
let c=0x100; | |
let d1=(1>9,fff,3,0o20); | |
let d2=(1>9,fff(),3,0o20); | |
let e1=(1+Math.random())?"it's truthy":"it's falsy"; | |
let e2=parseInt(256*Math.random(), 10); | |
and turns it into this: | |
function toBeGone(s, u, m) { | |
return arguments.reduce((a, b) => a + b, 0); | |
} | |
let arg = 2; | |
let a = 8; | |
let b = "ABC"; | |
let c = 256; | |
let d1 = 16; | |
let d2 = (1 > 9, fff(), 3); | |
let e1 = "it's truthy"; | |
let e2 = parseInt(256 * Math.random(), 10); | |
*/ | |
const FUNCTION_WHITELIST = { | |
toBeGone(s, u, m) { | |
return Array.from(arguments).reduce((a, b) => a + b, 0); | |
} | |
} | |
/* | |
var arg=35; | |
func(arg); | |
arg++; | |
If you know that the above pattern is followed for FUNCTION_WHITELIST then you can set the below parameter to true. | |
*/ | |
const FALLBACK_ASSIGNMENT_VALUE = false; | |
//Replace Math.random with 0.5 when it has a parent a control flow statement. | |
const SUBSTITUTE_MATH_RANDOM = true; | |
module.exports = function ({ types: t }) { | |
return { | |
visitor: { | |
"StringLiteral|NumericLiteral": function (path) { | |
if (path.node.hasOwnProperty("extra")) { | |
delete path.node["extra"]; | |
} | |
}, | |
CallExpression(path) { | |
const { node } = path; | |
const callee = node.callee; | |
const func = FUNCTION_WHITELIST[callee.name]; | |
if (t.isIdentifier(callee) && func) { | |
fargs = []; | |
for (arg of path.get("arguments")) { | |
const res = arg.evaluate(); | |
if (res.confident) fargs.push(res.value); | |
else if (FALLBACK_ASSIGNMENT_VALUE) { | |
try { | |
fargs.push(res.deopt.node.init.value) | |
} catch (err) { | |
return; | |
} | |
} else return; | |
} | |
path.replaceWith(t.valueToNode(func.apply(null, fargs))); | |
} | |
}, | |
ConditionalExpression: { | |
exit(path) { | |
const res = path.get("test").evaluate(); | |
if (res.confident) { | |
path.replaceWith( | |
res.value ? path.node.consequent : path.node.alternate | |
); | |
} | |
} | |
}, | |
BinaryExpression: { | |
enter(path) { | |
if (!SUBSTITUTE_MATH_RANDOM) return; | |
if (!["ConditionalExpression", "IfStatement", "LogicalExpression"].some(type => path.parentPath.isNodeType(type))) return; | |
const { node } = path; | |
let currentBranch, currentCallee; | |
for (currentDirection of ["left", "right"]) { | |
currentBranch = path.get(currentDirection); | |
if (t.isCallExpression(currentBranch) && t.isMemberExpression(currentCallee = currentBranch.node.callee)) { | |
const object = currentCallee.object; | |
const property = currentCallee.property; | |
if (object.name === "Math" && property.name === "random") { | |
currentBranch.replaceWith(t.numericLiteral(0.5)); | |
} | |
} | |
} | |
} | |
}, | |
SequenceExpression: { | |
exit(path) { | |
const lastExpression = path.node.expressions.pop(); | |
let stateChangerExpr = false; | |
path.traverse({ | |
"AssignmentExpression|UpdateExpression|CallExpression": function (path) { | |
stateChangerExpr = true; | |
path.stop() | |
} | |
}); | |
if (stateChangerExpr) return; | |
path.replaceWith(lastExpression); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment