Skip to content

Commit 9e14fbf

Browse files
committed
feat: add CLI for WebAssembly obfuscation
Introduce `swamped` command-line interface that exposes all 22 perturbation strategies (structural + code-level) via argparse.
1 parent 04e2bcc commit 9e14fbf

6 files changed

Lines changed: 546 additions & 0 deletions

File tree

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
__pycache__/
2+
*.py[cod]
3+
*.egg-info/
4+
*.egg
5+
dist/
6+
build/
7+
.eggs/

cli/README.md

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
# SWAMPED CLI
2+
3+
CLI for applying 22 semantics-preserving perturbation methods to WebAssembly modules.
4+
5+
## Install
6+
7+
```bash
8+
# Requires WABT (wasm2wat / wat2wasm) on PATH
9+
brew install wabt # macOS
10+
apt install wabt # Debian/Ubuntu
11+
12+
# Install swamped globally
13+
pip install -e .
14+
```
15+
16+
## Quick start
17+
18+
```bash
19+
# List all 22 perturbation methods
20+
swamped list
21+
22+
# Apply specific strategies
23+
swamped obfuscate input.wasm -o output.wasm -s nop_insertion shift_transformation
24+
25+
# Apply all strategies at once
26+
swamped obfuscate input.wasm -o output.wasm -s all
27+
28+
# Only structural or only code-level
29+
swamped obfuscate input.wasm -o output.wasm -s structural
30+
swamped obfuscate input.wasm -o output.wasm -s code
31+
32+
# Exclude specific strategies with -e
33+
swamped obfuscate input.wasm -o output.wasm -s all -e data_encryption direct_to_indirect
34+
swamped obfuscate input.wasm -o output.wasm -s code -e nop_insertion
35+
36+
# Control intensity (0.0 = none, 1.0 = max)
37+
swamped obfuscate input.wasm -o output.wasm -s all --ratio 0.3
38+
39+
# Validate the output after obfuscation
40+
swamped obfuscate input.wasm -o output.wasm -s nop_insertion --validate
41+
42+
# Stack operation insertion: all 6 variants (default)
43+
swamped obfuscate input.wasm -o output.wasm -s stack_op_insertion
44+
45+
# Stack operation insertion: only specific variants
46+
swamped obfuscate input.wasm -o output.wasm -s stack_op_insertion --stackop m b f
47+
```
48+
49+
Accepts both `.wasm` and `.wast` as input/output — conversion is automatic.
50+
51+
## The 22 perturbation methods
52+
53+
### Structural perturbations (9)
54+
55+
| # | Name | Description |
56+
| --- | ------------------------ | ------------------------------------------------ |
57+
| 1 | `function_sig_insertion` | Inject unused function type signatures |
58+
| 2 | `import_insertion` | Inject unused import declarations |
59+
| 3 | `function_insertion` | Inject entire dummy function bodies |
60+
| 4 | `function_body_cloning` | Clone functions with proxy redirection |
61+
| 5 | `global_insertion` | Inject dummy global variables |
62+
| 6 | `element_insertion` | Inject table element entries |
63+
| 7 | `export_insertion` | Inject unused export declarations |
64+
| 8 | `data_insertion` | Inject unused data segments |
65+
| 9 | `data_encryption` | XOR-encrypt data segments with runtime decryptor |
66+
67+
### Code-level perturbations (13)
68+
69+
| # | Name | Description |
70+
| --- | ------------------------------- | -------------------------------------------------------- |
71+
| 10 | `custom_section_insertion` | Inject custom named sections _(not yet implemented)_ |
72+
| 11 | `nop_insertion` | Insert NOP instructions |
73+
| 12 | `stack_op_insertion` | Insert dummy stack operations (see sub-variants below) |
74+
| 13 | `opaque_predicate_insertion` | Insert always-true/false Collatz-based predicates |
75+
| 14 | `proxy_function_insertion` | Insert proxy wrapper functions _(not yet implemented)_ |
76+
| 15 | `direct_to_indirect` | Convert direct calls to indirect table calls |
77+
| 16 | `add_sub_transformation` | Transform add/sub operations (a+b <-> a-(-b)) |
78+
| 17 | `shift_transformation` | Convert shifts to mul/div equivalents |
79+
| 18 | `eqz_transformation` | Rewrite eqz as comparison with zero |
80+
| 19 | `offset_expansion` | Decompose memory offset encoding |
81+
| 20 | `mba_transformation` | Replace XOR/OR with mixed boolean-arithmetic expressions |
82+
| 21 | `constant_value_splitting` | Split constants into arithmetic sums |
83+
| 22 | `constant_value_transformation` | Replace constants with global variable reads |
84+
85+
### Stack operation sub-variants (`--stackop`)
86+
87+
When using `stack_op_insertion`, you can select specific sub-variants with `--stackop`. If omitted, all 6 are applied.
88+
89+
| Flag | Description |
90+
| ---- | ------------------------------ |
91+
| `m` | memory/local/global operations |
92+
| `n` | arithmetic operations |
93+
| `b` | bitwise operations |
94+
| `c1` | type conversions (int/float) |
95+
| `c2` | floating-point conversions |
96+
| `f` | float operations |
97+
98+
Example: `swamped obfuscate input.wasm -o out.wasm -s stack_op_insertion --stackop m n b`
99+
100+
## Options
101+
102+
| Flag | Default | Description |
103+
| ------------ | ------- | ------------------------------------------------------------ |
104+
| `-s` || Strategy names, or `all` / `structural` / `code` |
105+
| `-e` || Exclude strategies (useful with `all`/`structural`/`code`) |
106+
| `-o` || Output path (`.wasm` or `.wast`) |
107+
| `--stackop` | all | Stack operation sub-variants: `m`, `n`, `b`, `c1`, `c2`, `f` |
108+
| `--ratio` | `1.0` | Fraction of targets to perturb |
109+
| `--alpha` | `1.0` | Beta-distribution alpha (target selection bias) |
110+
| `--beta` | `1.0` | Beta-distribution beta (target selection bias) |
111+
| `--validate` | off | Run `wasm-validate` on the output |
112+
113+
## Parameters
114+
115+
Defaults (`alpha=1, beta=1, ratio=1`) match the original project.
116+
117+
**`--ratio`** controls how much gets perturbed:
118+
119+
- `1.0` = everything (default), `0.5` = half, `0.1` = light
120+
121+
**`--alpha`** and **`--beta`** shape a [Beta distribution](https://en.wikipedia.org/wiki/Beta_distribution) that determines _where_ perturbations are applied within each function or section. Instead of picking targets purely at random, these parameters let you bias selection toward specific regions of the instruction sequence:
122+
123+
- `alpha=1, beta=1` — uniform distribution, all positions equally likely (default)
124+
- `alpha=1, beta=3` — skewed toward the beginning (early instructions are more likely to be perturbed)
125+
- `alpha=3, beta=1` — skewed toward the end (later instructions are more likely to be perturbed)
126+
- `alpha=2, beta=2` — bell-shaped, concentrates perturbations in the middle
127+
128+
If you just want to control how much gets changed, `--ratio` is enough. Use `--alpha`/`--beta` when you need finer control over the spatial distribution of perturbations.
129+
130+
## Preliminary tests
131+
132+
**Setup:** the `function_insertion` strategy requires a symlink `strategies/data/function_body.pkl` pointing to one of the precomputed pool files. Create it before running obfuscation:
133+
134+
```bash
135+
ln -s function_body_tmp100.pkl strategies/data/function_body.pkl
136+
```
137+
138+
Strategies could work correctly when applied individually.
139+
140+
Known issues:
141+
142+
- `function_body_cloning` + `function_insertion` — cloned proxy calls break when new functions shift indices
143+
- `data_encryption` — injected decryption function may have mismatched signatures on certain modules
144+
145+
Use `--validate` to catch failures, and `-e` to exclude problematic strategies:
146+
147+
```bash
148+
swamped obfuscate input.wasm -o out.wasm -s structural -e data_encryption function_body_cloning --validate
149+
```
150+
151+
## License
152+
153+
See [LICENSE](../LICENSE).

cli/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)