Description
What can you do with a file that has been WebAssembly compiled? Find the flag on the website.
Setup
Open the challenge URL in your browser.
# Open the challenge URL in your browser with DevTools open (F12)Solution
Walk me through it- Step 1Find and download the WASM binaryOpen DevTools > Network and reload. Look for a request with Content-Type application/wasm or a
.wasmURL. If no.wasmrequest appears, search the page source (Ctrl+U) fordata:application/wasmor a base64 blob - some pages inline the module instead of fetching it.Learn more
WebAssembly (WASM) is a binary instruction format designed for execution in web browsers alongside JavaScript. It compiles from languages like C, C++, or Rust and runs at near-native speed. WASM modules are fetched over HTTP just like JavaScript files - they appear in the Network tab as requests with Content-Type
application/wasm.Why WASM is used in CTF challenges: Developers sometimes compile validation logic to WASM thinking it is harder to reverse-engineer than JavaScript. In practice, WASM is just as reversible as any compiled binary - the WAT format is a full lossless representation, and tools like Ghidra (with the WASM plugin) or wabt can decompile it entirely. The security model of WASM is about sandboxing (preventing access to the host OS), not obfuscation.
Finding the WASM file if the Network tab is unclear: Look at the page's JavaScript source for calls to
WebAssembly.instantiateStreaming(fetch('...'))orWebAssembly.instantiate(buffer)- the first argument is the URL of the WASM binary. Alternatively, search the page source for.wasmto find the filename directly. - Step 2Decompile the WASM to WAT text formatUse wasm2wat (from the WebAssembly Binary Toolkit, WABT) to convert the binary WASM file to its human-readable WAT (WebAssembly Text Format) equivalent. Search the output for the picoCTF string.bash
# Install WABT (WebAssembly Binary Toolkit):bashsudo apt install wabt # or download from github.com/WebAssembly/wabtbashbashwasm2wat xSAR1.wasm -o xSAR1.watbashgrep 'picoCTF{' xSAR1.watbash# If grep finds nothing, the flag is byte-checked rather than stored as a literal -bash# trace the comparison loop in the validation function (see SAR2/SAR3 patterns).Learn more
WAT (WebAssembly Text Format) is the textual representation of WASM bytecode. It uses S-expression syntax (like Lisp) and is fully reversible from WASM - no information is lost in decompilation. String literals from the original source code are embedded as
datasegments in the WASM binary and appear verbatim in the WAT output.This is a fundamental property of compiled languages: string constants survive compilation. Strings like flag values, error messages, and format strings are stored in the data section of the binary and can be extracted with tools like
strings,wasm2wat, or a hex editor. Always search compiled binaries for string literals before attempting deeper reverse engineering.Structure of a WASM module: A WASM binary is organized into sections: type (function signatures), import (external JS functions the module calls), function (index-to-type mapping), memory (linear memory size), export (functions/memory exposed to JS), code (the actual bytecode), and data (initialized memory content including string literals). The data section is where the flag lives - it is essentially the
.rodatasection of the compiled binary, embedded verbatim in the WASM file.For harder WASM challenges: When the flag is not a simple string constant but is instead computed or compared byte-by-byte, you need to trace the WASM logic. Use the browser's built-in WASM debugger (Chrome DevTools supports WASM breakpoints and DWARF debug info), or load the WASM file in Ghidra with the WASM plugin to get a C-like decompilation of the validation function. Understanding the data flow from user input to the comparison is the same skill as binary reverse engineering.
Flag
picoCTF{...}
WebAssembly binaries compile to a readable WAT text format - string constants in the original source survive compilation and are visible in decompiled output.