# The Vault
The challenge is a simple HTML file with a keypad that allows you to input 4 digit pin.The file loads `main.js` and calls `Module.ccall('validate')` to check the pin.
Upon beautifying the JS we see that it calls `run()` which in turns runs:
```javascriptpreRun();initRuntime();  // => __wasm_call_ctors => Module["asm"]["h"]preMain();callMain(args);  // => main => Module["asm"]["m"]postRun()```
We also note the following "library" mapping in `main.js`:
```javascriptvar asmLibraryArg = {    "e": banner,    "a": _emscripten_resize_heap,    "b": fail,    "d": get_password,    "c": win};```
The WASM binary format can be turned into "WebAssembly Text (`WAT`)" using e.g. https://webassembly.github.io/wabt/demo/wasm2wat/ and then we find the JS-imports in the top and the wasm-exports near the end of the file:
```lisp(module  ; ...  (import "a" "a" (func $a.a (type $t1)))  ; _emscripten_resize_heap  (import "a" "b" (func $a.b (type $t2)))  ; fail  (import "a" "c" (func $a.c (type $t3)))  ; win  (import "a" "d" (func $a.d (type $t0)))  ; get_password  (import "a" "e" (func $a.e (type $t2)))  ; banner
  ; __wasm_call_ctors  (func $h (type $t2)    nop)
  ; main  (func $m (type $t4) (param $p0 i32) (param $p1 i32) (result i32)    call $a.e    i32.const 0)
  ; ...  (export "h" (func $h))  (export "m" (func $m))  (export "n" (func $n)))```
During startup all the `.wasm` file does is to print this super awesome banner:
    WASM VAULT v0.1
    WASM VAULT v0.1
## Initial idea
The PIN is a maximum of 4 digit and checked locally, right? So it should be super easy to bruteforce;
 * Patch the `fail` function to remove all logic (and skip blocking `alert()`) * Run the following in the browser console:
```javascriptfor (let i = 0; i < 10_000; i++) {    document.getElementById('password').value = String(i).padStart(4, '0');    Module.ccall('validate');}```
... aaand it didn't work. Maybe I shouldn't pad with `0` ? Maybe I can't do multiple failing `validate` calls?
I had a lot of uncertainties and assumptions I needed to test, but the biggest takeaway that this is not the right idea, is that it would be way too easy to do a `for` loop and just bruteforce the PIN.
## Let the reversing begin
In `main.js` we see that `validate` maps to `$n` in the wasm file:
```lisp(func $n (type $t2)    (local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32)    global.get $g0  ; SP?    i32.const 32    i32.sub    local.tee $l0    global.set $g0    call $a.d      ; get_password    local.set $l1  ; $l1 = password    local.get $l0    i32.const 1720    i32.load16_u    i32.store16 offset=24    local.get $l0    i32.const 1712    i64.load    i64.store offset=16    local.get $l0    i32.const 1704    i64.load    i64.store offset=8    local.get $l0    i32.const 1696    i64.load    i64.store    block $B0      block $B1        local.get $l1        call $f7       ; strlen(password) ?        i32.const 4 i32.ne        br_if $B1        local.get $l1  ; $l1 = password        i32.load8_u        i32.const 112  ; 'p' i32.ne        br_if $B1        local.get $l1  ; $l1 = password        i32.load8_u offset=1        i32.const 51   ; '3' i32.ne        br_if $B1        local.get $l1  ; $l1 = password        i32.load8_u offset=2        i32.const 107  ; 'k' i32.ne        br_if $B1        local.get $l1  ; $l1 = password        i32.load8_u offset=3        i32.const 48   ; '0' i32.ne        br_if $B1        i32.const 22        local.set $l3        local.get $l0        local.set $l4        loop $L2          local.get $l4          local.get $l1          local.get $l2          i32.const 3          i32.and          i32.add          i32.load8_u          local.get $l3          i32.xor          i32.store8          local.get $l0          local.get $l2          i32.const 1          i32.add          local.tee $l2          i32.add          local.tee $l4          i32.load8_u          local.tee $l3          br_if $L2        end        local.get $l0        call $a.c  ; win        br $B0      end      call $a.b    ; fail    end    local.get $l0    i32.const 32    i32.add    global.set $g0)```
I did not get far before I saw `p3k0`... Not the PIN I was expecting, but it worked:
```javascriptdocument.getElementById('password').value = "p3k0";Module.ccall('validate');// You win! Here is you flag: flag{w45m_w4sm_wa5m_wasm}```