Intercepting & monitoring Windows API calls to find a flag in a hidden buffer
Challenge Info
I’ve been learning more Windows API functions to do my bidding. Hmm… I swear this program was supposed to create a file and write the flag directly to the file. Can you try and intercept the file writing function to see what went wrong?
Download the exe here. Unzip the archive with the password picoctf
Basic forensics & info
1 2 3 4
C:\Users\river\Desktop\ctf\pico\BinaryInstrumentation2>file bininst2.exe bininst2.exe: PE32+ executable (console) x86-64, for MS Windows
FLARE-VM Sun 05/04/2025 4:11:07.21
file doesn’t yield anything unexpected/unusual. Additionally, the program produces no output when ran:
A logical attempt would be to run the same frida-trace command as used in the previous challenge, in which we’d target the Sleep call and then inspect Sleep.js for anything odd. However, this is not the case with this challenge, as the Sleep.js in both DLL folders looks normal.
Overkill frida-trace
1
frida-trace -f bininst2.exe -i "*"
Traces ALL API calls from every library
-i "*" means intercept everything
This frida-trace command may look good at a glance, as it traces everything, but this actually works against us. The reason being, is that 99% of the handlers aren’t relevant to solving the challenge, and this will just lead to information overload.
Specific frida-trace
Knowing that this is a CTF, it’s possible the flag is being written/read from a file, so we can try something like this:
1
frida-trace -i *File* -f bininst2.exe -X KERNEL32
Only traces APIs that contain “File” in their name (CreateFile, ReadFile, WriteFile)
-X KERNEL32 excludes KERNDEL32.dll APIs
This command, unlike the previous one, is much more focused and less noisy, as it focuses our scope on only the necessary.
Started tracing 547 functions. Web UI available at http://localhost:51013/ /* TID 0x18bc */ 501 ms NtDeviceIoControlFile() 501 ms RtlDosApplyFileIsolationRedirection_Ustr() 501 ms RtlDosApplyFileIsolationRedirection_Ustr() 501 ms RtlDosApplyFileIsolationRedirection_Ustr() 501 ms NtQueryAttributesFile() 501 ms NtQueryAttributesFile() 501 ms NtOpenFile() 501 ms RtlDosApplyFileIsolationRedirection_Ustr() 511 ms GetSystemTimeAsFileTime() 511 ms | GetSystemTimeAsFileTime() 511 ms GetModuleFileNameW() 511 ms | GetModuleFileNameW() 511 ms AreFileApisANSI() 511 ms | AreFileApisANSI() 511 ms CreateFileA() 511 ms | CreateFileA() Process terminated
FLARE-VM Sun 05/04/2025 4:46:25.91
The output shows us that the program is utilizing CreateFileA(). However, upon inspecting CreateFileA() we see a very basic configuration, before modifying it to try and get more information, it’s important to understand what we can do:
A quick search led me to this Microsoft page, which shows the syntax for the CreateFileA function. I’ll also leave it below for your convenience:
Started tracing 4 functions. Web UI available at http://localhost:64949/ /* TID 0x1a40 */ 19 ms CreateFileA() 19 ms | CreateFileA called with filename: "<Insert path here>" 19 ms CreateFileA returned: 0xffffffffffffffff Process terminated```
The program is calling CreateFileA with an invalid filename: ``”“` - this is clearly a placeholder that wasn’t properly replaced with a real path
CreateFileA returned 0xffffffffffffffff, which is -1 or INVALID_HANDLE_VALUE, confirming that file creation failed
The process terminated right after this, suggesting that the flag is being processed but never successfully written to a file
This lead me to further edit CreateFileA, but this time, let’s try replacing ““ with a valid filename (“flag.txt”)
Started tracing 2 functions. Web UI available at http://localhost:49254/ /* TID 0xb4c */ 20 ms CreateFileA() 20 ms | CreateFileA - Original path: "<Insert path here>" 20 ms | CreateFileA - Replaced with: "flag.txt" 20 ms CreateFileA returned: 0x274 Process terminated
However, upon checking the newly created flag.txt, you’ll notice it’s empty… but this is okay. Since CreateFileA is succeeding, that means it has to be calling WriteFile. So, let’s try modifying the WriteFile handler to see if we can intercept the data it’s attempting to write.
WriteFile modification & solution
We can set up a WriteFile handler to try and intercept the flag: