expose-kit 0.2.5 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -48
- package/dist/index.js +20 -7
- package/dist/package.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,99 +1,167 @@
|
|
|
1
1
|
# Expose Kit
|
|
2
2
|

|
|
3
|
-
[](https://discord.gg/evex)
|
|
3
|
+
[](https://discord.gg/evex)
|
|
4
4
|
|
|
5
|
-
> A universal toolkit for
|
|
6
|
-
---
|
|
5
|
+
> A universal toolkit for JavaScript deobfuscation
|
|
7
6
|
|
|
8
|
-
##### <center>❓ Question: Join our [Discord community](https://evex.land)</center>
|
|
9
7
|
---
|
|
10
8
|
|
|
11
|
-
##
|
|
12
|
-
JavaScript deobfuscation tools are *everywhere*.
|
|
13
|
-
<img width="145.2" height="113.5" alt="image" src="https://github.com/relative/synchrony/blob/master/.github/hm.png?raw=true" />
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
But many of them are **too aggressive**, rewriting code until it breaks.
|
|
17
|
-
|
|
18
|
-
<img width="654" height="24" alt="image" src="https://github.com/user-attachments/assets/fd11d250-0163-4cd2-b36c-5514137fe087" />
|
|
9
|
+
## What is this?
|
|
19
10
|
|
|
20
|
-
|
|
11
|
+
JavaScript deobfuscation tools are everywhere.
|
|
12
|
+
But many of them are **too aggressive**, rewriting code until it breaks.
|
|
21
13
|
|
|
22
|
-
|
|
14
|
+
Expose Kit takes a **different approach**.
|
|
23
15
|
|
|
24
|
-
|
|
16
|
+
- No brute force
|
|
17
|
+
- Step-by-step, verifiable transforms
|
|
18
|
+
- Designed to *not* break your code silently
|
|
25
19
|
|
|
26
|
-
|
|
20
|
+
Each transformation is meant to be **checked and validated**, so you always know *when* something goes wrong.
|
|
27
21
|
|
|
28
|
-
|
|
22
|
+
Alongside deobfuscation, Expose Kit also provides a set of **practical utilities** for working with obfuscated JavaScript.
|
|
29
23
|
|
|
30
|
-
##### If the feature you’re looking for doesn’t exist, please create an [issue](https://github.com/EdamAme-x/expose-kit/issues).
|
|
31
|
-
##### If you know what you want to do but aren’t sure which feature to use, join our [Discord community](https://evex.land) and ask for help.
|
|
32
24
|
---
|
|
33
25
|
|
|
34
26
|
## Installation
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
27
|
+
|
|
28
|
+
Just one step:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
38
31
|
npm i -g expose-kit
|
|
39
32
|
# or
|
|
40
33
|
bun i -g expose-kit
|
|
41
34
|
```
|
|
42
35
|
|
|
43
|
-
|
|
44
|
-
```regex
|
|
36
|
+
```bash
|
|
45
37
|
expose --help
|
|
46
38
|
expose parsable sample.js
|
|
47
39
|
```
|
|
48
40
|
|
|
49
|
-
|
|
50
|
-
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Usage Notes
|
|
44
|
+
|
|
45
|
+
### Default arguments
|
|
46
|
+
|
|
47
|
+
- The first argument is the input file
|
|
48
|
+
(`--file` / `--input` can also be used)
|
|
49
|
+
- If required options are missing, Expose Kit will **prompt you**
|
|
50
|
+
- A timeout is enabled by default to avoid hangs
|
|
51
|
+
Use `--unlimited` for long-running execution
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Recommended Workflow
|
|
56
|
+
|
|
57
|
+
First, an important premise:
|
|
58
|
+
|
|
59
|
+
> It is **impossible** to create a static deobfuscation tool that *never* breaks.
|
|
60
|
+
|
|
61
|
+
Reasons include:
|
|
62
|
+
- Unpredictable execution (`eval`, dynamic code)
|
|
63
|
+
- Bugs or edge cases in AST manipulation
|
|
51
64
|
|
|
52
|
-
|
|
65
|
+
Because of this, you should **verify the code at every step**.
|
|
53
66
|
|
|
54
|
-
|
|
55
|
-
|
|
67
|
+
### 1. Always verify with `parsable`
|
|
68
|
+
|
|
69
|
+
After each transformation, run:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
expose parsable file.js
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
This ensures the syntax is still valid.
|
|
56
76
|
|
|
57
|
-
### Commands
|
|
58
77
|
---
|
|
59
78
|
|
|
60
|
-
|
|
79
|
+
### 2. Make scopes safe first
|
|
80
|
+
|
|
81
|
+
One of the most common causes of breakage is **variable name confusion**.
|
|
82
|
+
|
|
83
|
+
If you try to write your own deobfuscation logic (e.g. in Python), you’ll quickly realize how painful it is to track scopes correctly.
|
|
84
|
+
|
|
85
|
+
That’s why you should **always start with**:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
expose scope-safe input.js
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
This renames bindings per scope, producing code like:
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
Before: var x = 810;((x) => console.log(x))(114514);
|
|
95
|
+
After: var x = 810;((_x) => console.log(_x))(114514);
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
With this alone:
|
|
99
|
+
- The code becomes far more resistant to breakage
|
|
100
|
+
- Writing custom deobfuscation logic becomes much easier
|
|
101
|
+
- You no longer need to worry about scope collisions
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
### 3. Apply transforms step by step
|
|
106
|
+
|
|
107
|
+
After `scope-safe`, combine common techniques like:
|
|
108
|
+
- `expand-array` and more
|
|
109
|
+
- legacy obfuscator-specific commands
|
|
110
|
+
|
|
111
|
+
After **each step**, run `parsable` again.
|
|
112
|
+
|
|
113
|
+
Expose Kit will also clearly indicate whether a **diff** exists, making inspection easy.
|
|
114
|
+
|
|
115
|
+
Repeat this process, and the original code will gradually reveal itself.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Commands
|
|
120
|
+
|
|
121
|
+
### `expose parsable`
|
|
122
|
+
|
|
123
|
+
Check whether a file is syntactically valid.
|
|
61
124
|
|
|
62
|
-
Check if the file is parsable
|
|
63
125
|
```js
|
|
64
126
|
parsable: const x = 810;
|
|
65
127
|
not parsable: cons x; = 810;
|
|
66
128
|
```
|
|
67
129
|
|
|
68
|
-
##### Example
|
|
69
130
|
```bash
|
|
70
131
|
expose parsable path/to/file.js
|
|
71
132
|
```
|
|
72
133
|
|
|
73
|
-
|
|
74
|
-
-
|
|
134
|
+
Args:
|
|
135
|
+
- Default args only
|
|
75
136
|
|
|
76
137
|
---
|
|
77
|
-
#### `expose scope-safe`
|
|
78
138
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
After: var x = 810;((_x) => console.log(_x))(114514);
|
|
83
|
-
```
|
|
139
|
+
### `expose scope-safe`
|
|
140
|
+
|
|
141
|
+
Rename bindings per scope for safer transformations.
|
|
84
142
|
|
|
85
|
-
##### Example
|
|
86
143
|
```bash
|
|
87
144
|
expose scope-safe path/to/file.js --output path/to/file.scope-safe.js
|
|
88
145
|
```
|
|
89
146
|
|
|
90
|
-
|
|
91
|
-
- `--o, --output <file
|
|
92
|
-
|
|
93
|
-
|
|
147
|
+
Args:
|
|
148
|
+
- `--o, --output <file>`
|
|
149
|
+
Output file path
|
|
150
|
+
- No extension → `file.scope-safe.js`
|
|
151
|
+
- With extension → `file.scope-safe.<ext>`
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Community & Support
|
|
156
|
+
|
|
157
|
+
- Missing a feature? → [Create an issue](https://github.com/EdamAme-x/expose-kit/issues)
|
|
158
|
+
- Not sure which command to use? → Join our [Discord](https://evex.land)
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Author
|
|
94
163
|
|
|
95
|
-
## Authors
|
|
96
164
|
- [EdamAme-x](https://github.com/EdamAme-x)
|
|
97
165
|
|
|
98
166
|
Built for research, not abuse.
|
|
99
|
-
Want stronger obfuscation? Then
|
|
167
|
+
Want stronger obfuscation? Then build something this tool can’t reverse.
|
package/dist/index.js
CHANGED
|
@@ -132,12 +132,25 @@ import traverse from "@babel/traverse";
|
|
|
132
132
|
import generate from "@babel/generator";
|
|
133
133
|
import loading2 from "loading-cli";
|
|
134
134
|
|
|
135
|
-
// utils/babel/
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
return traverse2.default;
|
|
135
|
+
// utils/babel/patchDefault.ts
|
|
136
|
+
var patchDefault = (babelFn) => {
|
|
137
|
+
return babelFn.default;
|
|
139
138
|
};
|
|
140
139
|
|
|
140
|
+
// utils/common/diff.ts
|
|
141
|
+
function diff(before, after) {
|
|
142
|
+
const beforeLines = before.split(/\r?\n/);
|
|
143
|
+
const afterLines = after.split(/\r?\n/);
|
|
144
|
+
const changed = [];
|
|
145
|
+
const max = Math.max(beforeLines.length, afterLines.length);
|
|
146
|
+
for (let i = 0; i < max; i++) {
|
|
147
|
+
if (beforeLines[i] !== afterLines[i]) {
|
|
148
|
+
changed.push(i + 1);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return changed;
|
|
152
|
+
}
|
|
153
|
+
|
|
141
154
|
// commands/scope-safe/index.ts
|
|
142
155
|
var createDefaultOutputPath = (inputPath) => {
|
|
143
156
|
const ext = extname(inputPath);
|
|
@@ -150,7 +163,7 @@ var createDefaultOutputPath = (inputPath) => {
|
|
|
150
163
|
var renameBindingsByScope = (code, filename) => {
|
|
151
164
|
const ast = parse2(code, createParseOptions(filename));
|
|
152
165
|
const renamedBindings = /* @__PURE__ */ new Set();
|
|
153
|
-
|
|
166
|
+
patchDefault(traverse)(ast, {
|
|
154
167
|
Scopable(path) {
|
|
155
168
|
for (const [name, binding] of Object.entries(path.scope.bindings)) {
|
|
156
169
|
if (renamedBindings.has(binding)) {
|
|
@@ -169,7 +182,7 @@ var renameBindingsByScope = (code, filename) => {
|
|
|
169
182
|
}
|
|
170
183
|
}
|
|
171
184
|
});
|
|
172
|
-
return generate(ast).code;
|
|
185
|
+
return patchDefault(generate)(ast).code;
|
|
173
186
|
};
|
|
174
187
|
var scope_safe_default = createCommand((program2) => {
|
|
175
188
|
program2.command("scope-safe").description("Rename bindings per scope for safer transforms").argument("[file]", "The file to transform").option("--input, --file <file>", "The file to transform").option("--o, --output <file>", "Output file path").option("--unlimited", "Unlimited timeout").action(
|
|
@@ -189,7 +202,7 @@ var scope_safe_default = createCommand((program2) => {
|
|
|
189
202
|
try {
|
|
190
203
|
const output = renameBindingsByScope(fileContent, filename);
|
|
191
204
|
writeFileSync(outputPath, output, "utf8");
|
|
192
|
-
loader.succeed(`Saved scope-safe file to: ${outputPath}`);
|
|
205
|
+
loader.succeed(`Saved scope-safe file to: ${outputPath} (${diff(fileContent, output).length} lines changed)`);
|
|
193
206
|
return finish();
|
|
194
207
|
} catch (error) {
|
|
195
208
|
loader.fail("Failed to apply scope-safe transform");
|
package/dist/package.json
CHANGED