Releases: j4k0xb/webcrack
Releases · j4k0xb/webcrack
v2.14.1
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
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
orfalse
- 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)
todecode(1)
- Support inlined control flow objects:
({ QuFtJ: function (n, r) { return n === r; }}).QuFtJ(u, v);
->u === v
Playground
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
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 inif (1) for (a = 1, b = 2;;) {}
(#54)
Transpile
- Decompile default parameters from @babel/plugin-transform-parameters:
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
Playground/Docs
- Fixed opening files in the sidebar for windows (#40)
- Added various examples, docs for common errors
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
Playground
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
, but1 / 3
stays1 / 3
(more readable than0.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
Features
- decompile the new jsx transform:
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;)
andwhile ([])
as infinite loop -
while (arr.pop());
no longer gets converted towhile (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 splittingexport const a = 1, b = 2;
into multiple variables
v2.9.1
v2.9.0
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:
Bug Fixes
- Control flow flattening detection in more cases
- Stricter string array function wrapper detection (#16)
v2.8.0
Features
- Mangle names:
function _0x379214(_0x5e1b2e) {
->function a(b) {
- View unpacked bundle modules in the playground
- 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