Skip to content

Instantly share code, notes, and snippets.

@QuarkGluonPlasma
Last active March 17, 2021 08:08
Show Gist options
  • Save QuarkGluonPlasma/7da399cb216f2e6a59e5e8a60a718bfd to your computer and use it in GitHub Desktop.
Save QuarkGluonPlasma/7da399cb216f2e6a59e5e8a60a718bfd to your computer and use it in GitHub Desktop.
基于base54算法实现的标识符混淆,支持toplevel设置
const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
const generate = require('@babel/generator').default;
const code1 = `
const ssh = 'sshssh';
(function parc(moo, man){
try {
console.log(ssh);
var foobar = 10;
function bbb() {
const ssh2 = 'sshsshsshssh';
console.log(foobar);
(function () {
console.log(ssh2);
})();
}
function ccc() {
const ssh3 = 'sshsshssh';
(function () {
console.log(ssh3);
})();
}
return parc(foobar + moo + man);
} catch(ex) {
log(ex);
return foobar;
}
})();
`;
const code2 = `
const ssh = 'sshssh';
(function parc(moo, man){
try {
console.log(ssh);
var foobar = 10;
function aaa() {
eval('console.log(foobar)');
}
function bbb() {
const ssh2 = 'sshsshsshssh';
console.log(foobar);
(function () {
console.log(ssh2);
})();
}
function ccc() {
const ssh3 = 'sshsshssh';
(function () {
console.log(ssh3);
})();
}
return parc(foobar + moo + man);
} catch(ex) {
log(ex);
return foobar;
}
})();
`;
const base54 = (function(){
var DIGITS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_";
return function(num) {
var ret = "";
do {
ret = DIGITS.charAt(num % 54) + ret;
num = Math.floor(num / 54);
} while (num > 0);
return ret;
};
})();
const defaultOptions = {
toplevel: false
}
function mangle(code, { toplevel } = defaultOptions) {
const ast = parser.parse(code);
let uid = 0;
traverse(ast, {
CallExpression(path) {
if (path.node) {
if(generate(path.node.callee).code === 'eval') {
let scope = path.scope
while(scope) {
scope.hasEval = true;
scope = scope.parent
}
}
}
}
});
traverse(ast, {
Scopable: {
exit(path) {
if(!toplevel && !path.scope.parent) {
return;
}
if(path.scope.hasEval) {
return;
}
Object.entries(path.scope.bindings).forEach(([key, binding]) => {
if(binding.mangled) return;
binding.mangled = true;
const newName = base54(uid++);
binding.path.scope.rename(key, newName)
})
}
}
});
return generate(ast).code
}
console.log('toplevel也混淆:\n', mangle(code1, { toplevel: true }));
console.log('\ntoplevel不混淆:\n', mangle(code1));
console.log('\n有eval:\n', mangle(code2));
toplevel也混淆:
const j = 'sshssh';
(function f(g, h) {
try {
console.log(j);
var i = 10;
function c() {
const a = 'sshsshsshssh';
console.log(i);
(function () {
console.log(a);
})();
}
function d() {
const b = 'sshsshssh';
(function () {
console.log(b);
})();
}
return f(i + g + h);
} catch (e) {
log(e);
return i;
}
})();
toplevel不混淆:
const ssh = 'sshssh';
(function f(g, h) {
try {
console.log(ssh);
var i = 10;
function c() {
const a = 'sshsshsshssh';
console.log(i);
(function () {
console.log(a);
})();
}
function d() {
const b = 'sshsshssh';
(function () {
console.log(b);
})();
}
return f(i + g + h);
} catch (e) {
log(e);
return i;
}
})();
有eval:
const ssh = 'sshssh';
(function parc(moo, man) {
try {
console.log(ssh);
var foobar = 10;
function aaa() {
eval('console.log(foobar)');
}
function bbb() {
const a = 'sshsshsshssh';
console.log(foobar);
(function () {
console.log(a);
})();
}
function ccc() {
const b = 'sshsshssh';
(function () {
console.log(b);
})();
}
return parc(foobar + moo + man);
} catch (c) {
log(c);
return foobar;
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment