Binary Instrumentation 2

Published: April 2, 2025

Description

A follow-up Windows binary supposedly writes the flag to disk via API hooks. In practice, the executable still leaks a Base64 flag in its strings section.

Unzip bininst2.zip (password: picoctf) to obtain bininst2.exe.

Use strings or binwalk -e to inspect the binary for Base64 chunks beginning with cGljb0NUR.

wget https://challenge-files.picoctf.net/.../bininst2.zip
unzip bininst2.zip # password: picoctf
strings bininst2.exe | grep cGljb0NUR | base64 -d

Solution

  1. Step 1Hunt for the payload
    Even without Frida, running strings (optionally against extracted sections) reveals `cGljb0NURntmcjFkYV9mMHJf...`. That Base64 string encodes the flag.
    Learn more

    Frida is a dynamic binary instrumentation framework used extensively in security research and reverse engineering. It lets you inject JavaScript snippets into a running process and intercept function calls at the native level. For Windows executables, typical hooks target Win32 API calls like CreateFileW, WriteFile, ReadFile, and messaging functions to observe what data flows through them at runtime.

    The intended approach for this challenge was to hook CreateFile and WriteFile API calls so that when the binary tries to write the flag to disk, Frida captures the buffer before it is written - without the analyst ever needing to find the actual file on disk. This technique is powerful for analyzing malware that encrypts output or writes to unusual locations.

    However, the binary inadvertently left the Base64 string in its .rdata section (read-only data), which holds compile-time constants. This is a common mistake: developers sometimes construct flags or keys at compile time and forget that static analysis tools expose everything in the binary's data sections. Proper secret handling requires generating secrets at runtime or fetching them from a protected external source.

    The prefix cGljb0NUR is the Base64 encoding of picoCTF - a reliable fingerprint for quickly spotting encoded picoCTF flags across any binary or network capture.

  2. Step 2Decode to finish
    Pipe the Base64 blob into base64 -d (or CyberChef) to retrieve picoCTF{fr1da_f0r_b1n_in5trum3nt4tion!...}.
    Learn more

    Piping shell commands together with | (the pipe operator) lets you chain transformations without intermediate files. The idiom strings binary | grep pattern | base64 -d is a three-stage pipeline: extract printable strings, filter for those matching a pattern, then decode the first result. This one-liner approach is standard in CTF workflows and in real incident response.

    Note that base64 -d on Linux expects the input to be a continuous Base64 string, so if grep returns multiple lines you may need to select just one. On macOS the flag is base64 -D (capital D). CyberChef handles multi-line input and partial strings gracefully, making it the preferred tool when the exact input format is uncertain.

    For analysts learning dynamic instrumentation, the proper Frida workflow for a challenge like this would be: install Frida (pip install frida-tools), attach to the process with frida bininst2.exe, and use a JavaScript snippet like Interceptor.attach(Module.getExportByName('kernel32.dll', 'CreateFileW'), { onEnter(args) { console.log(args[0].readUtf16String()); } }) to log file paths being opened for writing.

Flag

picoCTF{fr1da_f0r_b1n_in5trum3nt4tion!_b21a...}

The intended path was to instrument CreateFile/WriteFile via Frida, but static decoding works too.

Want more picoCTF 2025 writeups?

Useful tools for Reverse Engineering

Related reading

What to try next