MichaelXF / js-confuser

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

Error on class static field #116

Closed fgeorges closed 1 month ago

fgeorges commented 1 year ago

Describe the bug:

When the code to confuse contains a class with a static field, an error is thrown and code generation does not complete.

Config and Small code sample

Repro:

require("js-confuser").obfuscate(`
  class C {
    static v = 42;
  }
`, {
  target: "node",
  preset: "low",
}).then(obfuscated => {
  console.log(obfuscated)
})

Expected behavior

This example should pass and generate the corresponding, confused code.

Actual behavior

It throws an error:

xxx/node_modules/escodegen/escodegen.js:2525
        result = this[type](expr, precedence, flags);
                           ^

TypeError: this[type] is not a function
    at CodeGenerator.generateExpression (xxx/node_modules/escodegen/escodegen.js:2525:28)
    at xxx/node_modules/escodegen/escodegen.js:1133:38
    at withIndent (xxx/node_modules/escodegen/escodegen.js:581:9)
    at CodeGenerator.ClassBody (xxx/node_modules/escodegen/escodegen.js:1128:13)
    at CodeGenerator.generateStatement (xxx/node_modules/escodegen/escodegen.js:2538:33)
    at CodeGenerator.ClassDeclaration (xxx/node_modules/escodegen/escodegen.js:1159:30)
    at CodeGenerator.generateStatement xxx/node_modules/escodegen/escodegen.js:2538:33)
    at CodeGenerator.Program (xxx/node_modules/escodegen/escodegen.js:1718:43)
    at CodeGenerator.generateStatement (xxx/node_modules/escodegen/escodegen.js:2538:33)
    at generateInternal (xxx/node_modules/escodegen/escodegen.js:2559:28)

Additional context

It seems that in CodeGenerator.prototype.generateExpression(), the expression this[type] is undefined when type is PropertyDefinition.

j4k0xb commented 12 months ago

you can work around it with the es5 option

https://github.com/estools/escodegen/issues/443, https://github.com/estools/escodegen/pull/438 but it would be a good idea to switch to a more maintained escodegen fork or different lib (maybe https://github.com/davidbonnet/astring)

fgeorges commented 12 months ago

Thank you, @j4k0xb, using es5: true works!

For the suggestions about escodegen and/or astring, is it rather for @MichaelXF, or is it possible to change the generation lib by configuration also?

j4k0xb commented 12 months ago

for michael

fgeorges commented 12 months ago

Thank you! Just for the record, I have another issue, when I use es5. Repro code:

const code = `
function f() {}
() => { f(); };
`;

const options = {
    target: 'node',
    preset: 'low',
    es5: true,
};

require('js-confuser')
    .obfuscate(code, options)
    .then(t => console.log(t))

When executed, I get the following error (sometimes, not all the time, but I'd say above 50%):

node:internal/process/promises:288
            triggerUncaughtException(err, true / * fromPromise * /);
            ^

AssertionError [ERR_ASSERTION]: Should be a BlockStatement
    at /xxx/node_modules/js-confuser/dist/transforms/es5/es5.js:84:22
    at walk (/xxx/node_modules/js-confuser/dist/traverse.js:76:7)
    at walk (/xxx/node_modules/js-confuser/dist/traverse.js:63:15)
    at walk (/xxx/node_modules/js-confuser/dist/traverse.js:54:13)
    at walk (/xxx/node_modules/js-confuser/dist/traverse.js:63:15)
    at traverse (/xxx/node_modules/js-confuser/dist/traverse.js:97:3)
    at AntiArrowFunction.apply (/xxx/node_modules/js-confuser/dist/transforms/transform.js:136:27)
    at /xxx/node_modules/js-confuser/dist/transforms/transform.js:131:32
    at Array.forEach (<anonymous>)
    at ES5.apply (/xxx/node_modules/js-confuser/dist/transforms/transform.js:131:17) {
  generatedMessage: false,
  code: 'ERR_ASSERTION',
  actual: false,
  expected: true,
  operator: '=='
}

Node.js v18.18.2

When it fails, it is indeed not a BlockStatement, but instead a SequenceExpression.

If I change the test code from:

function f() {}
() => { f(); };

to:

function f() {}
() => {
    const f = f;
    f();
};

then it never fails anymore.

Just in case it can help if/when testing other libs.

j4k0xb commented 12 months ago

minify runs before es5 and theyre kinda incompatible đŸ¤”

https://github.com/MichaelXF/js-confuser/blob/b1fcb1d05b280cf9acc78889a51e7be278be2443/src/transforms/minify.ts#L339 https://github.com/MichaelXF/js-confuser/blob/b1fcb1d05b280cf9acc78889a51e7be278be2443/src/transforms/es5/es5.ts#L73

MichaelXF commented 1 month ago

Fixed in 2.0 (Currently 2.0.0-alpha.2). The 2.0 version nows uses Babel's parser and generator and is more suited for modern JavaScript syntax.

The ES5 option is removed in 2.0 - Babel implementation is more reliable