Rust-based tool for obfuscating WebAssembly code, enhancing security and protecting intellectual property. It enables sophisticated obfuscation for WebAssembly modules, utilizing multiple techniques such as control flow flattening, alias disruption, and more. All these methods, as well as their impact both in the original wasm module performance and the strength of the obfuscation is thoroughly explained in the paper Obfuscating the unreadable, a novel obfuscator for WebAssembly binaries, published in June of 2024.
In order to install the rust package you will need both Rust and Cargo installed, if you don't have them, check this link.
Then, after cloning the repository, run the following command:
cargo install --path .
WasmX can be utilized in two distinct ways: either programmatically through the SDK provided by the package or as a standalone console application.
wasmx [OPTIONS] <input-path> <output-path>
- Both input path of the WAT file and output path of the obfuscated WASM file are mandatory
| Short flag | Long flag | Description |
|---|---|---|
| -h | --help | It displays all the available options and requirements. |
| -V | --version | Displays wasmx version. |
| -v | --verbose | Turns on verbose mode (off by default). |
| -x | --all | Uses all the available obfuscation techniques with their default parameters. |
| -i | --identifiers | Encodes the wasm module identifiers (imports/exports names). It also generates a correspondence map. |
| -o | --opaquePredicates | It apply opaque predicates using the Collatz conjecture, in a the control flow flattening and bogus control flow jump flag, and in the alias disruption indirect function indexes. This only works if any of those techniques is applied. |
| -d | --removeDebug | Removes wasm module debugging information. (custom sections). |
| -e | --encrypt | Encrypts all loads and stores with custom methods in runtime. |
| -a | --alias | Replaces all direct function call (using call instruction) with indirect ones (call_indirect). |
| -c | --controlFlow | It performs control flow flattening in the provided module on function basis, it splits the code to the maximum possible, into basic code blocks. |
| -b | --bogusControlFLow | Applies a bogus layer of basic code blocks pointing to the actual real code blocks. This only works if control flattening is applied and it can be done recursively for a specified number of layers (the number of layers is mandatory.) |
- Example: Obfuscate the wasm module using control flow flattening and opaque predicates combined:
wasmx input.wat output.wasm -c -o
- Use the utilities module to read a WAT file and convert it to a Rust string:
let mut wat_content: String = String::new();
match read_file_to_string(file_path, Some("wat")) {
Ok(read_content) => wat_content = read_content.clone(),
Err(err) => {
eprint!("{} {}", "[ERROR] Reading input file in Test:".red(), err);
return Ok(());
}
}
- Use the parser from wast crate to return the wasm module object:
let parse_buffer: ParseBuffer<'_> = ParseBuffer::new(&wat_content)?;
let mut wat: Wat = parser::parse::<Wat>(&parse_buffer)?;
- Finally, apply the obfuscation techniques you desire:
match &mut wat {
Wat::Module(module) => {
// apply here
flatten_control_flow(module, false, 1, false);
remove_customs_section(module);
}
Wat::Component(_) => (),
}
WasmX © 2024 by Sérgio Rodrigues da Gama is licensed under CC BY-NC-ND 4.0 - LICENSE
