Flare-On 5 CTF WriteUp (Part 3)

. 6 min read

This is part 3 of the Flare-On 5 CTF writeup series.

5 - Web 2.0

The future of the internet is here, again. This next challenge will showcase some the exciting new technologies paving the information super-highway for the next generation.

Similar to the fourth, the fifth challenge is also based on Web technologies - HTML, Javascript and ... Web Assembly (WASM). Web Assembly is quite new and its usage is fairly limited but increasing nevertheless. As its name suggests, WASM allows to execute assembly code on the browser, but it doesn't mean traditional assembly languages like x86, ARM and MIPS we're familiar with. Instead, WASM defines an entirely new binary format with its own instruction set to be run on a stack-based virtual machine in the browser. WASM comes with the promise that it will provide near-native performance as a desktop app running on the user's system.

Let's go back to the challenge. We've three files index.html, main.js and test.wasm. Before WASM can be executed on the browser there are some tasks that must be done beforehand like setting up an interface so that the WASM code can interact with the JS code, setting up arguments for function calls, converting JS values such that WASM can operate on that etc. All of this is done by main.js.


It reads a URL parameter q and converts it to a Uint8Array of bytes. It allocates two 0x200 bytes memory block within the WASM instance. One of them is filled with an array of byte values declared at the start. The other is filled with the bytes of the URL parameter q. Next, it calls a function named Match exported from the WASM code with the proper arguments. It's evident the URL parameter q is the flag. If the function returns 1, our flag is correct.

Analyzing the WASM code in JEB decompiler

JEB decompiler from PNF Software can analyze WASM binaries. The demo version is good enough at least for a basic analysis.


Apart from Match, JEB identified nine other functions from f1 to f9. Besides, there's another function writev_c. Let's have a look at Match.


The signature specifies it takes four i32 parameters and returns an i32 value as output. We already had found out this information by analyzing the JS code. Unlike regular native executables, the WASM binary format also describes the signature and number of local variables of each and every function. For example, Match has 24 locals inclusive of the four parameters. Have a look at this document to know in-depth about the WASM format.

WASM is a stack-based virtual machine like CPython. There are no registers. All operations must be done by pushing and popping values off the stack. For example, adding two numbers is achieved by pushing the values; the i32.add instruction pops off the topmost two values, adds them and pushes the result back on the stack.

For experimenting with Web Assembly, try out WasmExplorer and WebAssembly Studio.

Match calls f9 and based on its return value either returns 1 or 0. So essentially the check is performed in f9.


Using the WebAssembly Binary Toolkit

The WebAssembly Binary Toolkit (WABT) provides several useful tools to work on WebAssembly. Among them is wasm2c which aims to convert a wasm binary to equivalent C source with a header. It is not a true decompiler but rather converts the WASM instructions to equivalent C code.

After running wasm2c on test.wasm, the C code for Match looks like.

static u32 Match(u32 p0, u32 p1, u32 p2, u32 p3) {
  u32 l0 = 0, l1 = 0, l2 = 0, l3 = 0, l4 = 0, l5 = 0, l6 = 0, l7 = 0, 
      l8 = 0, l9 = 0, l10 = 0, l11 = 0, l12 = 0, l13 = 0, l14 = 0, l15 = 0, 
      l16 = 0, l17 = 0, l18 = 0, l19 = 0, l20 = 0, l21 = 0, l22 = 0, l23 = 0;
  u32 i0, i1, i2, i3, i4;
  i0 = g0;
  l0 = i0;
  i0 = 32u;
  l1 = i0;

  i0 = l2;
  i1 = p1;
  i32_store((&memory), (u64)(i0 + 20), i1);
  i0 = l2;
  i1 = p2;
  i32_store((&memory), (u64)(i0 + 16), i1);
  i0 = i32_load8_u((&memory), (u64)(i0 + 11));
  l18 = i0;
  i0 = 1u;
  l19 = i0;
  i0 = l18;
  i1 = l19;
  i0 &= i1;
  l20 = i0;
  i0 = l2;
  i1 = l20;
  i32_store((&memory), (u64)(i0 + 28), i1);
  i0 += i1;
  l23 = i0;
  i0 = l23;
  g0 = i0;
  i0 = l21;
  goto Bfunc;
  return i0;

All assignment and arithmetic operations have been converted to their C equivalent. Additionally, wasm2c introduced some helper functions like i32_load and i32_store since they no C equivalent. However, the code is still far away from being fit for analysis. It would be nice if we can optimize the code.

We don't want to optimize by hand. That's the work of a compiler. However, we need to provide a main function before we can run gcc.


Compiling with we get an x86 ELF. Decompiling the file using HexRays in IDA, f9 looks like


This is a lot better than what we obtained with wasm2c. If we analyze the WASM code of f9 we can see it there's a CALL_INDIRECT instruction. This translates to the following C snippet.


Immediately below there's a comparison between a character of our input to the value calculated by the above indirect function call.


This means if set a breakpoint at this location we may be able to retrieve the flag character by character. However, we need to do this in the WASM code and not in the ELF as the decompiled wasm2c code may not have the exact behaviour as the WASM binary.

Debugging WASM in Firefox

Firefox offers the ability to debug WASM code. First, we need to set up a local web server which can be done using $ python -m SimpleHTTPServer or something like https://github.com/m3ng9i/ran.

With Firefox and the web server setup let's identify the proper location in the WASM code which implements the comparison of the correct byte with that of the flag.

The CALL_INDIRECT instruction is located at B7F.


The comparison instruction must be located after this. Indeed, a few lines below we do find an i32.eq instruction which performs a sign agnostic equality check.


Let's set a breakpoint here and rerun with a known flag as input like


When the breakpoint hits we can see the instruction is essentially comparing the values of var82 and var83 which are loaded on the stack just before. var83 contains 97 (a) the first character of our input. This is being compared to 119 (w). This suggests the first character of the flag is w. Proceeding in the same fashion we can retrieve the entire flag character by character.


FLAG: wasm_rulez_js_droolz@flare-on.com

Continue to the next part: Flare-on 5 CTF Write-up (Part 4)


Reverse Engineer with an interest in low level stuff and anything about security.

Get IoT Security Training

IoT Pentesting Exploitation Training


Android android application security android hands on security and exploitation training android security Apktool application auditing application security auditing appsec usa appwatch attify attify badge attify training binwalk blackberry pentesting blackhat ble BLE hacking and exploitation BLE sniffing box brut Exception chroot cloud based mobile application security scanner consulting CTF Damn Vulnerable iOS App devops dumping memory embedded hacking exploitation exploiting smart devices Firmware hacking frida hackfest hacking smart devices how to secure iot device IDA internet of things Internet of Things Security ios application security ios security iot iot device IoT Exploitation iot hacking iot pentest iot pentesting iot security iot security training iotsecurity jtag jtag debugging mobile app mobile application security mobile application security testing mobile security ninja recon technique offensive iot exploitation ola cabs owasp owasp appsec penetration testing pentesting pentesting mobile apps powerofcommunity PrinterSecurity qemu quizup radio communication protocol radio coomunication Reversing sdr secure coding guidelines security security issue security services security training security vulnerability smart devices social networking spi threat modeling training uart vulnerability writeups xposed hooking zigbee zigbee exploitation zigbee security zwave firmware reverse engineering firmware emulation firmware analysis toolkit firmadyne getting started with firmware hacking iot penetration testing iot attacks recent iot attacks cyber attacks iot hacks biggest iot attacks of all time hacked smart devices iot bots, malwares latest iot attacks BtleJuice bleah retail iot challenges in iot retail security issues faced by e-retailers network security in retail DDoS attacks phishing attacks how retail can prevent cyber attacks security challenges in retail IoT Flare-on radio waves hacking arduino nano how to hack radio waves analog modulation digital modulation capture radio traffic bluetooth technology BLE vulnerabilities BLE attacks BLE dangers BLE security issues exploiting ble how to exploit ble tools to exploit ble privacy protection iot threats protect against iot threats dangers of iot smart user security how to protect iot devices monitor iot devices internet security safety measures to protect privacy healthcare iot iot threats to healthcare industry how can healthcare fight iot threats healthcare cyber security prevent cyber attacks on healthcare measures to prevent cyber attacks on healthcare organisations steps to prevent iot attacks on healthcare healthcare business protection against iot threats security in healthcare iot recent cyber attacks recent ARM attacks ARM course ARM Training ARM binaries Exploit ARM devices IoT hacks on ARM devices ARM gadgets learn ARM exploitation Mirai Botnet vulnerable ARM devices arm ARM exploitation book ARM exploitation video training guide to ARM exploitation cybersecurity why you should be a cybersecurity expert professional expert career in cybersecurity why choose career in cybersecurity growth potential penetration testers hackers profession