Skip to content

How to Retrieve Randomized Export Names After WASMixer Obfuscation #8

@Owanesh

Description

@Owanesh

Hi WASMixer Team, i've a question about function that mangle the name of functions, specifically on a possible tool that helps to retrieve scrambled names to let $mixed_{wasm}$ usable.

As mentioned in WASMixer's paper available on arxiv

We offer an option to substitute random characters for $name_{export}$ .
It is worth noting that a small side effect of this obfuscating method is that it requires modifying outer modules to call the random strings instead of $name_{export}$ . Thus, we offer an auxiliary tool to assist developers to update the call to $name_{export}$ as the random string in its outer environment.

Now I am writing to you for that "tool" or function that I need to create a fully (automated) working example.

My enviroment is reported below:

source/
  |- sum.c
  |- sum.wat
  └- sum.wasm
mixer/
  |- sum.wat
  └- sum.wasm
sum.html

Source Code

//sum.c
int add(int a, int b) {
	return a + b;
}
  
// Dummy main to satisfy linker
int main() {
	return 0;
}

Compiling with Emscripten

emcc sum.c -O3 -s WASM=1 -s EXPORTED_FUNCTIONS="['_add']" -o sum.js

And as expected in sum.js we have

function assignWasmExports(wasmExports) {
	_add = Module["_add"] = wasmExports["c"];  👈
	wasmMemory = wasmExports["a"];
	wasmTable = wasmExports["__indirect_function_table"]
}

and we have in .wat (wasm2wat sum.wasm -o sum.wat ) [here is full .wat file, to reproduce the issue]

(module
  (type (;0;) (func (param i32 i32) (result i32)))
  (type (;1;) (func))
  (func (;0;) (type 0) (param i32 i32) (result i32)
    local.get 0
    local.get 1
    i32.add)
  (func (;1;) (type 1))
  (memory (;0;) 258 258)
  (export "a" (memory 0))
  (export "b" (func 1))
  (export "c" (func 0)))   👈

Let's Mix

python main.py --name ../../mixer_name_sample_issue/mixer/sum.wasm

	type start=8
	type end=20
	func start=20
	func end=25
	mem start=25
	mem end=33
	export start=33
	export end=48
	code start=48
	code end=62
	Obfuscated binary saved as ../../mixer_name_sample_issue/mixer/sum.wasm.

and we obtain

tail -n 6 mixer/sum.wat
    i32.add)
  (func (;1;) (type 1))
  (memory (;0;) 258 258)
  (export "a" (memory 0))
  (export "b" (func 1))
  (export "q" (func 0)))  👈(?)

Now I’m stuck — I need to modify sum.js manually. Right now it’s still manageable since there’s only one function (and three exports), so I can easily tell which function is which.
But once there are many functions with random names, it’ll be almost impossible to figure them out without a lot of trial and error.

Question:
Is it possible to retrieve a randomly generated name and its original counterpart?
Is the tool mentioned in the paper accessible through a specific code snippet?

I believe there’s some kind of “hash map” or table that associates the original name with its corresponding function (although this information might be generated at runtime to prevent static analyzers from detecting tokens based on those names).
I’ve looked through the code but couldn’t find that tool — apologies if I missed it somewhere, or if the tool in question is meant in a different way than I understood

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions