Athena Wiki

PE Binary Analysis (Windows)

reversingintermediate

Analyze Windows Portable Executable (PE) binaries for CTF reversing challenges.

reversingwindowspeportable-executabledllimportsdotnetx86

PE Binary Analysis (Windows)

PE (Portable Executable) is the binary format used by Windows executables (.exe), DLLs (.dll), and drivers (.sys). CTF reversing challenges increasingly include Windows binaries. The approach is similar to ELF analysis, but with different tools and conventions.


PE Structure

Mermaid diagram

Magic bytes: 4D 5A (MZ) at offset 0.


PE vs ELF: Key Differences

FeaturePE (Windows)ELF (Linux)
MagicMZ at offset 0\x7fELF at offset 0
Sections.text, .rdata, .data, .rsrc.text, .rodata, .data, .plt, .got
ImportsImport Address Table (IAT) in .idataPLT/GOT
StringsOften UTF-16 LETypically ASCII
ToolsGhidra, PE-bear, CFF Explorer, dnSpyGhidra, readelf, objdump, nm

Analysis Workflow

Identify the Binary

file suspicious.exe
# PE32 executable ... Intel 80386, for MS Windows
# PE32+ executable ... x86-64, for MS Windows

strings suspicious.exe | grep -iE "(flag|ctf|pass|key|secret)"
strings -e l suspicious.exe   # UTF-16 LE (Windows native!)

Always run both strings (ASCII) and strings -e l (UTF-16) on Windows binaries. Native Windows apps store most text as UTF-16.

Check for .NET

strings suspicious.exe | grep -i "mscoree\|\.NET"

If .NET, use ILSpy or dnSpy — they give near-original C# source. Much easier than native binary reversing.

Static Analysis with Ghidra

For non-.NET binaries, import into Ghidra → Auto-analyze → navigate to entry or WinMain → check Symbol Tree and Defined Strings.

Inspect Resources

sudo apt install icoutils
wrestool -x suspicious.exe -o resources/
binwalk -e suspicious.exe

Run with Wine (if needed)

sudo apt install wine
wine suspicious.exe
winedbg suspicious.exe

PE Inspection with Python

import pefile

pe = pefile.PE('suspicious.exe')
print('Architecture:', pe.FILE_HEADER.Machine)
print('Timestamp:', pe.FILE_HEADER.TimeDateStamp)

for entry in pe.DIRECTORY_ENTRY_IMPORT:
    print('Import DLL:', entry.dll.decode())
    for imp in entry.imports:
        if imp.name:
            print('  ', imp.name.decode())

.NET Binaries

Many Windows CTF challenges use .NET (C# / VB.NET):

strings suspicious.exe | grep -i "mscoree\|CLSIDFromProgID\|\.NET"
file suspicious.exe
# PE32 executable ... Mono/.Net assembly

Common Windows API Calls to Watch


Checklist

  • file → confirm PE format, 32 or 64-bit
  • strings -e l → Unicode strings (Windows native)
  • Check for .NET: decompile with ILSpy/dnSpy
  • Ghidra for non-.NET: decompile, find main/WinMain
  • Extract .rsrc with wrestool/binwalk
  • Look for: strcmp, CryptDecrypt, base64 functions
  • Run in Wine if static analysis is insufficient

Last updated on

On this page