# hxp 36C3 CTF - xmas_future
>###### tags: `wasm`
>[name=whysw@PLUS]
## Attachments
- problem
- [hxp2019.js](https://gist.github.com/YangSeungWon/080959d7e3d34b4bcdd6c9bc381dca86#file-hxp2019-js)
- [ferris.svg](https://gist.github.com/YangSeungWon/080959d7e3d34b4bcdd6c9bc381dca86#file-ferris-svg)
- [hxp2019_bg.wasm](https://gist.github.com/YangSeungWon/080959d7e3d34b4bcdd6c9bc381dca86#file-hxp2019_bg-wasm)
- [index.html](https://gist.github.com/YangSeungWon/080959d7e3d34b4bcdd6c9bc381dca86#file-index-html)
- [run.sh](https://gist.github.com/YangSeungWon/080959d7e3d34b4bcdd6c9bc381dca86#file-run-sh)
- [wasm.svg](https://gist.github.com/YangSeungWon/080959d7e3d34b4bcdd6c9bc381dca86#file-wasm-svg)
- writeup
- [hxp2019_bg.wat](https://gist.github.com/YangSeungWon/080959d7e3d34b4bcdd6c9bc381dca86#file-hxp2019_bg-wat)
- [hxp2019_bg.c](https://gist.github.com/YangSeungWon/080959d7e3d34b4bcdd6c9bc381dca86#file-hxp2019_bg-c)
- [hxp2019_bg.h](https://gist.github.com/YangSeungWon/080959d7e3d34b4bcdd6c9bc381dca86#file-hxp2019_bg-h)
- [main.c](https://gist.github.com/YangSeungWon/080959d7e3d34b4bcdd6c9bc381dca86#file-main-c)
- [sol.py](https://gist.github.com/YangSeungWon/080959d7e3d34b4bcdd6c9bc381dca86#file-sol-py)
- [xmas_future](https://gist.github.com/YangSeungWon/080959d7e3d34b4bcdd6c9bc381dca86#file-xmas_future)(ELF)
Attachments are uploaded on [gist](https://gist.github.com/YangSeungWon/080959d7e3d34b4bcdd6c9bc381dca86).
## Challenge
![](https://i.imgur.com/PXoy05n.png)
When you press the *Check* button, `check` function is called and `check` function in wasm is also called.
```javascript:hxp2019.js=66
/**
* @param {string} pwd
* @returns {bool}
*/
export function check(pwd) {
var ptr0 = passStringToWasm0(pwd, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
var len0 = WASM_VECTOR_LEN;
var ret = wasm.check(ptr0, len0);
return ret !== 0;
}
```
## Solution
### Dynamic debugging
```wasm:hxp2019_bg.wat=1958
(func $hxp2019::check::h578f31d490e10a31 (;4;) (param $var0 i32) (param $var1 i32) (result i32)
(local $var2 i32) (local $var3 i32) (local $var4 i32) (local $var5 i32) (local $var6 i32) (local $var7 i32) (local $var8 i32) (local $var9 i32) (local $var10 i32)
get_global $global0
i32.const 32
i32.sub
tee_local $var2
set_global $global0
i32.const 0
set_local $var3
block $label0
get_local $var1
i32.const 50
i32.ne
br_if $label0
```
...
```wasm:hxp2019_bg.wat=2281
end
local.get 2
i32.const 32
i32.add
global.set 0
local.get 3)
```
$var0 is ptr to input string, and $var1 is length of input string. so flag length must be 50!
---
### make ELF file
#### wasm2c
$ ~/tools/wabt/build/wasm2c hxp2019_bg.wasm --no-debug-names -o hxp2019_bg.c
Outputs are `hxp2019_bg.c` and `hxp2019_bg.h`.
For compilation, I fixed relative path of wasm-rt.h in `hxp2019_bg.h` to absolute path.
```c:hxp2019_bg.h=9
#include "/home/whysw/tools/wabt/wasm2c/wasm-rt.h"
```
#### main.c
I searched for memory allocation for wasm, and found this one.
[Flare-On 5 CTF WriteUp (Part 3)](https://blog.attify.com/flare-on-5-writeup-part3/)
```c:main.c=
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hxp2019_bg.h"
int main(int argc, char** argv) {
/* Make sure there is only one command-line argument, and length id 50.*/
if (argc != 2) return 1;
if (strlen(argv[1]) != 50) return 1;
init();
memcpy(&(Z_memory->data[10000]), argv[1], 50);
u32 result = Z_checkZ_iii(10000, 50);
if(result == 0)
printf("fail\n");
else
printf("success\n");
return 0;
}
```
#### compile
$ gcc hxp2019_bg.c ~/tools/wabt/wasm2c/wasm-rt-impl.c main.c -o xmas_future
---
### gdb scripting
![](https://i.imgur.com/Xa8P8AX.png)
![](https://i.imgur.com/hMqm2gI.png)
When the input character is different from the flag character, it goes to red block and break. But when it's correct, it goes to green block and continue the loop.
It means that if we set a breakpoint at 0x4065B5, the program stops when each character is right. So I decided to do gdb scripting.
```python:sol.py=
#!usr/bin/python
import gdb
import string
FILE_NAME = 'xmas_future'
BREAK_ADDR = '0x4065B5'
LEN = 50
count = 0;
class BP_Manager(gdb.Breakpoint):
def stop(self):
global count
count += 1
return;
gdb.execute("file {}".format(FILE_NAME))
bp_addr = BP_Manager("*"+BREAK_ADDR)
answer = "hxp{,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,}"
trial_pos = 4
while trial_pos < LEN-1:
for ch in string.digits+string.ascii_letters+'!.,{_/}':
count = 0
trial = answer[:trial_pos] + ch + answer[trial_pos+1:]
gdb.execute("r $(python -c \"print '{}'\")".format(trial))
if count == trial_pos -4 +1:
answer = trial
print("FLAG:",answer)
trial_pos += 1
break
```
$ gdb -x sol.py
output : `FLAG: hxp{merry_xmas___github.com/benediktwerner/rewasm}`