Skip to content

Releases: j4k0xb/webcrack

v2.15.0

05 Dec 19:43
Compare
Choose a tag to compare

General

  • CommonJS support: now require("webcrack") also works without errors

Deobfuscate

  • Evaluate atob, unescape, decodeURI and decodeURIComponent calls (#53)
  • Inline variable with multiple assignments (#121)
  • Log original string array name, length and decoder function names:
    image
  • Detect arrow-function iife (#127)
  • Fixed a bug where inlining string arrays and merging strings could mess them up
  • Fixed a bug where not all decoder aliases were detected (#119)

Playground

  • Open file from URL:
    image
  • Show syntax error alerts with line/col:
    image

v2.14.1

14 Aug 16:50
v2.14.1
Compare
Choose a tag to compare

Security

  • Fixed an arbitrary file write vulnerability: GHSA-ccqh-278p-xq6w
    Who's affected: Windows users which run the CLI with --output or (await webcrack(input)).save(dir) in JS
    Credits to @SteakEnthusiast for finding it

Unminify

  • Fixed a Maximum call stack size exceeded error on some comparisons (NaN == NaN)

v2.14.0

04 Aug 01:21
v2.14.0
Compare
Choose a tag to compare

Unminify

  • No longer extract sequence from while (a(), b()) c();
  • No longer invert relational operators (!(a > b); -> a <= b) due to breaking with NaN
  • Faster unminify (mainly string merging and numeric expressions)
  • Remove double negations: if (!!a) b(); -> if (a) b(); in if, ternary, array.filter
  • Extract sequence from for-of: for (let value of (a = 1, array)) {} -> a = 1; for (let value of array) {}
  • Mangle: names are inferred based on type (variable, function, parameter, class) and some expressions:
var iîiíiîï = exports;
function iìíïîíï(iïîiïîï, iìíìïîî, iìiiïiî) {
  var iïíïíiî = Array(Math.max(iïîiïîï.bitLength(), iìiiïiî) + 1);
  iïíïíiî.fill(0);
  var iiïiïîï = 1 << iìíìïîî + 1;
  var iìîíiîí = iïîiïîï.clone();

->

var vExports = exports;
function f(p, p2, p3) {
  var vArray = Array(Math.max(p.bitLength(), p3) + 1);
  vArray.fill(0);
  var v = 1 << p2 + 1;
  var v2 = p.clone();

Transpile

  • Fixed default parameters offset issue
  • Transpile default parameter with value true or false
  • Transpile default destructuring parameters:
function f() {
  let { x, y } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  let [z] = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
}

->

function f({ x, y } = {}, [z] = []) {}

Deobfuscate

  • Inline objects like var obj = ({ x: 1 }).x; decode(obj) to decode(1)
  • Support inlined control flow objects: ({ QuFtJ: function (n, r) { return n === r; }}).QuFtJ(u, v); -> u === v

Playground

  • Menu bar
  • Error alerts
  • CSP to disallow network requests etc in sandbox
  • Mangle filter presets:
    image

CLI

  • Added --no-jsx, --no-unpack, --no-deobfuscate, --no-unminify arguments

(the playground always has the latest changes, but the npm release was a bit outdated)

v2.13.0

31 Jan 16:11
v2.13.0
Compare
Choose a tag to compare

Unminify

  • Extract unrelated/inlined for loop variables:

    • for (var j = 0, i = 0; i < 3; i++) {} -> var j = 0; for (var i = 0; i < 3; i++) {}
  • Extract more sequence expressions:

    • while (a = (b = null, c)); -> b = null; while (a = c);
    • a[1] = (b(), c()); -> b(); a[1] = c();
  • Fixed a bug where a = 1; b = 2; was duplicated in if (1) for (a = 1, b = 2;;) {} (#54)

Transpile

function f() {
  var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
  var y = arguments.length > 1 ? arguments[1] : undefined;
}

->

function f(x = 1, y) {}
  • Fixed getting stuck in some cases when trying to convert template literals

Deobfuscate

  • Fixed Cannot read properties of undefined (reading 'params') due to dead code injection (#55)

v2.12.0

02 Jan 16:17
v2.12.0
Compare
Choose a tag to compare

Playground/Docs

Unminify

  • Unminify typeof a > "u" -> typeof a === "undefined"
  • Convert for to while:
    • for (;;) b() -> while (true) b();
    • for (; a(); ) b(); -> while (a()) b();
  • Extract sequence from while loop: while (a(), b()) c(); -> a(); while (b()) c();
  • Split vars in for loop: for (var i = 0, j = 1;;) {} -> var i = 0; var j = 1; while (true) {} thanks to @kuizuo (#37)
  • Invert boolean logic: !(a <= b) -> a > b
  • Fixed a mangle error when default parameters are used (#42)
  • Option to disable: await webcrack(source, { unminify: false })

Transpile

New WIP category for converting transpiled code of Babel/TypeScript/SWC/esbuild back to modern syntax:

  • Merge any expression into template literals: a + "b".concat(c) -> `${a}b${c}`
  • Fixed template literal escaping for \0\b\f\n\r\t\v
  • Logical assignments:
    • x && (x = y) -> x &&= y
    • var _x$y; (_x$y = x.y()).z || (_x$y.z = b); -> x.y().z ||= b;
  • Nullish coalescing: var _a; (_a = a) !== null && _a !== undefined ? _a : b; -> a ?? b
  • Nullish coalescing assignment: var _a; (_a = a) !== null && _a !== void 0 ? _a : a = b; -> a ??= b;
  • Optional chaining: a === null || a === undefined ? undefined : a.b -> a?.b

Unpack Bundle

  • Detect webpack 5 bundle without entry id (#33)

JSX

  • Create component variables: jsx(r ? "a" : "div", {}); -> const Component = r ? "a" : "div"; <Component /> (#38)

Deobfuscate

  • Inline variables that are assigned later: let a; ...; a = 1; let b = a; -> let b = 1 (#36)

v2.11.0

17 Dec 02:45
v2.11.0
Compare
Choose a tag to compare

Playground

  • Rewrite with options ui, file tree, tabs, references, go to declaration
    image

  • Quick actions:
    image

General

  • Parse bookmarklets: javascript:(function()%7Balert('hello%20world')%3B%7D)()%3B

Deobfuscate

  • Control flow proxy with spread parameter:
var _0xa7728a = {
    'UcfbR': function (_0x5a9ca0, ..._0x56527a) {
        return _0x5a9ca0(..._0x56527a);
    }
};
_0xa7728a[_0x5e8644(0x2)](a, ...b, ...c);

->

a(...b, ...c);
  • Partial control flow proxy property assignments:
const _0x4421b9 = {
  ["pOUyw"]: function (_0x48317b, _0x3eb9bf) {
    return _0x48317b < _0x3eb9bf;
  }
};
_0x4421b9.RLGat = "Hello World!";
const _0x2d22bf = _0x4421b9;
if (_0x2d22bf.pOUyw(a, b)) {
  console.log(_0x2d22bf.RLGat);
}

->

if (a < b) {
  console.log("Hello World!");
}
  • var a = function() {} -> function a() {} (#27)

Unminify

  • Extract sequence from for loop: for(; i < 10; a(), b(), i++); -> for (; i < 10; i++) { a(); b(); }
  • Extract sequence from assignment: t = (o = null, o); -> o = null; t = o;
  • 1 / 0 -> Infinity
  • Simplify divisions: 10 / 2 -> 5, but 1 / 3 stays 1 / 3 (more readable than 0.3333333333333333)
  • Convert concat to template literal: "'".concat(foo, "' \"").concat(bar, "\"") -> '${foo}' "${bar}";
  • void foo(); -> foo();, typeof foo(); -> foo();, !foo(); -> foo();, return void foo(); -> foo(); return;
  • Fix: don't transform { ["__proto__"]: 1 }

JSX

  • Self-closing tags: React.createElement("div", null) -> <div />
  • Spread props: React.createElement("div", {...props}) -> <div {...props} />
  • Detect more pragmas: jsx, jsxs, _jsx, _jsxs, jsxDEV, jsxsDEV
  • Fix string escaping, comments

Unpack Bundle

  • Detect globalThis.webpackJsonp

v2.10.0

12 Sep 17:30
Compare
Choose a tag to compare

Features

jsx("div", { children: jsxs("span", { children: ["Hello ", name] }) })

->

<div>
  <span>Hello {name}</span>
</div>
  • convert return void sequence to statements: return void (a(), b()); -> a(); b(); return;

  • simplify merged computed properties: const obj = {}; obj[1] = 2; -> const obj = { 1: 2 };

  • resolve circular browserify dependencies

  • detect for(; true;) and while ([]) as infinite loop

  • while (arr.pop()); no longer gets converted to while (arr.pop()) { ; }

Bug Fixes

  • the webcrack(code, { deobfuscate: false }) option now works (can give a minor performance boost on unobfuscated code)
  • export is no longer removed when splitting export const a = 1, b = 2; into multiple variables

v2.9.1

19 Aug 17:21
Compare
Choose a tag to compare

Bug Fixes

  • string literals with the unicode characters U+2028 and U+2029 no longer cause a SyntaxError (#17)

v2.9.0

19 Aug 04:37
Compare
Choose a tag to compare

Features

  • Inline simple string arrays: const arr = ['log', 'Hello, World!']; console[arr[0]](arr[1]); -> console.log('Hello, World!')
  • Unescape merged unicode strings: "\uD83D" + "\uDC40" -> "👀"
  • Merge object assignments:
    image

Bug Fixes

  • Control flow flattening detection in more cases
  • Stricter string array function wrapper detection (#16)

v2.8.0

12 Aug 20:52
Compare
Choose a tag to compare

Features

  • Mangle names: function _0x379214(_0x5e1b2e) { -> function a(b) {
    • CLI option: -m, --mangle
    • JS API: await webcrack(code, { mangle: true });
    • Playground: image
  • View unpacked bundle modules in the playground
    image
  • Flip *, ^, &, | operators, negative numbers, NaN/Infinity. E.g. if (1 & x) -> if (x & 1)
  • Detect more webpackJsonp variations: (this.webpackJsonp = this.webpackJsonp || []).push(...)

Performance

  • 50% faster esm conversion