MichaelXF / js-confuser

JS-Confuser is a JavaScript obfuscation tool to make your programs *impossible* to read.
https://js-confuser.com
MIT License
236 stars 35 forks source link

We can store code in comments #151

Open doctor8296 opened 5 days ago

doctor8296 commented 5 days ago

How?

example:

(function func() {

    // audio.src = "Y29uc29sZS5sb2coJ2hlbGxvLCB3b3JsZCEnKQ"

    func.constructor(atob((''+func).match(/=\s"(\w+)"/)[1]))();

})()

I actually inserted obfuscated code like that in my script on some dashboard with userscripts that doesn't allow obfuscated code there, but no one could find it

MichaelXF commented 3 days ago

This is a great idea, could be used with RGF to store the arbitrary code, OR, with String Concealing to store the encrypted strings. I'm assuming the comment // audio.src = is used to disguise the payload as human-written code but isn't required.

// Input
function test() {
  console.log("Hello World");
}

test();

// Output
function comments() {
  //function __p_1rWn_embedded(){var[__p_kaTK_rgf,__p_S0VN_args]=arguments;function __p_qirC_replacement(){console["log"]("Hello World")}return __p_qirC_replacement["apply"](this,__p_S0VN_args)}__p_1rWn_embedded;
}

var stringed = comments.toString();
var data = stringed.substring(stringed.indexOf("//") + 2);
data = data.substring(0, data.indexOf("\n"));

function __p_AJxm(__p__flag = true) {
  return __p__flag;
}
var __p_sosl_rgf_eval_integrity = __p_AJxm();
var __p_kaTK_rgf = [__p_Ttkd_rgf_eval(data)];
function test() {
  return __p_kaTK_rgf[0]["apply"](this, [__p_kaTK_rgf, arguments]);
}
function __p_Ttkd_rgf_eval(code) {
  if (__p_sosl_rgf_eval_integrity) {
    return eval(code);
  }
}
test();

What's great is some deobfuscators unknowingly remove comments, permanently breaking the reversed output (As they are missing vital pieces)

doctor8296 commented 2 days ago

@MichaelXF however, don't forget that there this obfuscator is public, so this is easily reversable, unless we don't have some kind of unreversable changes... undetermined obfuscation? Did you think about it?

MichaelXF commented 2 days ago

Yes that's true however anyone can fork the repo and add their own obstacles if they wanted to. I still like the idea of using comments, could throw some people off

MichaelXF commented 2 days ago

I've also been thinking about encryption keys based on the column/line numbers of the code. When someone deobfuscates the code, they would get changed (Formatted, Some functions get removed, Expressions expanded, etc)

function dummyFunction() {}

function testMe() {
  var error;
  try {
    throw new Error();
  } catch (e) {
    error = e;
  }

  // Parse error stack trace
  var stackTraceLine = error.stack.split("\n")[1];
  var functionName = stackTraceLine.match(/at (.*) \(/)[1];
  var fileAndLocation = stackTraceLine.match(/\((.*)\)/)[1];
  var [file, lineNumber, columnNumber] = fileAndLocation.split(":");

  var stringDecryptionKey = parseInt(lineNumber) + parseInt(columnNumber); // 6 + 11 = 17

  console.log(functionName, lineNumber, columnNumber, stringDecryptionKey); // testMe 6 11 17

  var decryptedString = decrypt("Yt}}~1F~c}u", stringDecryptionKey);

  console.log(decryptedString); // "Hello World"
}

testMe();

// Simple XOR encryption/decryption
function encrypt(text, key) {
  let encryptedText = "";
  for (let i = 0; i < text.length; i++) {
    // XOR the character code with the key
    encryptedText += String.fromCharCode(text.charCodeAt(i) ^ key);
  }
  return encryptedText;
}

function decrypt(encryptedText, key) {
  let decryptedText = "";
  for (let i = 0; i < encryptedText.length; i++) {
    // XOR again with the same key to get the original character
    decryptedText += String.fromCharCode(encryptedText.charCodeAt(i) ^ key);
  }
  return decryptedText;
}

If you remove the unused function dummyFunction, the string fails to decrypt and you get "V{rrq>Iqlrz" instead. Only issue I see is Error parsing and obtaining the accurate column/line numbers.

doctor8296 commented 2 days ago

@MichaelXF I dont really trust to the stack property since it is non-standard (on safari stack shorter for example, and on firefox this property can get deleted), but yeah, Idea that structure itself is a part of a code.. I think a told this before xD

Also I'd added some property that will change structure of obfuscated code in a very specific way using some user input (developer who is obfuscating some cose) to make it is impossible to reverse knowing the source of obfuscator. I feel like it is just the same "undetermined obfuscation", but with some user impact which makes it unique... Of course anyone can easily fork it, but it is still way harder than add some property to existing lib.

I hope you understand what I meant