j4k0xb / webcrack Goto Github PK
View Code? Open in Web Editor NEWDeobfuscate obfuscator.io, unminify and unpack bundled javascript
Home Page: https://webcrack.netlify.app
License: MIT License
Deobfuscate obfuscator.io, unminify and unpack bundled javascript
Home Page: https://webcrack.netlify.app
License: MIT License
It cant find the string array
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.
https://gist.github.com/g0dzcsgo/3728fd36c4a4a7c5af7d0db30c9a21db
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
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);
})();
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)
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
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.
says ReferenceError [Error]: DECODE_0 is not defined
at vm.js:4:9
at vm.js:5:9
to deobfuscate the code with no issues.
https://gofile.io/d/YzWlw7
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)
After deobfuscating of this code, some parts are still obfuscated.
obfuscated.txt
Obfuscation 1: An object stores a lot of simple functions and literals.
Obfuscation 2: An object references some literals or functions in another object.
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";
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
I expect to keep the value defined but it seems to remove it, breaking the whole code for the check
https://cdn.discordapp.com/attachments/1139534194402414592/1142290059559714816/0mY0xmK.js
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
is there any guide for that? thx
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)
Probably referring to DECODE_0 function that won't exists.
It should have kept the string decoder function (which should be renamed to DECODE_0). But somehow it removes it (I guess).
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
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
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
Can click and see the generated file.
NA
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.
deobfuscate without breaking it? I don't know exactly what's being removed, it's some value again
https://cdn.discordapp.com/attachments/1139534194402414592/1142441118085152829/HoszeQA.js
here's the only log of an error.
Uncaught SyntaxError: Invalid or unexpected token options.bundle.js:23754
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
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%;
}
`;
}
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;
}
};
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;
};
#!/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
#!/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
because '...'
and "..."
quotes cannot have multi-line strings
class SomeElement extends HTMLElement {
static #htmlNode = htmlNodeOfString`
<template>
${'<div id="container"> ... </div>'}
</template>
`;
I can deobfuscate scripts successfully, but some like this give this error. How can we fix it?
I want to deobfuscate it with webcrack.
https://pastes.io/vh35utbtad
https://ibb.co/02HBZbh
There are some js to c/wasm transpilers but:
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
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
function a(a, b = 0, c = a, d = 30) {
return a;
}
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
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.
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);
})();
too long for pastebin.
https://cdn.discordapp.com/attachments/822252846027374634/1097603453007712367/raw-game.js
no logs
When trying to deobfuscate this file, it seems like webcrack can't find the string array.
I expect webcrack to find the string array.
https://gist.github.com/g0dzcsgo/fa6e0402b54718a77656a28affd9c396
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
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()));
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)
Loading the above minimised code in the webcrack web IDE (Ref) with the following config:
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
});
}
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,
};
As the title suggests. It should be an easy fix, since the only thing left is to mark type only imports with ESLint.
webcrack ~/index.js
work
https://gist.github.com/Geczy/a274e77ebd2969ed0e2e4d53c2730ef6
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
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++) {}
}
A compiler from Go to JavaScript for running Go code in a browser
Gopherjs reverse engineering
Gopherjs is a compiler for the go language which compiles to pure javascript, it can be used to write go code which is executed on a webrowser, or where I found it, on a cordova app, while I was trying to reverse engineer an android apk.
At a glance, we can get the following info:
- First six lines, I will call it "header", it the same for all the projects, so we can ignore them, the only useful info is the go version, which also tell us the gopherjs version as they are linked.
- Then we have a variable number of lines, were each line is a go package, we will split each of this lines in an individual file, so the IDE those not implode (which is what happens when you try to beautify the code all at once).
- Lastly, we have 9 lines which are all the same for all the programs too, this is where everything starts whith the call to init(), but we will ignore this part for now.
To help with the decompiling process I will be writting a VScode extension which can be found here.
gopherjsRE is an attempt to make analysis of gopherjs produced files easier
Some ideas for the future
Use a parser like this one to improve the decompiler extension. Or maybe run the code for its decompilation, as the$packages
structure might contain really useful information, and maybe could be use for better reverse engineering.
cc // @vik0t0r FYI
you should try porting this to one of the Lang's: fortran, go, c, rust, Python, c++
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.
Overview of extending DevTools:
Extending DevTools
DevTools extensions add functionality to Chrome DevTools by accessing DevTools-specific extension APIs through a DevTools page added to the extension.
Some of the Chrome Extension API's that would be useful/enable this:
Use the
chrome.devtools.inspectedWindow
API to interact with the inspected window: obtain the tab ID for the inspected page, evaluate the code in the context of the inspected window, reload the page, or obtain the list of resources within the page.
Use the
getResources
call and theonResourceContent
event to obtain the list of resources (documents, stylesheets, scripts, images etc) within the inspected page. ThegetContent
andsetContent
methods of theResource
class along with theonResourceContentCommitted
event may be used to support modification of the resource content, for example, by an external editor.
The execution context of the code being evaluated includes the Developer Tools console API. For example, the code can use
inspect
and$0
.
Evaluates a JavaScript expression in the context of the main frame of the inspected page.
frameURL
s, different scriptExecutionContext
s, etcRetrieves the list of resources from the inspected page.
A resource within the inspected page, such as a document, a script, or an image.
getContent
: Gets the content of the resource. (potentially encoded, Currently, only base64 is supported.).
setContent
: Sets the content of the resource. Only resources with the text type are currently supported.
Reloads the inspected page.
reloadOptions
-> injectedScript
(though userAgent
might be useful sometimes too):
injectedScript
: If specified, the script will be injected into every frame of the inspected page immediately upon load, before any of the frame's scripts.
userAgent
: If specified, the string will override the value of the User-Agent HTTP header that's sent while loading the resources of the inspected page. The string will also override the value of thenavigator.userAgent
property that's returned to any scripts that are running within the inspected page.
Fired when a new resource is added to the inspected page.
Fired when a new revision of the resource is committed (e.g. user saves an edited version of the resource in the Developer Tools).
Use the
chrome.devtools.panels
API to integrate your extension into Developer Tools window UI: create your own panels, access existing panels, and add sidebars.
Represents the Sources panel
Creates an extension panel
Requests DevTools to open a URL in a Developer Tools panel.
Specifies the function to be called when the user clicks a resource link in the Developer Tools window. To unset the handler, either call the method with no parameters or pass null as the parameter.
chrome.devtools.network
API to retrieve the information about network requests displayed by the Developer Tools in the Network panel.onNavigated
/ onRequestFinished
might be useful in some cases.Use the
chrome.devtools.recorder
API to customize the Recorder panel in DevTools.
devtools.recorder
API is a preview feature that allows you to extend the Recorder panel in Chrome DevTools.
The
chrome.debugger
API serves as an alternate transport for Chrome's remote debugging protocol. Usechrome.debugger
to attach to one or more tabs to instrument network interaction, debug JavaScript, mutate the DOM and CSS, etc.
For security reasons, the
chrome.debugger
API does not provide access to all Chrome DevTools Protocol Domains. The available domains are: Accessibility, Audits, CacheStorage, Console, CSS, Database, Debugger, DOM, DOMDebugger, DOMSnapshot, Emulation, Fetch, IO, Input, Inspector, Log, Network, Overlay, Page, Performance, Profiler, Runtime, Storage, Target, Tracing, WebAudio, and WebAuthn.
chrome.devtools.inspectedWindow
). Still worth being aware of it and the features it has though, as there is some pretty cool stuff here!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:
Use the
chrome.runtime
API to retrieve the service worker, return details about the manifest, and listen for and respond to events in the app or extension lifecycle. You can also use this API to convert the relative path of URLs to fully-qualified URLs.
connect
/ onConnectExternal
/ onMessageExternal
/ connectNative
/ sendMessageNative
:
Attempts to connect listeners within an extension/app (such as the background page), or other extensions/apps. This is useful for content scripts connecting to their extension processes, inter-app/extension communication, and web messaging. Note that this does not connect to any listeners in a content script. Extensions may connect to content scripts embedded in tabs via
tabs.connect
.
Fired when a connection is made from another extension (by
runtime.connect
).
Fired when a message is sent from another extension/app (by
runtime.sendMessage
).
Connects to a native application in the host machine. See Native Messaging for more information.
Send a single message to a native application.
Fired when a connection is made from a native application. Currently only supported on Chrome OS.
Use the
chrome.permissions
API to request declared optional permissions at run time rather than install time, so users understand why the permissions are needed and grant only those that are necessary.
Use the
chrome.contextMenus
API to add items to Google Chrome's context menu. You can choose what types of objects your context menu additions apply to, such as images, hyperlinks, and pages.
Use the
chrome.sidePanel
API to host content in the browser's side panel alongside the main content of a webpage.
chrome.notifications
API to create rich notifications using templates and show these notifications to users in the system tray.And some that are a little more esoteric, but might still be interesting/useful:
Use the
chrome.scripting
API to execute script in different contexts.
Use the
userScripts
API to execute user scripts in the User Scripts context.
Use the
chrome.webNavigation
API to receive notifications about the status of navigation requests in-flight.
Use the
offscreen
API to create and manage offscreen documents.
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:
Error raised when deobfuscate main.js
file.
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
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]))
}
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;
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.
webcrack/src/transforms/jsx.ts
Line 26 in a972c32
webcrack/src/transforms/jsx.ts
Line 32 in a972c32
webcrack/src/transforms/jsx.ts
Line 34 in a972c32
connot resolve webpack bundle like no entry
unpack this bundle
(()=>{
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);
}
});
})();
})()
No response
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)
Just running webcrack on an index.js from webpack
Shouldn't be an error
/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)
No response
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.
As the title suggests. I've been using this approach for a while (https://git.sr.ht/~self/delance-builder/tree/9cf2a258e0e1e07d981075cf225b238c0e2a2111/item/transform/webcrack/index.ts#L24-28), and it works well on Node.js, browser and Bun.
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);
});
i would have expected the npm package and the cli to have deobfuscated and mangled without issues.
too long... file is included in source.zip
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)
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
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"
no warnings
no
No response
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
Thank you for your help -__-
DECODE_0
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
No response
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?
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.
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...
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.
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.
Could not recognize a certain webpack bundle.
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.
__webpack_require__
and __webpack_modules__
should be inferred from usage, and unpacked correctly
No response
maybe obfuscator.io update, idk. this code looks weird and dont deobfuscating in webcrack:
obfs.txt
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.