An open API service indexing awesome lists of open source software.

https://github.com/evex-dev/expose-kit

A universal toolkit for deobfuscating JavaScript
https://github.com/evex-dev/expose-kit

deobfuscation deobfuscator javascript obfuscator

Last synced: 5 months ago
JSON representation

A universal toolkit for deobfuscating JavaScript

Awesome Lists containing this project

README

          

# Expose Kit
![release workflow](https://github.com/evex-dev/linejs/actions/workflows/release.yml/badge.svg)
[![](https://dcbadge.limes.pink/api/server/evex)](https://discord.gg/evex)

> A universal toolkit for JavaScript deobfuscation

---

## What is this?

JavaScript deobfuscation tools are everywhere.
But many of them are **too aggressive**, rewriting code until it breaks.

Expose Kit takes a **different approach**.

- No brute force
- Step-by-step, verifiable transforms
- Designed to *not* break your code silently

Each transformation is meant to be **checked and validated**, so you always know *when* something goes wrong.

Alongside deobfuscation, Expose Kit also provides a set of **practical utilities** for working with obfuscated JavaScript.

---

## Installation

Just one step:

```bash
npm i -g expose-kit
# or
bun i -g expose-kit
```

```bash
expose --help
expose parsable sample.js
```

---

## Usage Notes

### Default arguments

- The first argument is the input file
(`--file` / `--input` can also be used)
- If required options are missing, Expose Kit will **prompt you**
- A timeout is enabled by default to avoid hangs
Use `--unlimited` for long-running execution

---

## Recommended Workflow

First, an important premise:

> It is **impossible** to create a static deobfuscation tool that *never* breaks.

Reasons include:
- Unpredictable execution (`eval`, dynamic code)
- Bugs or edge cases in AST manipulation

Because of this, you should **verify the code at every step**.

### 1. Always verify with `parsable`

After each transformation, run:

```bash
expose parsable file.js
```

This ensures the syntax is still valid.

---

### 2. Make scopes safe first

One of the most common causes of breakage is **variable name confusion**.

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.

That’s why you should **always start with**:

```bash
expose safe-scope input.js
```

This renames bindings per scope, producing code like:

```js
Before: var x = 810;((x) => console.log(x))(114514);
After: var x = 810;((_x) => console.log(_x))(114514);
```

With this alone:
- The code becomes far more resistant to breakage
- Writing custom deobfuscation logic becomes much easier
- You no longer need to worry about scope collisions

---

### 3. Apply transforms step by step

After `safe-scope`, combine common techniques like:
- `expand-array`, `expand-object` and more

After **each step**, run `parsable` and `remove-unused` again.
(even if it's not frequent, we might overlook something broken)

The more you do it, the clearer it becomes.

Expose Kit will also clearly indicate whether a **diff** exists, making inspection easy.

Repeat this process, and the original code will gradually reveal itself.

---

## Commands

### `expose parsable`

Check whether a file is syntactically valid.

```js
parsable: const x = 810;
not parsable: const ;x; == 810;
```

```bash
expose parsable path/to/file.js
```

Args:
- Default args only

---

### `expose safe-scope`

Rename bindings per scope for safer transformations.

```bash
expose safe-scope path/to/file.js --output path/to/file.safe-scope.js
```
Example is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/safe-scope/mocks).

Args:
- `--o, --output `
Output file path
- No extension → `file.safe-scope.js`
- With extension → `file.safe-scope.`

---

### `expose pre-evaluate`

Pre-evaluate const numeric/string expressions. (Safe evaluate)

```js
const a = 1 + 2 * 3; // => 7
const c = "aaaa";
const b = "a" + c; // => "aaaaa"
```

```bash
expose pre-evaluate path/to/file.js --output path/to/file.pre-evaluate.js
```

Args:
- `--o, --output `
Output file path
- No extension → `file.pre-evaluate.js`
- With extension → `file.pre-evaluate.`

Notes:
- Inlines zero-arg functions that return safe array literals by hoisting them to a var.

---

### `expose expand-array`

Expand array index access for primitive values.
```js
var a = [1, 1, 4, 5, 1, 4];
// before
console.log(a[0], a[2], a[3]);
// after
console.log(1, 4, 5);
```
Example is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/expand-array/mocks).

```bash
expose expand-array path/to/file.js --target arrayName --output path/to/file.expand-array.js
```

Args:
- `--target `
Target array variable name
- `--o, --output `
Output file path

Notes:
- Each replacement is validated by reparsing; unsafe replacements are skipped.
(This array is intended to be immutable, so caution is required)

---

### `expose expand-object`

Expand object property access for primitive values.
```js
const obj = { a: 1, b: 2 };
// before
console.log(obj.a, obj["b"]);
// after
console.log(1, 2);
```
Example is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/expand-object/mocks).

```bash
expose expand-object path/to/file.js --target objectName --output path/to/file.expand-object.js
```

Args:
- `--target `
Target object variable name
- `--o, --output `
Output file path

Notes:
- Each replacement is validated by reparsing; unsafe replacements are skipped.
(This object is intended to be immutable, so caution is required)

---

### `expose object-packer`

Pack consecutive object property assignments into literals.
```js
const obj = {};
// before
obj.a = 0;
obj["b"] = 1;
// after
const obj = { a: 0, b: 1 };
```
Example is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/object-packer/mocks).

```bash
expose object-packer path/to/file.js --output path/to/file.object-packer.js
```

Args:
- `--o, --output `
Output file path

Notes:
- Packs only consecutive assignments following an empty object literal.
- Stops when a property value references the object itself.

---

### `expose key-simplify`

Replace safe string literal property accesses (`obj["foo"]`) with dot-style access (`obj.foo`).
```js
const obj = { foo: 1, bar_baz: 2 };
obj["foo"] = obj['bar'];
console.log(obj["foo"], obj["bar_baz"]);
```
Example is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/key-simplify/mocks).

```bash
expose key-simplify path/to/file.js --output path/to/file.key-simplify.js
```

Args:
- `--o, --output `
Output file path

Notes:
- Only rewrites computed keys that are plain identifiers.
- Leaves invalid identifier keys untouched so the output stays parseable.

---

### `expose remove-updater`

Replace safe update expressions with += or -=.
```js
// before
a++;
--b;
// after
a += 1;
b -= 1;
```
Example is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/remove-updater/mocks).

```bash
expose remove-updater path/to/file.js --output path/to/file.remove-updater.js
```

Args:
- `--o, --output `
Output file path

Notes:
- Only replaces update expressions whose value is not used.
- Safe for expression statements and for-loop update clauses.

---

### `expose remove-reassign`

Inline safe alias assignments and wrapper calls.
```js
const a = 0;
const b = a;
const c = b;
console.log(c); // => console.log(a);
```
```js
function a(arg) {
return b(arg);
}
function c(arg) {
return d[arg];
}
a(0); // => b(0)
c(0); // => d[0]
```
Example is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/remove-reassign/mocks).

```bash
expose remove-reassign path/to/file.js --output path/to/file.remove-reassign.js
```

Args:
- `--o, --output `
Output file path

Notes:
- Only inlines const/immutable alias chains.
- Skips object shorthand replacements and shadowed bindings.
- Wrapper inlining is limited to single-return passthroughs.

---

### `expose remove-deadcode`

Remove unreachable branches and simplify conditional expressions.
```js
if (true) {
a();
} else {
b();
}
// after
a();

const x = cond ? true : false;
// after
const x = !!cond;
```
Example is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/remove-deadcode/mocks).

```bash
expose remove-deadcode path/to/file.js --output path/to/file.remove-deadcode.js
```

Args:
- `--o, --output `
Output file path

Notes:
- Only removes branches with literal/array/object tests.
- Simplifies ternaries when both branches are booleans.

---

### `expose remove-anti-tamper`

Drop the self-defending wrapper, debug guards, and console hijacks generated by anti-tamper scripts.
```js
var wrapper = (function () {
var guard = true;
return function (ctx, fn) {
var thunk = guard ? function () {
if (fn) {
fn.apply(ctx, arguments);
fn = null;
}
} : function () {};
guard = false;
return thunk;
};
})();

wrapper(this, function () {
console.log("tamper");
});

console.log("safe");
```
Example is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/remove-anti-tamper/mocks).

```bash
expose remove-anti-tamper path/to/file.js --output path/to/file.remove-anti-tamper.js
```

Args:
- `--o, --output `
Output file path

Notes:
- Targets wrappers that return guarded helper functions and removes their invocations.
- Cleans up debug/console helper functions before removing the wrapper.

---

### `expose control-flow-packer`

Inline control-flow flattening loops generated by string-based state machines.
```js
const _0x1 = "a|b|c".split("|");
let _0x2 = 0;

while (true) {
switch (_0x1[_0x2++]) {
case "a":
console.log("a");
continue;
case "b":
console.log("b");
continue;
case "c":
console.log("c");
return;
}
break;
}
```
Example is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/control-flow-packer/mocks).

```bash
expose control-flow-packer path/to/file.js --output path/to/file.control-flow-packer.js
```

Args:
- `--o, --output `
Output file path

Notes:
- Only flattens loops whose state array comes from a literal `split`.
- Stops when a branch returns or a state token is missing.

---

### `expose fn-inliner`

Inline proxy function calls into expressions.
```js
const add = (a, b) => a + b;
const sum = add(1, 2);
// after
const sum = 1 + 2;
```
Example is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/fn-inliner/mocks).

```bash
expose fn-inliner path/to/file.js --output path/to/file.fn-inliner.js
```

Args:
- `--o, --output `
Output file path

Notes:
- Only inlines functions that return a single expression.
- Skips return expressions with assignments, functions, blocks, or sequences.

---

### `expose sequence-split`

Split sequence expressions into statements.
```js
// before
a, b, c;
// after
a;
b;
c;
```
Example is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/sequence-split/mocks).

```bash
expose sequence-split path/to/file.js --output path/to/file.sequence-split.js
```

Args:
- `--o, --output `
Output file path

Notes:
- Splits safe sequence expressions into standalone statements.
- Also normalizes single-statement control flow blocks.

---

### `expose remove-unused`

Remove unused variabless.
```js
// before
var a = 0, b = 1;
console.log(a);
// after
var a = 0;
console.log(a);
```
Example is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/remove-unused/mocks).

```bash
expose remove-unused path/to/file.js --output path/to/file.remove-unused.js
```

Args:
- `--o, --output `
Output file path

## Community & Support

- Missing a feature? → [Create an issue](https://github.com/EdamAme-x/expose-kit/issues)
- Not sure which command to use? → Join our [Discord](https://evex.land)

---

## Author

- [EdamAme-x](https://github.com/EdamAme-x)

Built for research, not abuse.
Want stronger obfuscation? Then build something this tool can’t reverse.