Reversing Web Assembly (WASM)

Aneesh Dogra
Aneesh Dogra’s Blog
3 min readDec 29, 2019

The challenge is a flag-checking-service written in web assembly. The flag must be in format hxp{…}. Our goal is to guess the correct flag. I hosted the challenge on my local setup; used Nginx and made sure .wasm files are served with the correct mime-type.

xmas_future

by benediktwerner

Most people just give you a present for christmas, hxp gives you a glorious future.

If you’re confused, simply extract the flag from this 山葵 and you shall understand. :)

xmas_future-265eb0be46555aad.tar.xz (15.5 KiB)

reverse wasm

The challenge is a flag-checking-service in web assembly. The flag must be in format hxp{…}. Our goal is to guess the correct flag. I hosted the challenge on my local setup; used Nginx and made sure .wasm files are served with the correct mime-type.

server {
listen 4301 default_server;
listen [::]:4301 default_server;
location = /hxp2019_bg.wasm {
types { } default_type "application/wasm";
add_header x-robots-tag "noindex, follow";
}
}

This will allow us to instantiate streaming and use Chrome’s debugger with stack variables, call stack, memory and all the information at our disposal.

I have hosted the challenge here. You can try along if you’d like.

Check in JS

The correct flag is compared against our input in javascript (hxp2019.js). The check function passes our input to wasm and calls a method in wasm namespace. While exploring wasm methods, I found a couple of to be interesting, like this one wasm-0002e886-4:

Wasm Check

We can set up a breakpoint and start executing. With a test flag “hxp{checkthis}”:

Debugging wasm

We can see the first jump “br_if” is a couple of instructions down at 1075. This first checks the input length of the string. Apparently, our input has to be 50 bytes in total. Let’s adjust our input and bypass this check.

check

Our input is placed from memory address 1179596->1179645. Later the program checks our input byte after byte in memory. It's easy to set up a breakpoint and check what’s being compared:

Wasm Xmas — Debugging in Chrome

i32.eq checks arguments on the stack. We can see 97 is being compared with 109.

109 ASCII

109 is ‘m’ in ASCII. Let's change our flag and put an m at first character after {. And run the app again.

We can see we bypassed the first check.

We have guessed our first byte. Continuing one more time. We get the next comparison:

2nd byte

101 is ‘e’ in ASCII. the flag starts with hxp{me….}. After a couple of mins of playing with the debugger and guessing the flag one byte at a time, we have recovered the flag.

Interesting challenge. First experience debugging web assembly. Thanks, hxp!

--

--

Written by Aneesh Dogra

Always been a tinker! Started coding in 2008 (when I was in 8th grade). Fell in love with x86 assembly, C and Linux: Manipulation of memory and getting RCE

No responses yet