js-confuser icon indicating copy to clipboard operation
js-confuser copied to clipboard

We can store code in comments

Open doctor8296 opened this issue 1 year ago • 10 comments

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

doctor8296 avatar Nov 07 '24 12:11 doctor8296

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)

MichaelXF avatar Nov 09 '24 03:11 MichaelXF

@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?

doctor8296 avatar Nov 10 '24 16:11 doctor8296

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 avatar Nov 10 '24 18:11 MichaelXF

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.

MichaelXF avatar Nov 10 '24 18:11 MichaelXF

@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

doctor8296 avatar Nov 10 '24 19:11 doctor8296

Maybe a little out of topic but maybe something unique can be implemented by using HTML comments in javascript which everyone seems to forget about:

function test()
{
  console.log(`Hello World`);
<!-- hello this is still valid
}

test();

Siyabent avatar Nov 26 '24 13:11 Siyabent

@Siyabent

  1. WTF
  2. Doesn't actually matter

obfuscator is public, so this is easily reversable, unless we don't have some kind of unreversable changes

doctor8296 avatar Nov 26 '24 15:11 doctor8296

Maybe a little out of topic but maybe something unique can be implemented by using HTML comments in javascript which everyone seems to forget about:

Only works in browsers but this is pretty cool.

obfuscator is public, so this is easily reversable, unless we don't have some kind of unreversable changes

This is true but I don't think there are any real 'unreversable changes', unless you have some concept? Even closed source obfuscators can't have something unreversable.

MichaelXF avatar Dec 04 '24 00:12 MichaelXF

closed source obfuscators can't have something unreversable

Well, when you have opened source that means you know EXACTLY what replaces with what, there fore it can be done extrimely easily. With closed source it is not the case.

doctor8296 avatar Dec 27 '24 10:12 doctor8296

Only works in browsers but this is pretty cool.

also in node (except for modules). its actually part of the js spec for some reason

j4k0xb avatar Jan 02 '25 17:01 j4k0xb