# WASM (rev)

{% file src="<https://243380073-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FBIa0PcXGYuP6chd3J1Ry%2Fuploads%2FvFsRiTL8uPisjFj5CLHE%2Fscript.js?alt=media&token=2a5225aa-5f56-4a1a-8360-6acd2fe48382>" %}

We are given an encryption script which contains the following code:

```javascript
function strToBytes(str) {
    const bytes = new Uint8Array(str.length);
    for (let i = 0; i < str.length; i++)
      bytes[i] = str.charCodeAt(i);
    return bytes;
  }
  
  const wasmBuffer = new Uint8Array([0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x01, 0x60, 0x01, 0x7f, 0x00, 0x02, 0x09, 0x01, 0x00, 0x03, 0x6d, 0x65, 0x6d, 0x02, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x07, 0x0a, 0x01, 0x06, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x00, 0x00, 0x0a, 0x64, 0x01, 0x62, 0x02, 0x04, 0x7f, 0x01, 0x7c, 0x02, 0x40, 0x41, 0x00, 0x21, 0x01, 0x03, 0x40, 0x20, 0x01, 0x20, 0x00, 0x41, 0x01, 0x6b, 0x4e, 0x0d, 0x01, 0x02, 0x40, 0x20, 0x01, 0x21, 0x02, 0x03, 0x40, 0x20, 0x02, 0x20, 0x00, 0x41, 0x01, 0x6b, 0x4e, 0x0d, 0x01, 0x20, 0x02, 0x2d, 0x00, 0x00, 0x21, 0x03, 0x20, 0x02, 0x41, 0x01, 0x6a, 0x2d, 0x00, 0x00, 0x21, 0x04, 0x20, 0x03, 0x20, 0x04, 0x73, 0x21, 0x04, 0x20, 0x02, 0x41, 0x01, 0x6a, 0x20, 0x04, 0x3a, 0x00, 0x00, 0x20, 0x02, 0x41, 0x01, 0x6a, 0x21, 0x02, 0x0c, 0x00, 0x0b, 0x0b, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x0c, 0x00, 0x0b, 0x0b, 0x0b]).buffer;
  
  const importObject = {
    "": {
      mem: new WebAssembly.Memory({ initial: 1 }),
    }
  };
  
  WebAssembly.instantiate(wasmBuffer, importObject)
  .then(({ instance }) => {
    let memArr = new Uint8Array(importObject[""].mem.buffer);
    let flagArr = strToBytes('THIS_IS_A_FAKE_FLAG');
  
    for (let i = 0; i < flagArr.length; i++)
      memArr[i] = flagArr[i];
    instance.exports.encode(flagArr.length);
    let result = "";
    for (let i = 0; i < flagArr.length; i++) {
      result += ("00" + memArr[i].toString(0x10)).slice(-2);
    }
      
    console.log(result); # 571653080c6e350c6b0f01196d06436075756365
  });
```

It uses `WebAssembly.instantiate` to create a WebAssembly instance. Then, each encoded character is appending to `result`. We then receive the `result`.&#x20;

After some googling, I realised that the bytes given as `wasmBuffer` is actually a WebAssembly payload which exports a function called `encode`. After using the `wasm2wat` tool, I get the following web assembly:

```wasm
(module
  (type $t0 (func (param i32)))
  (import "" "mem" (memory $.mem 0))
  (func $encode (export "encode") (type $t0) (param $p0 i32)
    (local $l1 i32) (local $l2 i32) (local $l3 i32) (local $l4 i32) (local $l5 f64)
    (block $B0
      (local.set $l1
        (i32.const 0))
      (loop $L1
        (br_if $B0
          (i32.ge_s
            (local.get $l1)
            (i32.sub
              (local.get $p0)
              (i32.const 1)))) 
        (block $B2
          (local.set $l2
            (local.get $l1))
          (loop $L3
            (br_if $B2
              (i32.ge_s
                (local.get $l2)
                (i32.sub
                  (local.get $p0)
                  (i32.const 1))))
            (local.set $l3
              (i32.load8_u
                (local.get $l2)))
            (local.set $l4
              (i32.load8_u
                (i32.add
                  (local.get $l2)
                  (i32.const 1))))
            (local.set $l4
              (i32.xor
                (local.get $l3)
                (local.get $l4)))
            (i32.store8
              (i32.add
                (local.get $l2)
                (i32.const 1))
              (local.get $l4))
            (local.set $l2
              (i32.add
                (local.get $l2)
                (i32.const 1)))
            (br $L3)))
        (local.set $l1
          (i32.add
            (local.get $l1)
            (i32.const 1)))
        (br $L1)))))
```

I asked chatGPT to convert this into Python and got the following encoding function:

```python
def encode(data):
    for i in range(len(data) - 1):
        for j in range(i, len(data) - 1):
            data[j + 1] = data[j] ^ data[j + 1]
    return data
```

The encoding function iterates `i` from from the `0` to `n - 1`, and for each `i` it iterates `j` from `i` to `n - 1`. For each `j` value, the element at index `j + 1` is XOR'd with the element at index `j`. To decode this function we can do the XOR operations in the reverse order.

```python
x = "571653080c6e350c6b0f01196d06436075756365"

ct = [x[i:i+2] for i in range(0, len(x), 2)] # create an array of hex strings
n = len(ct)
for i in range(0, n):
    ct[i] = int(ct[i], 16) # convert hex values to ints
for i in range(n - 2, -1, -1):
    for j in range(n - 2, i - 1, -1):
        ct[j + 1] ^= ct[j] # decode
for i in range(0, n):
    ct[i] = chr(ct[i])
print(ct) # CDDC24{WASM_15_R34LY_C00L!!}
```
