Giter Site home page Giter Site logo

j4k0xb / webcrack Goto Github PK

View Code? Open in Web Editor NEW
511.0 13.0 58.0 1.31 MB

Deobfuscate obfuscator.io, unminify and unpack bundled javascript

Home Page: https://webcrack.netlify.app

License: MIT License

JavaScript 18.38% TypeScript 81.22% CSS 0.14% HTML 0.27%
ast bundle debundle extract reverse-engineering unminify unpack webpack deobfuscation deobfuscator

webcrack's Introduction

Test npm license Netlify Status

webcrack

webcrack is a tool for reverse engineering javascript. It can deobfuscate obfuscator.io, unminify, transpile, and unpack webpack/browserify, to resemble the original source code as much as possible.

Try it in the online playground or view the documentation.

  • 🚀 Performance - Various optimizations to make it fast
  • 🛡️ Safety - Considers variable references and scope
  • 🔬 Auto-detection - Finds code patterns without needing a config
  • ✍🏻 Readability - Removes obfuscator/bundler artifacts
  • ⌨️ TypeScript - All code is written in TypeScript
  • 🧪 Tests - To make sure nothing breaks

Command Line Interface

npm install -g webcrack

Examples:

webcrack input.js
webcrack input.js > output.js
webcrack bundle.js -o output-dir

API

npm install webcrack

Examples:

import fs from 'fs';
import { webcrack } from 'webcrack';

const input = fs.readFileSync('bundle.js', 'utf8');

const result = await webcrack(input);
console.log(result.code);
console.log(result.bundle);
await result.save('output-dir');

webcrack's People

Contributors

dependabot[bot] avatar j4k0xb avatar kuizuo avatar milahu avatar sorte1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

webcrack's Issues

Unnecessary "Double-bang operator" cleaning

Example:

if (!!processedOrders[openOrder.orderId.toString()]) {
    return;
}
// ...

const orderBidsAsks = [...(bids ?? []), ...(asks ?? [])].filter(e => !!openOrdersMap.get(e.openOrdersAddress.toBase58()));

Cleaned (and also correct) example:

if (processedOrders[openOrder.orderId.toString()]) {
    return;
}
// ...

const orderBidsAsks = [...(bids ?? []), ...(asks ?? [])].filter(e => openOrdersMap.get(e.openOrdersAddress.toBase58()));

support decoder is FunctionExpression

function hi() {
  var _0x4c1b3b = _0x1b20;
  console['log'](_0x4c1b3b(0x0));
}

hi();

function _0x1b20(_0x107060, _0x1b2020) {
  var _0x4c3a62 = _0x1070();

  return _0x1b20 = function (_0x2a3d13, _0x5768cc) {
    _0x2a3d13 = _0x2a3d13 - 0x0;
    var _0x4e2495 = _0x4c3a62[_0x2a3d13];
    return _0x4e2495;
  }, _0x1b20(_0x107060, _0x1b2020);
}

function _0x1070() {
  var _0x349c11 = ['Hello\x20World!'];

  _0x1070 = function () {
    return _0x349c11;
  };

  return _0x1070();
}

The above code is generated by a obfuscator.

But when I changed the FunctionDeclaration with FunctionExpression of the decoder (_0x1b20) like this:

- function _0x1b20(_0x107060, _0x1b2020) {
+ var _0x1b20 = function (_0x107060, _0x1b2020) {
   // ...
}

At this time, deobfuscate won't work.

This is especially common in some of the obfuscated code I've seen. So I hope you will support this feature.

By the way, I read the source code and noticed that you commented TODO in the findDecoder to support this feature, but that was 8 months ago.

hardcoded React UMD global

The current Sketchy implementation only decompiles React JSX when the code utilizes the UMD global, which is not effective since the majority of React websites incorporate the library within their bundle.

To make the decompilation process more effective and adaptable to different React websites, I recommend a more dynamic approach by identifying the React library being used in the compiled code, instead of hardcoding the use of 'React'. This can possibly be achieved by finding the variable name assigned to the React library and using that in the matchers.

constMemberExpression(m.identifier('React'), 'createElement'),

constMemberExpression(m.identifier('React'), 'createElement'),

constMemberExpression(m.identifier('React'), 'Fragment'),

unexpected token

Describe the bug

image
basically that

Expected Behaviour

for it do just deobfuscate I guess?

Code

https://raw.githubusercontent.com/BotSolver/krunk/main/game_1_4.js

Logs

no logs, used site.

add smart-rename rule from wakaru

currently, webcrack produces code like

let { sin: k, cos: v, abs: w, log: N, floor: U, PI: A } = Math;

with the smart-rename rule of wakaru this becomes

let { sin, cos, abs, log, floor, PI } = Math;

Awesome project - looking for help?

Hello
I ve been using webcrack for some stuff the past week and it's an awesome tool, so i'd love to help maintain and grow it. Let me know if you're looking for help and we can discuss anytime.

connot resolve webpack bundle like no entry

Describe the bug

connot resolve webpack bundle like no entry

Expected Behaviour

unpack this bundle

Code

(()=>{
var __webpack_modules__ = {...};
var __webpack_module_cache__ = {};
  function __webpack_require__(e) {
    var t = __webpack_module_cache__[e];
    if (t !== undefined) {
      return t.exports;
    }
    var i = __webpack_module_cache__[e] = {
      exports: {}
    };
    __webpack_modules__[e].call(i.exports, i, i.exports, __webpack_require__);
    return i.exports;
  }
  __webpack_require__.d = (e, t) => {
    for (var i in t) {
      if (__webpack_require__.o(t, i) && !__webpack_require__.o(e, i)) {
        Object.defineProperty(e, i, {
          enumerable: true,
          get: t[i]
        });
      }
    }
  };
  __webpack_require__.o = (e, t) => Object.prototype.hasOwnProperty.call(e, t);
  __webpack_require__.r = e => {
    if (typeof Symbol != "undefined" && Symbol.toStringTag) {
      Object.defineProperty(e, Symbol.toStringTag, {
        value: "Module"
      });
    }
    Object.defineProperty(e, "__esModule", {
      value: true
    });
  };
  var __webpack_exports__ = {};
  (() => {
    "use strict";

    const e = __webpack_require__(9896);
    const t = __webpack_require__(1914);
    const i = __webpack_require__(1441);
    const n = __webpack_require__(4718);
    const s = __webpack_require__(3890);
    const a = __webpack_require__(6324);
    const r = __webpack_require__(5026);
    const o = __webpack_require__(2020);
    const l = __webpack_require__(2966);
    const h = __webpack_require__(2542);
    global.ShaderEditor = (0, e.createEditor)(class {
      constructor() {
        Editor.typeRegistry.addTypes(l.allTypes);
      }
      async onBeginPlay(e) {
        Editor.createAppMenu((0, o.createAppMenuTemplate)());
        Editor.setWindowTitle("Shader Blueprint");
        Editor.createHotkeyManager();
        await Editor.connectAssetDb();
        await Editor.connectShaderDb();
        let i = await gui.UIPackage.createWidget("~/ui/editor/MainView2.widget");
        this._mainView = i;
        i.name = "MainView";
        i.setSize(gui.GRoot.inst.width, gui.GRoot.inst.height);
        i.addRelation(gui.GRoot.inst, gui.RelationType.Size);
        gui.GRoot.inst.addChild(i);
        this._tabBar = new r.FileTabBar(i);
        this._tabBar.onTabSelected = (...e) => this.onTabSelected(...e);
        this._tabBar.onTabWillClose = (...e) => this.onTabWillClose(...e);
        this._tabBar.onTabSave = (...e) => this.onTabSave(...e);
        this.previewFrame = new s.WebIFrame();
        this.previewFrame.port.handle("materialPreviewReady", () => {
          this.previewFrame.ready = true;
          if (t.ScenePanel.ins) {
            t.ScenePanel.ins.autoBuild(0);
          }
        });
        this.previewFrame.load("preview.html");
        let n = i.getChild("panelManager", gui.Shape);
        Editor.createPanelManager({
          filePath: "shaderEditorLayout.json",
          layouts: {
            default: {
              mainPanelId: "ScenePanel"
            }
          }
        }, n);
        await this.setupPanels();
        Editor.panelManager.loadLayout();
        Editor.panelManager.start();
        if (e) {
          await this.onOpenFile(e);
        } else {
          await this.restoreTabs();
        }
      }
      async onBeforeEndPlay() {
        return this._tabBar.queryToCloseAllTabs(true);
      }
      async onEndPlay() {
        Editor.setHistoryDocuments(this._tabBar.getTabs().map(e => e.assetId || ""), this._tabBar.selectedIndex);
      }
      async onOpenFile(e) {
        let t = await Editor.assetDb.getAsset(e);
        if (t) {
          this.openFileInside(t, true);
        }
      }
      async restoreTabs() {
        let {
          files: e,
          active: t
        } = Editor.getHistoryDocuments();
        for (let t of e) {
          try {
            let e = await Editor.assetDb.getAsset(t);
            if (e) {
              await this.openFileInside(e, false);
            }
          } catch (e) {}
        }
        if (t < this._tabBar.tabCount) {
          this._tabBar.selectedTab = this._tabBar.getTabAt(t);
        }
      }
      async openFileInside(e, t) {
        let i;
        if ((i = this._tabBar.findTab(t => t.assetId == e.id)) == null) {
          i = {
            id: (0, h.genShortId2)(),
            assetId: e.id,
            fileType: e.type,
            isModified: false
          };
          this._tabBar.addTab(i, null, t);
        } else if (t) {
          this._tabBar.selectedTab = i;
        }
      }
      async _save(e, i, n) {
        t.ScenePanel.ins.save();
        return true;
      }
      async save(e) {
        return this._save(null, false, e);
      }
      async saveAs() {
        return this._save(null, true);
      }
      async saveAll() {
        for (let e of this._tabBar.getTabs()) {
          if (!(await this._save(e))) {
            break;
          }
        }
      }
      queryToSaveAll() {
        return this._tabBar.queryToSaveAllTabs();
      }
      async setupPanels() {
        let e = Editor.panelManager;
        await Promise.all([e.registerPanel("BlueprintUniformPanel", a.BlueprintUniformPanel, {
          title: "Params",
          icon: "~/ui/type-icons/panel/inspector.svg",
          stretchPriorityX: -1,
          stretchPriorityY: 100,
          location: "left"
        }), e.registerPanel("ScenePanel", t.ScenePanel, {
          title: "",
          icon: "~/ui/type-icons/panel/scene.svg",
          stretchPriorityX: 1,
          stretchPriorityY: 1
        }), e.registerPanel("BlueprintInspectorPanel", i.BlueprintInspectorPanel, {
          title: "Inspector",
          icon: "~/ui/type-icons/panel/inspector.svg",
          stretchPriorityX: -1,
          stretchPriorityY: 100,
          location: "left"
        }), e.registerPanel("BlueprintPreviewPanel", n.BlueprintPreviewPanel, {
          title: "Preview",
          icon: "~/ui/type-icons/panel/preview.svg",
          stretchPriorityX: -1,
          stretchPriorityY: 100,
          location: "left"
        })]);
      }
      async onTabWillClose(e, t) {
        let i = e.length == this._tabBar.tabCount;
        if (t) {
          for (let t of e) {
            if (t.isModified && !(await this._save(t))) {
              return;
            }
          }
        }
        let n = [];
        for (let t of e) {
          this._tabBar.removeTab(t.id);
        }
        if (n.length > 0) {
          await Promise.all(n);
        }
        if (i) {
          Editor.shutdown();
        }
      }
      async onTabSave(e) {
        for (let t of e) {
          t.isModified;
        }
      }
      async onTabSelected(e) {
        t.ScenePanel.ins.openFile(this._tabBar, e, e.assetId);
      }
    });
  })();

})()

Logs

No response

improve require/import/export support in unminify

Was testing the new v2.11.0 web IDE update today and found some areas that unminify could be further improved.

This issue is about the require/import/export syntax after unminification.

You can get the minimised code that I am testing against here (Ref, that repo also has lots of other example code if you want to test further)

Webcrack

Loading the above minimised code in the webcrack web IDE (Ref) with the following config:

image

In the unminified output, you can see an example of the current require/import/export in 180.js:

(Note: I also used this same file as my example for the JSX unminify in #10 (comment), but the specifics in this issue are different, despite it using the same source)

(Sidenote: I love the /*webcrack:missing*/ annotation here!)

180.js

require.d(exports, {
  Z: function () {
    return a;
  }
});
var r = require( /*webcrack:missing*/"./35250.js");
function a(e) {
  var t;
  var n = e.url;
  var a = e.size;
  var i = a === undefined ? 16 : a;
  var s = e.className;
  try {
    t = new URL(n);
  } catch (e) {
    console.error(e);
    return null;
  }
  return (0, r.jsx)("img", {
    src: `https://icons.duckduckgo.com/ip3/${t.hostname}.ico`,
    alt: "Favicon",
    width: i,
    height: i,
    className: s
  });
}

Wakaru

Contrasting this against the unminified output from wakaru's web IDE (Ref) (which separates the 'unpack modules' and 'unminify' steps)

Unpacked module-180.js source:

var r = require(35250);
function a(e) {
  var t;
  var n = e.url;
  var a = e.size;
  var i = void 0 === a ? 16 : a;
  var s = e.className;
  try {
    t = new URL(n);
  } catch (e) {
    return console.error(e), null;
  }
  return (0, r.jsx)("img", {
    src: "https://icons.duckduckgo.com/ip3/".concat(t.hostname, ".ico"),
    alt: "Favicon",
    width: i,
    height: i,
    className: s,
  });
}

module.exports = {
  Z: a,
};

Transformed (unminified) module-180.js source:

const { jsx } = require(35250);

function a(e) {
  let t;

  const { url, size, className } = e;

  const i = size === undefined ? 16 : size;
  try {
    t = new URL(url);
  } catch (e) {
    console.error(e);
    return null;
  }
  return (
    <img
      src={`https://icons.duckduckgo.com/ip3/${t.hostname}.ico`}
      alt="Favicon"
      width={i}
      height={i}
      className={className}
    />
  );
}

export default {
  Z: a,
};

Cannot read properties of null (reading 'buildUndefinedNode')

Describe the bug

Just running webcrack on an index.js from webpack

Expected Behaviour

Shouldn't be an error

Code

/Users/matt/.nvm/versions/node/v16.18.1/lib/node_modules/webcrack/node_modules/@babel/types/lib/converters/gatherSequenceExpressions.js:55
    exprs.push(scope.buildUndefinedNode());
                     ^

TypeError: Cannot read properties of null (reading 'buildUndefinedNode')
    at gatherSequenceExpressions (/Users/matt/.nvm/versions/node/v16.18.1/lib/node_modules/webcrack/node_modules/@babel/types/lib/converters/gatherSequenceExpressions.js:55:22)
    at toSequenceExpression (/Users/matt/.nvm/versions/node/v16.18.1/lib/node_modules/webcrack/node_modules/@babel/types/lib/converters/toSequenceExpression.js:11:57)
    at NodePath.replaceExpressionWithStatements (/Users/matt/.nvm/versions/node/v16.18.1/lib/node_modules/webcrack/node_modules/@babel/traverse/lib/path/replacement.js:140:37)
    at NodePath.insertBefore (/Users/matt/.nvm/versions/node/v16.18.1/lib/node_modules/webcrack/node_modules/@babel/traverse/lib/path/modification.js:48:17)
    at Object.exit (file:///Users/matt/.nvm/versions/node/v16.18.1/lib/node_modules/webcrack/dist/cli.js:434:16)
    at NodePath._call (/Users/matt/.nvm/versions/node/v16.18.1/lib/node_modules/webcrack/node_modules/@babel/traverse/lib/path/context.js:45:20)
    at NodePath.call (/Users/matt/.nvm/versions/node/v16.18.1/lib/node_modules/webcrack/node_modules/@babel/traverse/lib/path/context.js:35:17)
    at NodePath.visit (/Users/matt/.nvm/versions/node/v16.18.1/lib/node_modules/webcrack/node_modules/@babel/traverse/lib/path/context.js:89:8)
    at TraversalContext.visitQueue (/Users/matt/.nvm/versions/node/v16.18.1/lib/node_modules/webcrack/node_modules/@babel/traverse/lib/context.js:86:16)
    at TraversalContext.visitSingle (/Users/matt/.nvm/versions/node/v16.18.1/lib/node_modules/webcrack/node_modules/@babel/traverse/lib/context.js:65:19)

Logs

No response

There are some js to c/wasm transpilers but:

          There are some js to c/wasm transpilers but:
  • they only supports a small subset of js
  • https://stackoverflow.com/a/5193132/4011614

    Very, very tricky --- Javascript is a heavily dynamic language where pretty much everything can be changed at run time: object properties, functions, types, etc.
    As such it maps very badly onto C. Any Javascript translator would have to be able to cope with such things, which means it would have to translate the Javascript into machine code at run-time - which makes it a JIT, which we're already using.

So a transpiler that supported every js feature would still be slower overall.

https://www.assemblyscript.org is very similar to js/ts but would also require rewriting or substantially modifying all libs, in which case using another language is most likely a better choice

Originally posted by @j4k0xb in #23 (comment)

found this:
https://www.wasm.builders/gunjan_0307/compiling-javascript-to-wasm-34lk

feature split variable declarations in for loop

The purpose of this feature is as follows.

before

for (var a = "0|1|2|3"["split"]("|"), i=0;;) {
  // ...
}

after

var a = "0|1|2|3"["split"]("|");
var i = 0;
for (;;) {
   // ...
}

I've come across a piece of obfuscated code in which the qt identifier is the decoder.
I think with this transform, the control-flow-switch can be handled better.

function l(n) {
    for (var t = qt, r = {
        WzHjn: t(1835) + "1",
        UwEQS: function (n, t, r) {
            return n(t, r)
        },
        CoZgR: function (n, t) {
            return n >>> t
        },
        TRZvx: function (n, t) {
            return n >>> t
        },
        XwGzX: function (n, t, r) {
            return n(t, r)
        },
        cVxKc: function (n, t) {
            return n >>> t
        },
        WvIaT: function (n, t, r) {
            return n(t, r)
        }
    }, e = r[t(1701)][t(601)]("|"), u = 0; ;) {
        switch (e[u++]) {
            case "0":
                n = r[t(369)](h, n, [0, r[t(598)](n[0], 1)]);
                continue;
            case "1":
                return n;
            case "2":
                n = r[t(369)](f, n, [4283543511, 3981806797]);
                continue;
            case "3":
                n = r[t(369)](h, n, [0, r[t(1320)](n[0], 1)]);
                continue;
            case "4":
                n = r[t(1475)](h, n, [0, r[t(2043)](n[0], 1)]);
                continue;
            case "5":
                n = r[t(1554)](f, n, [3301882366, 444984403]);
                continue
        }
        break
    }
}

At last, I tried to write a piece of visitor code, but I couldn't guarantee whether it was safe or not. This can cause variable names
to be duplicated. And the above code should run before split-variable-declarations

export default {
  name: 'forLoopHoist',
  visitor() {
    return {
      ForStatement: {
        exit(path) {
          if (t.isVariableDeclaration(path.node.init)) {
            path.insertBefore(path.node.init)

            path.node.init = null
          }
        },
      },
    }
  },
} satisfies Transform

How can I bundle the generated unpack files again?

i have a huge bundled js file, use this awesome tool i can get the unpack files, and do some rewrite in specific modules, after that, how can I bundle all the modules again.

Thanks a lot for your answer

Disable the syntax highlighter

Pasting 2-10MB minified JS file will likely hang the whole webcrack tab because of the highlighter taking so long to do syntax highlighting, please add option to disable it.

TypeError: Cannot read properties of undefined (reading 'isVariableDeclaration')

Error raised when deobfuscate main.js file.

main.zip

The console output:

$ webcrack -o crack app/main.js
  webcrack:transforms prepare: started +0ms
  webcrack:transforms prepare: finished with 23537 changes +5s
  webcrack:transforms deobfuscate: started +1ms
  webcrack:deobfuscate String Array: no +0ms
  webcrack:transforms deobfuscate: finished with 0 changes +4s
  webcrack:transforms transpile, unminify: started +0ms
  webcrack:transforms transpile, unminify: finished with 215971 changes +7s
  webcrack:transforms self-defending, debug-protection, jsx, jsx-new: started +1ms
  webcrack:transforms self-defending, debug-protection, jsx, jsx-new: finished with 0 changes +1s
  webcrack:transforms merge-object-assignments: started +1ms
E:\.nvm\versions\node\v20.11.1\bin\node_modules\webcrack\node_modules\@babel\traverse\lib\scope\index.js:520
    if (path.isVariableDeclaration()) {
             ^

TypeError: Cannot read properties of undefined (reading 'isVariableDeclaration')
    at Scope.registerBinding (E:\.nvm\versions\node\v20.11.1\bin\node_modules\webcrack\node_modules\@babel\traverse\lib\scope\index.js:520:14)
    at Object.Function (E:\.nvm\versions\node\v20.11.1\bin\node_modules\webcrack\node_modules\@babel\traverse\lib\scope\index.js:267:18)
    at NodePath._call (E:\.nvm\versions\node\v20.11.1\bin\node_modules\webcrack\node_modules\@babel\traverse\lib\path\context.js:46:20)
    at NodePath.call (E:\.nvm\versions\node\v20.11.1\bin\node_modules\webcrack\node_modules\@babel\traverse\lib\path\context.js:36:17)
    at NodePath.visit (E:\.nvm\versions\node\v20.11.1\bin\node_modules\webcrack\node_modules\@babel\traverse\lib\path\context.js:82:31)
    at TraversalContext.visitQueue (E:\.nvm\versions\node\v20.11.1\bin\node_modules\webcrack\node_modules\@babel\traverse\lib\context.js:86:16)
    at TraversalContext.visitSingle (E:\.nvm\versions\node\v20.11.1\bin\node_modules\webcrack\node_modules\@babel\traverse\lib\context.js:65:19)
    at TraversalContext.visit (E:\.nvm\versions\node\v20.11.1\bin\node_modules\webcrack\node_modules\@babel\traverse\lib\context.js:109:19)
    at traverseNode (E:\.nvm\versions\node\v20.11.1\bin\node_modules\webcrack\node_modules\@babel\traverse\lib\traverse-node.js:22:17)
    at NodePath.visit (E:\.nvm\versions\node\v20.11.1\bin\node_modules\webcrack\node_modules\@babel\traverse\lib\path\context.js:88:52)

Node.js v20.11.1

pnpm install: warning: Failed to create bin at apps/playground/node_modules/.bin/webcrack

Describe the bug

when running pnpm install in the repo root
pnpm is trying to install packages/webcrack to apps/playground
but packages/webcrack is not-yet built at this point

pnpm version 8.15.2
webcrack version e6b584f

git clone --depth=1 https://github.com/j4k0xb/webcrack
cd webcrack
pnpm install

WARN  Failed to create bin at apps/playground/node_modules/.bin/webcrack. ENOENT: no such file or directory, open 'packages/webcrack/dist/cli.js'

WARN  Failed to create bin at apps/playground/node_modules/.bin/webcrack. ENOENT: no such file or directory, open 'apps/playground/node_modules/webcrack/dist/cli.js'

workaround

pnpm install --ignore-scripts
npm run build

possible solution

create a wrapper packages/webcrack/src/cli-wrapper.js for packages/webcrack/dist/cli.js

commit 70500eb14a9c9f1660caad0596cff288ce102ff3
Author: Milan Hauth <[email protected]>
Date:   Tue Feb 13 14:41:48 2024 +0100

    use bin wrapper

diff --git a/packages/webcrack/package.json b/packages/webcrack/package.json
index f5816c0..6db5072 100644
--- a/packages/webcrack/package.json
+++ b/packages/webcrack/package.json
@@ -7,7 +7,7 @@
   "type": "module",
   "main": "dist/index.js",
   "types": "dist/index.d.ts",
-  "bin": "dist/cli.js",
+  "bin": "src/cli-wrapper.js",
   "files": [
     "dist"
   ],
diff --git a/packages/webcrack/src/cli-wrapper.js b/packages/webcrack/src/cli-wrapper.js
new file mode 100755
index 0000000..dc4b410
--- /dev/null
+++ b/packages/webcrack/src/cli-wrapper.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+import "../dist/cli.js"

Expected Behaviour

no warnings

Code

no

Logs

No response

Cannot move to file clicked in playground

Describe the bug

When I tried playing with the playground, it successfully generated some modules. But when I clicked on files on the left panel, the playground failed to navigate / open the file. I got stuck on the input file.

System: Windows 11
Browser: Chrome 120.0.6099.129

Expected Behaviour

Can click and see the generated file.

Code

NA

Logs

image

true it could result in more performance (except python lol) but afaik these languages don't have similar libs as I'm currently using (babel, isolated-vm, codemod matcher), and implementing them from scratch would be too much effort to be worth it

          true it could result in more performance (except python lol) but afaik these languages don't have similar libs as I'm currently using (babel, isolated-vm, codemod matcher), and implementing them from scratch would be too much effort to be worth it

swc is probably the closest thing to babel but still too limited:

Originally posted by @j4k0xb in #22 (comment)
you could also transpile the libs if possible

add Chrome DevTools extension that allows the web IDE to be used within DevTools

First off, I LOVE the new v2.11.0 update, and the changes to the web IDE to use monaco to support 'references', 'go to declaration', etc.

This issue is about an idea I've had and wanted to work on myself for a while, but haven't got around to it yet. Often when exploring web apps, I make pretty heavy use of Chrome DevTools' 'Search' / 'Sources' / 'Network' / etc tabs, the debugger, and the console / utilities APIs. While there have been some nice improvements to the 'Sources' tab over the years (pretty printing, syntax highlighting, code folding, etc); one area I have really wished it was able to support for a long time now is 'references' / 'go to definition' / similar.

A thought I had in this space is that, while I obviously can't outright replace the 'Sources' tab (which I believe is based on CodeMirror), it should be possible to create a Chrome DevTools Extension that adds a new tab/panel that does similar to the current 'Sources' tab, but using monaco as it's base, and enabling features like 'references' / 'go to definition' / etc within that.

Useful Chrome Extension APIs

Overview of extending DevTools:

Some of the Chrome Extension API's that would be useful/enable this:

Then there are also all of the 'standard' Chrome Extension APIs as well, which can do a lot of cool stuff:

A few of which could be useful for this feature:

And some that are a little more esoteric, but might still be interesting/useful:


Edit: This is also captured on the following gist for posterity, and that will likely be where I capture any future notes about my own explorations of this:

I just need help, it's removing a defined value from this code.

Describe the bug

I press deobfuscate and everything is fine, but if I put the code with the rest of the files it says this

background-wrapper.js:1 ReferenceError: _0x541988 is not defined
at Object.S (background.bundle.js:1:152)
at new It (background.bundle.js:1:338930)
at background.bundle.js:1:930915
at background.bundle.js:1:930940
at background.bundle.js:1:931274
at background.bundle.js:1:934771
at background.bundle.js:1:934775

I don't mean to be annoying if anything so I apologize, just trying to get something done

Expected Behaviour

I expect to keep the value defined but it seems to remove it, breaking the whole code for the check

Code

https://cdn.discordapp.com/attachments/1139534194402414592/1142290059559714816/0mY0xmK.js

Logs

background-wrapper.js:1 ReferenceError: _0x541988 is not defined
    at Object.S (background.bundle.js:1:152)
    at new It (background.bundle.js:1:338930)
    at background.bundle.js:1:930915
    at background.bundle.js:1:930940
    at background.bundle.js:1:931274
    at background.bundle.js:1:934771
    at background.bundle.js:1:934775
    at background-wrapper.js:1:5

Webcrack doesn't fully remove deadcode

This code obfuscated with obfuscator.io (high):

function hi() {
  console.log("Hello World!");
}
hi();

Returns this when deobfuscated:

function a() {
  console.log("Hello World!");
}
a();
(function () {
  function a() {
    var a;
    try {
      a = Function("return (function() {}.constructor(\"return this\")( ));")();
    } catch (b) {
      a = window;
    }
    return a;
  }
  var c = a();
  c.setInterval(b, 4000);
})();

Support for Vercel

Error [ERR_REQUIRE_ESM]: require() of ES Module /var/task/node_modules/webcrack/dist/index.js from /var/task/api/unobf.js not supported.
Instead change the require of index.js in /var/task/api/unobf.js to a dynamic import() which is available in all CommonJS modules.

segmentation fault

Describe the bug

webcrack ~/index.js

Expected Behaviour

work

Code

https://gist.github.com/Geczy/a274e77ebd2969ed0e2e4d53c2730ef6

Logs

matt@pc:~$ webcrack ~/index.js
  webcrack:transforms prepare: started +0ms
  webcrack:transforms prepare: finished with 13930 changes +4s
  webcrack:transforms deobfuscate: started +0ms
  webcrack:deobfuscate String Array: 14034 strings +0ms
  webcrack:deobfuscate String Array Rotate: yes +3ms
  webcrack:deobfuscate String Array Encodings: 1 +40ms
  webcrack:transforms inlineObjectProps: started +3s
  webcrack:transforms inlineObjectProps: finished with 0 changes +735ms
  webcrack:transforms inlineDecoderWrappers: started +0ms
  webcrack:transforms inlineDecoderWrappers: finished with 86937 changes +4s
  webcrack:transforms inlineDecodedStrings: started +21ms
Segmentation fault

unmangle import names via import path

input: mangled import names

import a from "/lib/some-lib-a/index.js"
import b from "/lib/some-lib-b/dist/index.js"
import c from "/lib/some-lib-c/dist/modules/some-module.js"

actual result: preserve the mangled import names a b c

expected result: unmangle import names via import path

import lib_someLibA from "/lib/some-lib-a/index.js";
import lib_someLibB_dist from "/lib/some-lib-b/dist/index.js";
import lib_someLibC_dist_modules_someModule from "/lib/some-lib-c/dist/modules/some-module.js";

Array unpooler

I need a transformer which would be able to simplify functions like this:
(varargs are empty btw)

function W8xps6(...ZQUk8w) {
  !((ZQUk8w.length = 0),
  (ZQUk8w[223] = 25),
  (ZQUk8w[ZQUk8w[ZQUk8w[ZQUk8w[223] + 198] - (ZQUk8w[223] - 223)] - 25] =
    xgCiq2(
      ZQUk8w[ZQUk8w[ZQUk8w[ZQUk8w[223] + 198] + 198] - (ZQUk8w[223] - 223)] -
        (ZQUk8w[
          ZQUk8w[223] - (ZQUk8w[223] - (ZQUk8w[223] - (ZQUk8w[223] - 223)))
        ] -
          (ZQUk8w[ZQUk8w[ZQUk8w[223] - (ZQUk8w[223] - 223)] + 198] + 7))
    )),
  (ZQUk8w[ZQUk8w[223] + 222] = ZQUk8w[ZQUk8w[223] - 23]),
  (ZQUk8w[ZQUk8w[223] - 24] = jZoT758(
    ZQUk8w[223] + (ZQUk8w[ZQUk8w[223] - (ZQUk8w[223] - 223)] - 19)
  )),
  (ZQUk8w[ZQUk8w[223] + 197] = ZQUk8w[223] + 75),
  (ZQUk8w[ZQUk8w[ZQUk8w[222] + 122] + 147] = jZoT758(30)),
  (ZQUk8w[ZQUk8w[223] + 198] = ZQUk8w[223] - (ZQUk8w[223] + 116)),
  (ZQUk8w[ZQUk8w[222] - (ZQUk8w[222] - 3)] = yvO5GCA(ZQUk8w[223] + 145)),
  (ZQUk8w[ZQUk8w[222] - 96] = jZoT758(27)),
  (ZQUk8w[ZQUk8w[ZQUk8w[223] + 339] + 121] = jZoT758(ZQUk8w[222] - 76)),
  (ZQUk8w[ZQUk8w[222] + 72] = ZQUk8w[5]),
  (ZQUk8w[ZQUk8w[ZQUk8w[223] + 339] - (ZQUk8w[222] - 222)] = jZoT758(23)),
  (ZQUk8w[ZQUk8w[222] - (ZQUk8w[223] + 209)] = yvO5GCA(22)),
  (ZQUk8w[ZQUk8w[222] - 92] = nPVOJ4v(
    VR7dvi +
      ZQUk8w[
        ZQUk8w[ZQUk8w[223] - (ZQUk8w[223] - 222)] -
          (ZQUk8w[223] - (ZQUk8w[ZQUk8w[223] + 339] - 93))
      ] +
      ZQUk8w[
        ZQUk8w[ZQUk8w[222] + 122] -
          (ZQUk8w[222] -
            (ZQUk8w[222] - (ZQUk8w[222] - (ZQUk8w[222] - (ZQUk8w[222] - 6)))))
      ] +
      ZQUk8w[ZQUk8w[223] - (ZQUk8w[ZQUk8w[222] - (ZQUk8w[223] - 6)] - 388)] +
      DIdw2v5 +
      '5X',
    UhTH66F +
      ZQUk8w[ZQUk8w[ZQUk8w[222] + 122] - 96] +
      pcaDZd +
      ZQUk8w[
        ZQUk8w[ZQUk8w[222] + 123] +
          (ZQUk8w[ZQUk8w[222] - (ZQUk8w[223] - 7)] - (ZQUk8w[223] - 119))
      ] +
      ZQUk8w[ZQUk8w[222] + (ZQUk8w[222] + 47)],
    ZQUk8w[1],
    ZQUk8w[ZQUk8w[ZQUk8w[ZQUk8w[222] + 122] + 123] + 116] + fWAd1b + Ke3skc
  )),
  j7ibOsb(ZQUk8w[ZQUk8w[223] + 124]))
}

TypeError: Cannot read properties of undefined (reading 'path')

Describe the bug

While using the CLI or the npm package, i've ran into some issue trying to deobfuscate some source code.

it throws the following error:
TypeError: Cannot read properties of undefined (reading 'path')

mangling this file also seems to be an issue.

TypeError: Cannot read properties of undefined (reading 'add')
same error as in #41

let code = fs.readFileSync('source.js', 'utf8');

    webcrack(code, {
        unminify: true,
       //mangle: true,
        onProgress: progress => {
            console.log('Progress:', progress);
        },
        // mangle: true,
    }).then(result => {
        console.log(result);
    });

source.zip

Expected Behaviour

i would have expected the npm package and the cli to have deobfuscated and mangled without issues.

Code

too long... file is included in source.zip

Logs

Progress: 0
progress: 12.5
Progress: 25
Progress: 37.5
Progress: 50
Progress: 62.5
Progress: 75
Progress: 87.5

TypeError: Cannot read properties of undefined (reading 'path')
    at file:///home/sorte/projects/Bot/ignore/node_modules/.pnpm/[email protected]/node_modules/webcrack/dist/index.js:3600:26
    at Array.forEach (<anonymous>)TypeError: Cannot read properties of undefined (reading 'path')
    at file:///home/sorte/projects/test/node_modules/.pnpm/[email protected]/node_modules/webcrack/dist/index.js:3600:26
    at Array.forEach (<anonymous>)
    at ImportExportManager.insertImportsAndExports (file:///home/sorte/projects/test/node_modules/.pnpm/[email protected]/node_modules/webcrack/dist/index.js:3584:22)
    at new WebpackModule (file:///home/sorte/projects/test/node_modules/.pnpm/[email protected]/node_modules/webcrack/dist/index.js:4197:31)
    at Object.CallExpression (file:///home/sorte/projects/test/node_modules/.pnpm/[email protected]/node_modules/webcrack/dist/index.js:4287:27)
    at NodePath._call (/home/sorte/projects/test/node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/path/context.js:46:20)
    at NodePath.call (/home/sorte/projects/test/node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/path/context.js:36:17)
    at NodePath.visit (/home/sorte/projects/test/node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/path/context.js:82:31)
    at TraversalContext.visitQueue (/home/sorte/projects/test/node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:86:16)
    at TraversalContext.visitSingle (/home/sorte/projects/test/node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:65:19)
    at ImportExportManager.insertImportsAndExports (file:///home/sorte/projects/Bot/ignore/node_modules/.pnpm/[email protected]/node_modules/webcrack/dist/index.js:3584:22)
    at new WebpackModule (file:///home/sorte/projects/Bot/ignore/node_modules/.pnpm/[email protected]/node_modules/webcrack/dist/index.js:4197:31)
    at Object.CallExpression (file:///home/sorte/projects/Bot/ignore/node_modules/.pnpm/[email protected]/node_modules/webcrack/dist/index.js:4287:27)
    at NodePath._call (/home/sorte/projects/Bot/ignore/node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/path/context.js:46:20)
    at NodePath.call (/home/sorte/projects/Bot/ignore/node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/path/context.js:36:17)
    at NodePath.visit (/home/sorte/projects/Bot/ignore/node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/path/context.js:82:31)
    at TraversalContext.visitQueue (/home/sorte/projects/Bot/ignore/node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:86:16)
    at TraversalContext.visitSingle (/home/sorte/projects/Bot/ignore/node_modules/.pnpm/@[email protected]/node_modules/@babel/traverse/lib/context.js:65:19)

support GopherJS bundles

cc // @vik0t0r FYI

See Also

prettify html and css strings in tagged template literals

currently, only the javascript code is pretty printed
it would be nice to also pretty print html-in-javascript and css-in-javascript strings

im afraid this would require dynamic analysis of the template tag functions

a cheap fix would be guessing string type from string content
= try to parse html, try to parse css, use what works

see also Template literals # Tagged templates

actual result: html and css strings are ugly long lines

class SomeElement extends HTMLElement {
  static #htmlNode = htmlNodeOfString` <template> <div id="container"> ... </div> </template> `;
  static #cssSheet = cssSheetOfString` :host { display: block; width: 100%; }`;
}

expected result: pretty print html and css strings

class SomeElement extends HTMLElement {
  static #htmlNode = htmlNodeOfString`
    <template>
      <div id="container">
        ...
      </div>
    </template>
  `;
  static #cssSheet= cssSheetOfString`
    :host {
      display: block;
      width: 100%;
    }
  `;
}
htmlNodeOfString is a html parser
let pn = document.createElement("template");

let htmlNodeOfString = (aC, ...aD) => {

  // build the string aF
  let aE = [];
  for (let aH = 0; aH < aC.length; aH += 1) {
    aE.push(aC[aH]);
    if (aD[aH] !== undefined) {
      aE.push(aD[aH]);
    }
  }
  let aF = aE.join("");

  // parse the string aF
  pn.innerHTML = aF;

  // return html node
  let aG = document.importNode(pn.content, true);
  if (aG.children.length === 1) {
    return aG.firstElementChild;
  } else {
    return aG;
  }
};
cssSheetOfString is a css parser
let cssSheetOfString = (aC, ...aD) => {

  // build the string aF
  let aE = [];
  for (let aH = 0; aH < aC.length; aH += 1) {
    aE.push(aC[aH]);
    if (aD[aH] !== undefined) {
      aE.push(aD[aH]);
    }
  }
  let aF = aE.join("");

  // parse the string aF
  let aG = new CSSStyleSheet();
  aG.replaceSync(aF);

  // return css stylesheet
  return aG;
};
workaround: grep and prettier: prettify html strings
#!/usr/bin/env bash

for js_path in elements/*/*.js; do

  echo "patching $js_path"

  js_code=$(<"$js_path")

  while read line; do
    html_code=$(echo "$line" | cut -d'`' -f2)
    html_code_start=${html_code:0:50}
    echo "  prettying ${html_code_start}..."
    html_code_new=$(
      echo
      echo "$html_code" |
        prettier --print-width 9999999999 --stdin-filepath x.html |
        sed 's/^/    /'
      echo
    )
    js_code=${js_code/"$html_code"/"$html_code_new"}
  done < <(echo "$js_code" | grep -E ' = htmlNodeOfString`.')

  echo -n "$js_code" >"$js_path"

done
workaround: grep and prettier: prettify css strings
#!/usr/bin/env bash

for js_path in elements/*/*.js; do

  echo "patching $js_path"

  js_code=$(<"$js_path")

  while read line; do
    css_code=$(echo "$line" | cut -d'`' -f2)
    css_code_start=${css_code:0:50}
    echo "  prettying ${css_code_start}..."
    css_code_new=$(
      echo
      echo "$css_code" |
        prettier --print-width 9999999999 --stdin-filepath x.css |
        sed 's/^/    /'
      echo
    )
    js_code=${js_code/"$css_code"/"$css_code_new"}
  done < <(echo "$js_code" | grep -E ' = cssSheetOfString`.')

  echo -n "$js_code" >"$js_path"

done
workaround breaks on nested strings

because '...' and "..." quotes cannot have multi-line strings

class SomeElement extends HTMLElement {
  static #htmlNode = htmlNodeOfString`
    <template>
      ${'<div id="container"> ... </div>'}
    </template>
  `;

rename short identifiers

is it possible to correct short variable names? for example with JADX, it has this option:

 --deobf                             - activate deobfuscation

which will turn short variables such as a into a1234 or something, for easier searching

Webcrack can't find string array

Describe the bug

When trying to deobfuscate this file, it seems like webcrack can't find the string array.

Expected Behaviour

I expect webcrack to find the string array.

Code

https://gist.github.com/g0dzcsgo/fa6e0402b54718a77656a28affd9c396

Logs

webcrack:transforms prepare: started +0ms
  webcrack:transforms prepare: finished with 4339 changes +461ms
  webcrack:transforms deobfuscate: started +0ms
  webcrack:deobfuscate String Array: no +0ms
  webcrack:transforms deobfuscate: finished with 0 changes +620ms
  webcrack:transforms transpile, unminify: started +0ms
  webcrack:transforms transpile, unminify: finished with 39226 changes +472ms
  webcrack:transforms self-defending, debug-protection, jsx, jsx-new: started +0ms
  webcrack:transforms self-defending, debug-protection, jsx, jsx-new: finished with 0 changes +139ms
  webcrack:transforms merge-object-assignments: started +1ms
  webcrack:transforms merge-object-assignments: finished with 2 changes +438ms

ERR_DLOPEN_FAILED

Nevermind. The issue is related with isolated-vm. I'm leaving a link in case anyone has a similar problem. laverdet/isolated-vm#249 (comment)

Describe the bug

Probably referring to DECODE_0 function that won't exists.

Expected Behaviour

It should have kept the string decoder function (which should be renamed to DECODE_0). But somehow it removes it (I guess).

Code

Logs

node:internal/modules/cjs/loader:1473
  return process.dlopen(module, path.toNamespacedPath(filename));
                 ^

Error: /home/io/.local/share/pnpm/global/5/.pnpm/[email protected]/node_modules/isolated-vm/out/isolated_vm.node: undefined 
symbol: _ZNK2v815ValueSerializer8Delegate20SupportsSharedValuesEv
    at Module._extensions..node (node:internal/modules/cjs/loader:1473:18)
    at Module.load (node:internal/modules/cjs/loader:1207:32)
    at Module._load (node:internal/modules/cjs/loader:1023:12)
    at Module.require (node:internal/modules/cjs/loader:1235:19)
    at require (node:internal/modules/helpers:176:18)
    at Object.<anonymous> (/home/io/.local/share/pnpm/global/5/.pnpm/[email protected]/node_modules/isolated-vm/isolated-vm.js:1:18)
    at Module._compile (node:internal/modules/cjs/loader:1376:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1435:10)
    at Module.load (node:internal/modules/cjs/loader:1207:32)
    at Module._load (node:internal/modules/cjs/loader:1023:12) {
  code: 'ERR_DLOPEN_FAILED'
}

Node.js v20.10.0

Require.D

Sorry if i am missinformed and could find the solution without opening an issue. I am also new to webpacks and the programming language overall.

I get this output on one of the files using the tool:

require.d(exports, {
  JF: function () {
    return c;
  },
  UZ: function () {
    return u;
  },
  jK: function () {
    return a;
  }
});
const n = "^https?:";
const i = "^wss?:";
function o(t) {
  const e = t.match(new RegExp(/^\w+:/, "gi"));
  if (e && e.length) {
    return e[0];
  }
}
function s(t, e) {
  const r = o(t);
  return typeof r !== "undefined" && new RegExp(e).test(r);
}
function a(t) {
  return s(t, n);
}
function u(t) {
  return s(t, i);
}
function c(t) {
  return new RegExp("wss?://localhost(:d{2,5})?").test(t);
}

require.d isn't defined, this should be the func to export the functions to call them later on. Is it generated on purpose? What should i change in order for it to not give me an error?

string splitting prevents the deobfuscator from minimising flattened code

String concatenations prevent the deobfuscator from realising it could simplify table references to be inlined
The below scripts have string arrays enabled (obfuscator.io stuff) since otherwise the deobfuscator wont even attempt to minify the table references
Flattened (deobfuscation is perfectly fine):

function main(){var _0x475a8b=_0x2f09;var _0x525a5a={'jzSnL':_0x475a8b(0x0),'kiVev':function(_0x1c95e2,_0x3dcadd){return _0x1c95e2+_0x3dcadd;}};console[_0x475a8b(0x1)](_0x525a5a[_0x475a8b(0x2)]);for(var _0x317c4c in[0x1,0x2,0x3,0x4]){console[_0x475a8b(0x1)](_0x525a5a[_0x475a8b(0x3)](_0x317c4c,0x5));}}main();function _0x2f09(_0x24c0b8,_0x2f0965){var _0x45ec21=_0x24c0();_0x2f09=function(_0x3ae4a4,_0x15035f){_0x3ae4a4=_0x3ae4a4-0x0;var _0x183ba9=_0x45ec21[_0x3ae4a4];return _0x183ba9;};return _0x2f09(_0x24c0b8,_0x2f0965);}function _0x24c0(){var _0x56f23c=['Running','log','jzSnL','kiVev'];_0x24c0=function(){return _0x56f23c;};return _0x24c0();}

Flattened + Split strings (doesn't deobfuscate well):

function _0x79aa(_0x52b12d,_0x79aa97){var _0x28c17a=_0x52b1();_0x79aa=function(_0x43b4f5,_0x533fd5){_0x43b4f5=_0x43b4f5-0x0;var _0x2d7d34=_0x28c17a[_0x43b4f5];return _0x2d7d34;};return _0x79aa(_0x52b12d,_0x79aa97);}function _0x52b1(){var _0x3ad461=['Runn','ing','log','EIrI','nFgH'];_0x52b1=function(){return _0x3ad461;};return _0x52b1();}function main(){var _0x37295b=_0x79aa;var _0x4fa635={'EIrIY':_0x37295b(0x0)+_0x37295b(0x1),'nFgHG':function(_0x4a2455,_0x1fc706){return _0x4a2455+_0x1fc706;}};console[_0x37295b(0x2)](_0x4fa635[_0x37295b(0x3)+'Y']);for(var _0x26704d in[0x1,0x2,0x3,0x4]){console[_0x37295b(0x2)](_0x4fa635[_0x37295b(0x4)+'G'](_0x26704d,0x5));}}main();

(I assume its essentially an order of operations issue. I'd attempted to look into this myself but couldn't get the build process to cooperate at all)

Unpack atob() and other common functions

I see some code that has statements like this:

const blah = atob("ZGVza3RvcA==")

Another common one is a "decryptor"/translation function like ROT13. It would be great if such cases could be extracted.

Reference Error

Describe the bug

says ReferenceError [Error]: DECODE_0 is not defined
at vm.js:4:9
at vm.js:5:9

Expected Behaviour

to deobfuscate the code with no issues.

Code

https://gofile.io/d/YzWlw7

Logs

webcrack:transforms prepare: started +0ms
  webcrack:transforms prepare: finished with 6722 changes +1s
  webcrack:transforms deobfuscate: started +1ms
  webcrack:deobfuscate String Array: yes +0ms
  webcrack:deobfuscate  - length: 4039 +1ms
  webcrack:deobfuscate  - function __STRING_ARRAY__(){var _0x57d5e9=["Server response not verifi … e9};return __STRING_ARRAY__()} +42ms
  webcrack:deobfuscate String Array Rotate: yes +4ms
  webcrack:deobfuscate  - (function(_0x41e1f8,_0x32060c){var _0x19df2c=a3_0x11e7;var _0x119013=_ … }}})(__STRING_ARRAY__,371229); +3ms
  webcrack:deobfuscate String Array Encodings: 1 +18ms
  webcrack:transforms objectLiterals: started +2s
  webcrack:transforms objectLiterals: finished with 0 changes +342ms
  webcrack:deobfuscate  - function __DECODE_0__(_0x54f465,_0x3665fb){var _0x521afc=__STRING_ARRA … CODE_0__(_0x54f465,_0x3665fb)} +342ms
  webcrack:transforms inlineDecoderWrappers: started +1ms
  webcrack:transforms inlineDecoderWrappers: finished with 25046 changes +1s
  webcrack:transforms inlineDecodedStrings: started +14ms

node:internal/process/promises:288
            triggerUncaughtException(err, true /* fromPromise */);
            ^
ReferenceError [Error]: __DECODE_0__ is not defined
    at vm.js:4:9
    at vm.js:5:9
    at Script.runInContext (node:vm:141:12)
    at VM.runScript (C:\Users\ladyg\AppData\Local\npm-cache\_npx\0b61241d7c17bcbb\node_modules\vm2\lib\vm.js:288:18)
    at C:\Users\ladyg\AppData\Local\npm-cache\_npx\0b61241d7c17bcbb\node_modules\vm2\lib\vm.js:512:16
    at timeout_bridge.js:1:1
    at Script.runInContext (node:vm:141:12)
    at doWithTimeout (C:\Users\ladyg\AppData\Local\npm-cache\_npx\0b61241d7c17bcbb\node_modules\vm2\lib\vm.js:135:29)
    at VM.run (C:\Users\ladyg\AppData\Local\npm-cache\_npx\0b61241d7c17bcbb\node_modules\vm2\lib\vm.js:511:10)
    at VMDecoder.sandbox (file:///C:/Users/ladyg/AppData/Local/npm-cache/_npx/0b61241d7c17bcbb/node_modules/webcrack/dist/index.js:981:15)

optimisation ideas

you should try porting this to one of the Lang's: fortran, go, c, rust, Python, c++

Cannot read properties of undefined (reading 'params')

Describe the bug

I can deobfuscate scripts successfully, but some like this give this error. How can we fix it?

Expected Behaviour

I want to deobfuscate it with webcrack.

Code

https://pastes.io/vh35utbtad

Logs

https://ibb.co/02HBZbh

Unable to match certain webpack bundles

Describe the bug

Could not recognize a certain webpack bundle.

Details

Webpack runtime requirements in the sample:

  • runtimeId = "__webpack_require__.j";
  • onChunksLoaded = "__webpack_require__.O";
  • nodeModuleDecorator = "__webpack_require__.nmd";
  • ensureChunkHandlers = "__webpack_require__.f";
  • hasOwnProperty = "__webpack_require__.o";
  • ensureChunk = "__webpack_require__.e";
  • exports = "__webpack_exports__";
  • getChunkScriptFilename = "__webpack_require__.u";
  • definePropertyGetters = "__webpack_require__.d";
  • compatGetDefaultExport = "__webpack_require__.n";
  • startup = "__webpack_require__.x";
  • moduleFactories = "__webpack_require__.m";

All wrapped in an IIFE.

Expected Behaviour

__webpack_require__ and __webpack_modules__ should be inferred from usage, and unpacked correctly

Code

https://fars.ee/FrBW.js

Logs

No response

possible memory leak

Describe the bug

It seems that the javascript GC doesn't clean up all the memory so after deobfuscating a large file I was left with 1200 MB of memory that wouldn't be cleaned up.

I'm running node v18.16.0.

Expected Behaviour

import path from 'path';
import { webcrack } from 'webcrack';
import fs from 'fs';

(async () => {
  let source = fs.readFileSync(path.join(__dirname, 'raw-game.js'), 'utf8');
  let deobfuscated = await webcrack(source, {
    maxIterations: 5,
  });
  fs.writeFileSync(path.join(__dirname, 'deobfuscated.js'), deobfuscated.code);
})();

Code

too long for pastebin.

https://cdn.discordapp.com/attachments/822252846027374634/1097603453007712367/raw-game.js

Logs

no logs

FeatReq | Extend webcrack instance

It'd be great If we can extend rules/scripts. Depends on choice, before or after deobfuscation.

For example:

import {
    webcrack
} from 'webcrack';

const result = await webcrack(input);
result.code.extend(async ({
    types
}) => {
    Identifier(path) {
        //....
    }
});
console.log(result.code)

Duplicated variable initialization when unminifying

Any variables initialized inside a for loop inside an inline if statement will be duplicated when unminifying.

for example:

if (1) for (a=1,b=2,c=3;a<10;a++){}

will turn into:

if (1) {
  a = 1;
  b = 2;
  c = 3;
  a = 1;
  b = 2;
  c = 3;
  for (; a < 10; a++) {}
}

__DECODE_0__

Describe the bug

Hello -_-

The javascript code is not completely DECODE_0 ;

I use the online version webcrack.netlify.app

Is there a difference between the online version and the version Command Line Interface ?
Can you correct the DECODE_0 error?

Edge chromiun last version
Windows 11 64 bit system, 24 ram

obfuscate.txt
Deobfuscate.txt
console log

Thank you for your help -__-

Expected Behaviour

DECODE_0

Code

small party example:
const originalQuerySelector = document[__DECODE_0__("0x245" - {
  e: 102
}.e, "e8^^") + __DECODE_0__("0x289" - {
  e: 102
}.e, "e8^^")];
document[__DECODE_0__("0x25a" - {
  e: 102
}.e, "6lfy") + __DECODE_0__("0x261" - {
  e: 102

Logs

No response

identifier mangler on default parameters

Describe the bug

When passing an identifier as a default parameter valuee, i doest work

the error seems to come from "babel-plugin-minify-mangle-names/lib/scope-tracker.js"
line 47

image

Expected Behaviour

function a(a, b = 0, c = a, d = 30) {
  return a;
}

Code

function func(adad, arg2 = 0, arg3 = adad, arg4 = 30) {
  return arg1;
}

or 

```js 
let adad = 1
function func(arg1, arg2 = 0, arg3 = adad, arg4 = 30) {
  return arg1;
}


### Logs

```Text
TypeError: Cannot read properties of undefined (reading 'add')
    at ScopeTracker.addReference (/home/sorte/.npm/_npx/6da011cd7208f74f/node_modules/babel-plugin-minify-mangle-names/lib/scope-tracker.js:47:34)
    at ReferencedIdentifier (/home/sorte/.npm/_npx/6da011cd7208f74f/node_modules/babel-plugin-minify-mangle-names/lib/index.js:202:26)
    at newFn (/home/sorte/.npm/_npx/6da011cd7208f74f/node_modules/@babel/traverse/lib/visitors.js:195:17)
    at bfsTraverse (/home/sorte/.npm/_npx/6da011cd7208f74f/node_modules/babel-plugin-minify-mangle-names/lib/bfs-traverse.js:38:43)
    at Mangler.collect (/home/sorte/.npm/_npx/6da011cd7208f74f/node_modules/babel-plugin-minify-mangle-names/lib/index.js:235:7)
    at Mangler.run (/home/sorte/.npm/_npx/6da011cd7208f74f/node_modules/babel-plugin-minify-mangle-names/lib/index.js:60:12)
    at Object.exit (/home/sorte/.npm/_npx/6da011cd7208f74f/node_modules/babel-plugin-minify-mangle-names/lib/index.js:546:19)
    at NodePath._call (/home/sorte/.npm/_npx/6da011cd7208f74f/node_modules/@babel/traverse/lib/path/context.js:46:20)
    at NodePath.call (/home/sorte/.npm/_npx/6da011cd7208f74f/node_modules/@babel/traverse/lib/path/context.js:36:17)
    at NodePath.visit (/home/sorte/.npm/_npx/6da011cd7208f74f/node_modules/@babel/traverse/lib/path/context.js:90:8)

Node.js v18.16.0

(0, fn)(...args) type of calls

Is there any particular reason to not replace calls like (0, fn)(...args) to just fn(...args)? Also, would be great to know in which cases webpack does this kind of transformation if anyone knows...

Webcrack can't find string array

Describe the bug

It cant find the string array

Expected Behaviour

Well I expect it to decrypt ofcourse, the thing I am decrypting has multiple files named index with added letters/numbers and this is the only file that didnt decrypt while the other files in the same assets folder decrypted fine.

I had to put the file on gist since I couldn't fit it into the code block on here, or pastebin/hastebin.

As you can see below in the code, the string array is the very first thing in the code block.

Code

https://gist.github.com/g0dzcsgo/3728fd36c4a4a7c5af7d0db30c9a21db

Logs

webcrack index-4d2e6cae.js > output.js
  webcrack:transforms prepare: started +0ms
  webcrack:transforms prepare: finished with 3119 changes +303ms
  webcrack:transforms deobfuscate: started +0ms
  webcrack:deobfuscate String Array: no +0ms
  webcrack:transforms deobfuscate: finished with 0 changes +539ms
  webcrack:transforms unminify: started +0ms
  webcrack:transforms unminify: finished with 35255 changes +360ms
  webcrack:transforms selfDefending, debugProtection, jsx: started +1ms
  webcrack:transforms selfDefending, debugProtection, jsx: finished with 0 changes +108ms

Now I know this is getting annoying, but when I deobfuscate it completely breaks this code.

Describe the bug

Now I know this is getting annoying, but when I deobfuscate it completely breaks this code, that is suppose to support an html file but it only shows a white page now.

Expected Behaviour

deobfuscate without breaking it? I don't know exactly what's being removed, it's some value again

Code

https://cdn.discordapp.com/attachments/1139534194402414592/1142441118085152829/HoszeQA.js

Logs

here's the only log of an error.

Uncaught SyntaxError: Invalid or unexpected token options.bundle.js:23754

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.