courses

Static Analysis

Static analysis is the examination of a binary without executing it. It is the safest form of analysis and often yields a great deal of information with no risk of infection.

File Identification and Triage

Before deep analysis, perform quick triage to understand what you’re working with.

File Type Identification

The file command reads magic bytes to identify file type regardless of extension:

$ file sample.exe
sample.exe: PE32 executable (GUI) Intel 80386, for MS Windows
$ file sample
sample: ELF 64-bit LSB executable, x86-64, dynamically linked

Hashing

Always compute and record hashes before analysis. The hash serves as the unique identifier for the sample.

$ sha256sum sample.exe
$ md5sum sample.exe   # legacy, but still used in threat intel feeds
$ ssdeep sample.exe   # fuzzy hash — useful for finding similar samples

String Extraction

The strings command extracts printable ASCII/Unicode sequences. This often reveals URLs, file paths, registry keys, error messages, and C2 addresses embedded in plaintext.

$ strings -n 6 sample.exe | less      # minimum length 6
$ strings -el sample.exe | less       # 16-bit little-endian (common in Windows)

FLOSS (FireEye Labs Obfuscated String Solver) goes further by also recovering stack strings, encoded strings, and tight loops that concatenate characters:

$ floss sample.exe

PE File Format (Windows)

The Portable Executable (PE) format is used by Windows executables (.exe, .dll, .sys). Understanding the structure is essential for static analysis.

PE Structure Overview

┌──────────────────────┐
│   DOS Header         │  MZ magic bytes, legacy stub
├──────────────────────┤
│   PE Header (COFF)   │  machine type, section count, timestamps
├──────────────────────┤
│   Optional Header    │  entry point, image base, subsystem, data directories
├──────────────────────┤
│   Section Table      │  .text, .data, .rsrc, .rdata, ...
├──────────────────────┤
│   Sections           │  actual code and data
└──────────────────────┘

Examining the PE with pev

The pev toolkit provides focused views of PE structure:

$ pestr sample.exe        # strings with offset and section
$ pehash sample.exe       # multiple hash types
$ pepack sample.exe       # packing detection (entropy, section names)
$ pesec sample.exe        # security features (ASLR, DEP, CFG, SafeSEH)
$ pedis sample.exe        # disassemble entry point region
$ peres sample.exe        # resource section contents

Imports and Exports

The Import Address Table (IAT) lists functions the binary calls from external DLLs. This is one of the most valuable pieces of static information:

$ objdump -p sample.exe | grep -A 100 "Import"

Common suspicious import patterns:

Category Functions
Process injection VirtualAllocEx, WriteProcessMemory, CreateRemoteThread
Persistence RegSetValueEx, CreateService, SHGetSpecialFolderPath
Network WSAStartup, connect, InternetOpen, HttpSendRequest
Crypto CryptEncrypt, CryptHashData, BCrypt APIs
Anti-analysis IsDebuggerPresent, GetTickCount, QueryPerformanceCounter

ELF File Format (Linux)

ELF (Executable and Linkable Format) is used on Linux and most Unix-like systems.

$ readelf -h sample        # ELF header (architecture, entry point, etc.)
$ readelf -S sample        # section headers
$ readelf -d sample        # dynamic section (shared library dependencies)
$ readelf -s sample        # symbol table (if not stripped)
$ nm sample 2>/dev/null    # symbol names (works on unstripped binaries)
$ objdump -d sample | less # disassembly

Disassembly and Decompilation

We use two tools depending on the binary format:

IDA Classroom — PE Workflow

  1. Launch ida64 (64-bit) or ida (32-bit)
  2. Open the binary; accept auto-analysis
  3. Navigate to main via the Functions window or the Imports tab
  4. Press F5 in any function to open the Hex-Rays pseudocode decompiler
  5. Press N to rename functions and variables; press ; for comments
  6. Press X on any name to show all cross-references

IDA’s type library contains all standard Windows API definitions — argument names and types appear automatically for known functions.

Cutter / Rizin / radare2 — ELF Workflow

Rizin is a community fork of radare2 with a cleaner API; Cutter is its GUI. Both tools share the same command vocabulary — commands from one work in the other.

Launch cutter, open the binary, and accept the analysis defaults. The Console pane accepts Rizin commands directly:

# Rizin CLI (preferred) or radare2 CLI (compatible):
$ rizin -A sample        # rizin
$ r2 -A sample           # radare2 (same result)

[0x00401000]> afl        # list all functions
[0x00401000]> pdf @main  # disassemble main
[0x00401000]> pdg @main  # decompile main (rz-ghidra)
[0x00401000]> iz         # strings in data sections
[0x00401000]> ii         # imports

Entropy Analysis

High-entropy sections indicate packed, encrypted, or compressed data:

$ binwalk -E sample.exe

A .text section with entropy > 7.0 is a strong indicator of packing. In Cutter, the Dashboard shows a per-section entropy bar chart.

Useful Resources