Description
What is in this web assembly? Find the flag hidden in the WASM module loaded by the challenge page.
Setup
Open the challenge URL in your browser with DevTools open.
# Open DevTools with F12 and navigate to the Network tab before loading the pageSolution
Walk me through it- Step 1Download the WASM file from the Network tabIn DevTools > Network, reload the page and look for a request with Content-Type application/wasm or a .wasm extension. Right-click and save the file.
Learn more
Unlike Some Assembly Required 1, the flag in this challenge is not stored as a plaintext string. Instead, it is XOR-encoded in the WASM data section. A runtime function decodes it on the fly during the validation check. You need to identify both the encoded data and the XOR key.
- Step 2Decompile the WASM to WATUse wasm2wat to convert the binary to readable text format. Search for data segments and the XOR logic in the validation function.bash
wasm2wat xSAR2.wasm -o xSAR2.watbashgrep -n 'i32.xor\|data\|pico' xSAR2.watLearn more
In the WAT output, look for a
datasegment near the bottom of the file - this is the encoded flag. Then find the validation function (often named something like$checkor indexed asfunc 2). Trace through the logic to find where the XOR operation occurs and what value is used as the key.WAT XOR pattern: A XOR loop in WAT looks like a series of
i32.load8_u,i32.const <key>,i32.xor, andi32.store8instructions. The key is thei32.constimmediately precedingi32.xor(ori64.xor). If the key is not an inline constant, trace backwards from the XOR instruction - the value being XORed comes from somewhere (a local, another load, a function argument), and walking the data flow reveals the source.Data segment offset. A WAT data segment looks like
(data (i32.const 1024) "...")- the encoded bytes start at memory offset 1024 in this example. Inside the segment, byte literals are written as\41\42\43for the bytes[0x41, 0x42, 0x43]. Match the offset to where the validation function reads from to confirm you are looking at the right segment. - Step 3Decode the XOR-encoded flagExtract the encoded bytes from the data segment and XOR each byte with the discovered key to recover the plaintext flag.python
python3 - <<'EOF' # Paste the encoded bytes from the WAT data segment here encoded = bytes([0x??, 0x??, ...]) # Replace with actual bytes key = 0x?? # Replace with XOR key from WAT flag = bytes(b ^ key for b in encoded) print(flag.decode()) EOFLearn more
XOR encoding is trivially reversible: if
encoded = plaintext XOR key, thenplaintext = encoded XOR key. Applying the same key twice returns the original value, making XOR its own inverse. This makes XOR useless as an encryption scheme when the key is static and embedded in the binary - the "obfuscation" only protects against a raw strings search, not actual analysis.
Flag
picoCTF{...}
The flag was XOR-encoded in the WASM data segment - decompiling to WAT reveals both the encoded bytes and the XOR key, making decoding trivial.