Description
A 32-bit Windows PE binary that runs on Linux under Wine. Reverse-engineer the password check in Ghidra and supply the correct input to print the flag.
Setup
Download the Windows PE binary from the challenge.
Install Wine. For a 32-bit PE on a 64-bit host, configure a 32-bit prefix once with WINEARCH=win32 WINEPREFIX=~/.wine32 winecfg, then run subsequent commands with the same env vars exported.
Open the binary in Ghidra: it auto-detects PE format on import, so no manual format selection is needed.
sudo apt-get install wine32WINEARCH=win32 WINEPREFIX=~/.wine32 winecfgWINEARCH=win32 WINEPREFIX=~/.wine32 wine vuln.exeSolution
Walk me through it- Step 1Run the binary under WineRunning the EXE prints a banner and a single password prompt on stdin:
Enter password:. Type anything; the binary either printsWrong!and exits, orCorrect! Here is your flag: .... There is no menu and no immediate flag drop.bashWINEARCH=win32 WINEPREFIX=~/.wine32 wine vuln.exeLearn more
Wine (Wine Is Not an Emulator) is a compatibility layer that allows Windows executables to run on Linux without a full Windows VM. It implements the Windows API on top of Linux system calls, making it possible to run most 32-bit Windows programs.
In CTF challenges, Windows binaries are often distributed to require Wine or a Windows VM. Using Wine on Linux is more convenient for scripting automated exploits and using Linux analysis tools like Ghidra, objdump, and Python.
- Step 2Reverse-engineer the password check in GhidraLoad the PE into Ghidra, find the string comparison function, and extract the expected password value.bash
# In Ghidra: File > Import File > vuln.exebash# Search > For Strings to find password/flag stringsbash# Decompile the main function to see the strcmp or comparison logicLearn more
Ghidra supports PE (Portable Executable) format just as well as ELF. After auto-analysis, navigate to the entry point or
main(). Look for calls tostrcmp,strncmp, or inline byte comparisons that validate user input.The decompiler view makes it easy to spot patterns like:
if (strcmp(input, "secretpassword") == 0) print_flag();. The hardcoded string is the password you need to supply.Alternatively,
strings vuln.exeon Linux dumps all printable strings from the binary. Filter for password-shaped candidates:strings vuln.exe | grep -E '^[A-Za-z0-9_!]{6,}$' | head # Sample output: # AcceptEx # Enter password: # Correct! # Su93r_S3cr37_P455w0rd <- the embedded password # picoCTF # DispatchMessageWThe regex keeps strings of 6+ "identifier-style" characters and discards short tokens, format directives, and most Windows API names. The hit list is short enough to eyeball; the real password is usually the only line that looks like an English-ish or leetspeak phrase rather than a Win32 symbol.
- Step 3Supply the password and capture the flagRun the binary again under Wine with the correct password to trigger the flag output.bash
echo 'CORRECT_PASSWORD' | wine vuln.exebash# or use Python to pipe input:pythonpython3 -c "import subprocess; p = subprocess.run(['wine', 'vuln.exe'], input=b'CORRECT_PASSWORD\n', capture_output=True); print(p.stdout.decode())"Learn more
Once you have the password from static analysis, pipe it into the binary via stdin. Windows programs running under Wine accept stdin just like Linux programs, so standard piping works.
If the binary expects a GUI dialog for input, you can use
wineconsoleor set upWINEDEBUG=environment variables to suppress Wine debugging output that might clutter your terminal.
Flag
picoCTF{...}
This challenge was not solved during the competition. The flag is printed after supplying the correct password found by reversing the PE binary in Ghidra.