Skip to content

Instantly share code, notes, and snippets.

@cflems
Last active December 12, 2022 10:01
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save cflems/f1d9d5566f8fa05be17b8e554615baa1 to your computer and use it in GitHub Desktop.
Save cflems/f1d9d5566f8fa05be17b8e554615baa1 to your computer and use it in GitHub Desktop.
Obfuscate JavaScript code into having zero readable characters; I want to improve this not to use eval at all but I'll have to write a JS tokenizer for that.
const zero = '+[]'; // 1
const one = '+!![]'; // 1
const two = '('+ one + one +')'; // 2
const three = '('+ one + one + one +')'; // 3
const four = '('+ one + one + '<<' + one +')'; // 3
const five = '('+ four + one +')'; // 4
const six = '('+ one + one + one + '<<' + one +')'; // 4
const seven = '('+ six + one +')';
const eight = '('+ one + one + '<<' + one + one +')'; // 4
const int_lits = {0: zero, 1: one, 2: two, 3: three, 4: four, 5: five, 6: six, 7: seven, 8: eight};
function compile_int(n) {
if (n in int_lits) return int_lits[n];
let compiled = [], m = n;
if (n < 0) m = -n;
const stack = m.toString(8).split('');
for (let sh = 0; stack.length > 0; sh++) {
const lit = parseInt(stack.pop());
if (lit === 0) continue;
let tentative = int_lits[lit];
if (sh > 0) tentative = '('+tentative+'<<'+compile_int(sh*3)+')';
compiled.push(tentative);
}
compiled = '('+compiled.join('|')+')';
if (n < 0) compiled = '-'+compiled;
int_lits[n] = compiled;
return compiled;
}
const char_lits = {
'N': '(+{}+[])['+compile_int(0)+']',
'a': '(+{}+[])['+compile_int(1)+']',
// N
'[': '({}+[])['+compile_int(0)+']',
'o': '({}+[])['+compile_int(1)+']',
'b': '({}+[])['+compile_int(2)+']',
'j': '({}+[])['+compile_int(3)+']',
// e
'c': '({}+[])['+compile_int(5)+']',
// t
' ': '({}+[])['+compile_int(7)+']',
'O': '({}+[])['+compile_int(8)+']',
// bject
']': '({}+[])['+compile_int(14)+']',
'f': '(![]+[])['+compile_int(0)+']',
// a
'l': '(![]+[])['+compile_int(2)+']',
's': '(![]+[])['+compile_int(3)+']',
// e
't': '(!![]+[])['+compile_int(0)+']',
'r': '(!![]+[])['+compile_int(1)+']',
'u': '(!![]+[])['+compile_int(2)+']',
'e': '(!![]+[])['+compile_int(3)+']',
'\/': '(/\\\\/+[])['+compile_int(0)+']',
'\\': '(/\\\\/+[])['+compile_int(1)+']',
'I': '((+!![]/+[])+[])['+compile_int(0)+']',
'n': '((+!![]/+[])+[])['+compile_int(1)+']',
// f
'i': '((+!![]/+[])+[])['+compile_int(3)+']',
// nit
'y': '((+!![]/+[])+[])['+compile_int(7)+']',
//un
'd': '([]['+compile_int(0)+']+[])['+compile_int(2)+']',
// efined
};
// wanted: m C h in relatively short fashion
function compile_string(s, as_code = false) {
const compiled = [];
for (const c of s) {
const req = '$('+compile_int(c.charCodeAt(0))+')';
if (c in char_lits && (char_lits[c].length <= req.length || !as_code))
compiled.push(char_lits[c]);
else
compiled.push(req);
}
return compiled.join('+');
}
// these are ~300 chars, will require compression
char_lits['p'] = '(/</['+compile_string('constructor')+']+[])['+compile_int(14)+']';
char_lits['S'] = '([]+([]+[])['+compile_string('constructor')+'])['+compile_int(9)+']';
char_lits['g'] = '([]+([]+[])['+compile_string('constructor')+'])['+compile_int(14)+']';
char_lits['('] = '([]+([]+[])['+compile_string('constructor')+'])['+compile_int(15)+']';
char_lits[')'] = '([]+([]+[])['+compile_string('constructor')+'])['+compile_int(16)+']';
char_lits['{'] = '([]+([]+[])['+compile_string('constructor')+'])['+compile_int(18)+']';
char_lits['}'] = '([]+([]+[])['+compile_string('constructor')+'])['+compile_int(34)+']';
char_lits['v'] = '([]+([]+[])['+compile_string('constructor')+'])['+compile_int(25)+']';
char_lits['m'] = '((+[])['+compile_string('constructor')+']+[])['+compile_int(11)+']';
// these are ~800 chars, will require great compression
char_lits['h'] = '('+compile_int(17)+')['+compile_string('toString')+']('+compile_int(24)+')';
char_lits['C'] = '((()=>{})['+compile_string('constructor')+']('+compile_string('return escape')+')()('+compile_string('\\')+'))['+compile_int(2)+']';
const prelude = '$=([]+[])['+compile_string('constructor')+']['+compile_string('fromCharCode')+'];';
function compile_code(code) {
return prelude + '(()=>{})['+compile_string('constructor')+']('+compile_string(code, true)+')()';
}
if (typeof process === 'undefined')
process = global.process;
if (process.argv.length < 3) {
console.log('Usage:', process.argv[0], process.argv[1], '<input file>');
process.exit(1);
}
if (process.argv[2] === '-') {
const data = [];
process.stdin.on('data', function (fragment) {
data.push(fragment);
});
process.stdin.on('close', function() {
const code = Buffer.concat(data).toString();
console.log(compile_code(code));
});
} else {
if (typeof require === 'undefined')
require = global.require || global.process.mainModule.constructor._load;
const fs = require('fs');
const code = fs.readFileSync(process.argv[2], {encoding: 'utf8'});
console.log(compile_code(code));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment