expose-kit 0.2.7 → 0.3.0
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 +6 -6
- package/dist/index.js +57 -20
- package/dist/package.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -85,7 +85,7 @@ If you try to write your own deobfuscation logic (e.g. in Python), you’ll quic
|
|
|
85
85
|
That’s why you should **always start with**:
|
|
86
86
|
|
|
87
87
|
```bash
|
|
88
|
-
expose scope
|
|
88
|
+
expose safe-scope input.js
|
|
89
89
|
```
|
|
90
90
|
|
|
91
91
|
This renames bindings per scope, producing code like:
|
|
@@ -104,7 +104,7 @@ With this alone:
|
|
|
104
104
|
|
|
105
105
|
### 3. Apply transforms step by step
|
|
106
106
|
|
|
107
|
-
After `scope
|
|
107
|
+
After `safe-scope`, combine common techniques like:
|
|
108
108
|
- `expand-array` and more
|
|
109
109
|
- legacy obfuscator-specific commands
|
|
110
110
|
|
|
@@ -136,19 +136,19 @@ Args:
|
|
|
136
136
|
|
|
137
137
|
---
|
|
138
138
|
|
|
139
|
-
### `expose scope
|
|
139
|
+
### `expose safe-scope`
|
|
140
140
|
|
|
141
141
|
Rename bindings per scope for safer transformations.
|
|
142
142
|
|
|
143
143
|
```bash
|
|
144
|
-
expose scope
|
|
144
|
+
expose safe-scope path/to/file.js --output path/to/file.safe-scope.js
|
|
145
145
|
```
|
|
146
146
|
|
|
147
147
|
Args:
|
|
148
148
|
- `--o, --output <file>`
|
|
149
149
|
Output file path
|
|
150
|
-
- No extension → `file.scope
|
|
151
|
-
- With extension → `file.scope
|
|
150
|
+
- No extension → `file.safe-scope.js`
|
|
151
|
+
- With extension → `file.safe-scope.<ext>`
|
|
152
152
|
|
|
153
153
|
---
|
|
154
154
|
|
package/dist/index.js
CHANGED
|
@@ -59,13 +59,14 @@ var createParseOptions = (filename) => {
|
|
|
59
59
|
};
|
|
60
60
|
|
|
61
61
|
// utils/common/timeout.ts
|
|
62
|
+
var MAX_TIMEOUT = 2147483647;
|
|
62
63
|
var timeout = (fn, ms) => {
|
|
63
64
|
let aborted = false;
|
|
64
65
|
const { resolve, reject, promise } = Promise.withResolvers();
|
|
65
66
|
const timer = setTimeout(() => {
|
|
66
67
|
aborted = true;
|
|
67
68
|
reject(new Error("Hang detected, please report to the developer"));
|
|
68
|
-
}, ms);
|
|
69
|
+
}, ms ?? MAX_TIMEOUT);
|
|
69
70
|
const finish = () => {
|
|
70
71
|
clearTimeout(timer);
|
|
71
72
|
resolve();
|
|
@@ -118,13 +119,13 @@ var parsable_default = createCommand((program2) => {
|
|
|
118
119
|
return finish();
|
|
119
120
|
}
|
|
120
121
|
},
|
|
121
|
-
options.unlimited ?
|
|
122
|
+
options.unlimited ? null : 30 * 1e3
|
|
122
123
|
);
|
|
123
124
|
}
|
|
124
125
|
);
|
|
125
126
|
});
|
|
126
127
|
|
|
127
|
-
// commands/scope
|
|
128
|
+
// commands/safe-scope/index.ts
|
|
128
129
|
import { readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
129
130
|
import { basename, dirname, extname, join } from "path";
|
|
130
131
|
import { parse as parse2 } from "@babel/parser";
|
|
@@ -134,31 +135,61 @@ import loading2 from "loading-cli";
|
|
|
134
135
|
|
|
135
136
|
// utils/babel/patchDefault.ts
|
|
136
137
|
var patchDefault = (babelFn) => {
|
|
138
|
+
if (typeof babelFn === "function") {
|
|
139
|
+
return babelFn;
|
|
140
|
+
}
|
|
137
141
|
return babelFn.default;
|
|
138
142
|
};
|
|
139
143
|
|
|
140
144
|
// utils/common/diff.ts
|
|
141
145
|
function diff(before, after) {
|
|
142
|
-
const
|
|
143
|
-
const
|
|
146
|
+
const b = before.split(/\r?\n/);
|
|
147
|
+
const a = after.split(/\r?\n/);
|
|
148
|
+
const n = b.length;
|
|
149
|
+
const m = a.length;
|
|
150
|
+
const dp = Array.from(
|
|
151
|
+
{ length: n + 1 },
|
|
152
|
+
() => Array(m + 1).fill(0)
|
|
153
|
+
);
|
|
154
|
+
for (let i2 = 0; i2 < n; i2++) {
|
|
155
|
+
for (let j2 = 0; j2 < m; j2++) {
|
|
156
|
+
if (b[i2] === a[j2]) {
|
|
157
|
+
(dp[i2 + 1] || [])[j2 + 1] = (dp[i2]?.[j2] ?? 0) + 1;
|
|
158
|
+
} else {
|
|
159
|
+
(dp[i2 + 1] || [])[j2 + 1] = Math.max(
|
|
160
|
+
dp[i2]?.[j2 + 1] ?? 0,
|
|
161
|
+
dp[i2 + 1]?.[j2] ?? 0
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
144
166
|
const changed = [];
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
167
|
+
let i = n;
|
|
168
|
+
let j = m;
|
|
169
|
+
while (i > 0 || j > 0) {
|
|
170
|
+
if (i > 0 && j > 0 && b[i - 1] === a[j - 1]) {
|
|
171
|
+
i--;
|
|
172
|
+
j--;
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
if (j > 0 && (i === 0 || (dp[i]?.[j - 1] ?? 0) >= (dp[i - 1]?.[j] ?? 0))) {
|
|
176
|
+
changed.push(j);
|
|
177
|
+
j--;
|
|
178
|
+
} else {
|
|
179
|
+
i--;
|
|
149
180
|
}
|
|
150
181
|
}
|
|
151
|
-
return changed;
|
|
182
|
+
return changed.reverse();
|
|
152
183
|
}
|
|
153
184
|
|
|
154
|
-
// commands/scope
|
|
185
|
+
// commands/safe-scope/index.ts
|
|
155
186
|
var createDefaultOutputPath = (inputPath) => {
|
|
156
187
|
const ext = extname(inputPath);
|
|
157
188
|
if (!ext) {
|
|
158
|
-
return `${inputPath}.scope
|
|
189
|
+
return `${inputPath}.safe-scope.js`;
|
|
159
190
|
}
|
|
160
191
|
const base = basename(inputPath, ext);
|
|
161
|
-
return join(dirname(inputPath), `${base}.scope
|
|
192
|
+
return join(dirname(inputPath), `${base}.safe-scope${ext}`);
|
|
162
193
|
};
|
|
163
194
|
var renameBindingsByScope = (code, filename) => {
|
|
164
195
|
const ast = parse2(code, createParseOptions(filename));
|
|
@@ -184,8 +215,8 @@ var renameBindingsByScope = (code, filename) => {
|
|
|
184
215
|
});
|
|
185
216
|
return patchDefault(generate)(ast).code;
|
|
186
217
|
};
|
|
187
|
-
var
|
|
188
|
-
program2.command("scope
|
|
218
|
+
var safe_scope_default = createCommand((program2) => {
|
|
219
|
+
program2.command("safe-scope").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
220
|
async (fileArgument, options) => {
|
|
190
221
|
await timeout(
|
|
191
222
|
async ({ finish }) => {
|
|
@@ -197,15 +228,21 @@ var scope_safe_default = createCommand((program2) => {
|
|
|
197
228
|
try {
|
|
198
229
|
const fileContent = readFileSync2(filename, "utf8");
|
|
199
230
|
const defaultOutputPath = createDefaultOutputPath(filename);
|
|
200
|
-
|
|
231
|
+
let outputPath = options.output;
|
|
232
|
+
if (!outputPath) {
|
|
233
|
+
const promptPath = (await createPrompt("Enter the output file path:"))?.trim();
|
|
234
|
+
outputPath = promptPath || defaultOutputPath;
|
|
235
|
+
}
|
|
201
236
|
const loader = loading2("Renaming variables by scope...").start();
|
|
202
237
|
try {
|
|
203
238
|
const output = renameBindingsByScope(fileContent, filename);
|
|
204
239
|
writeFileSync(outputPath, output, "utf8");
|
|
205
|
-
loader.succeed(
|
|
240
|
+
loader.succeed(
|
|
241
|
+
`Saved safe-scope file to: ${outputPath} (${diff(fileContent, output).length} lines changed)`
|
|
242
|
+
);
|
|
206
243
|
return finish();
|
|
207
244
|
} catch (error) {
|
|
208
|
-
loader.fail("Failed to apply scope
|
|
245
|
+
loader.fail("Failed to apply safe-scope transform");
|
|
209
246
|
showError(
|
|
210
247
|
`Error transforming file '${filename}': ${error instanceof Error ? error.message : "Unknown error"}`
|
|
211
248
|
);
|
|
@@ -218,7 +255,7 @@ var scope_safe_default = createCommand((program2) => {
|
|
|
218
255
|
return finish();
|
|
219
256
|
}
|
|
220
257
|
},
|
|
221
|
-
options.unlimited ?
|
|
258
|
+
options.unlimited ? null : 120 * 1e3
|
|
222
259
|
);
|
|
223
260
|
}
|
|
224
261
|
);
|
|
@@ -287,7 +324,7 @@ program.name("expose").description("CLI for Deobfuscating").version(
|
|
|
287
324
|
"-v, --version",
|
|
288
325
|
"display version number"
|
|
289
326
|
);
|
|
290
|
-
var commands = [parsable_default,
|
|
327
|
+
var commands = [parsable_default, safe_scope_default];
|
|
291
328
|
for (const command of commands) {
|
|
292
329
|
command(program);
|
|
293
330
|
}
|
package/dist/package.json
CHANGED