# WASM (rev)

{% file src="/files/iwjZVHsS06a3jHhSN2tI" %}

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!!}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://elijahchia.gitbook.io/ctf-blog/cddc-qualifiers-2024/wasm-rev.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
