Home Reverse Engineering

Reverse Engineering Checklist: Triage a Suspicious Binary in Your First Hour

Reverse Engineering

September 25, 2026

Reverse Engineering Checklist: Triage a Suspicious Binary in Your First Hour

It starts the same way every time. A file shows up on a host, in a quarantine folder, or attached to a ticket, and someone asks the only question that matters: is this bad? You do not need to fully reverse it to answer. You need to know what it is, what it can do, and what it actually did. An hour of disciplined triage usually gets you there, and it keeps you from burning three days on something a hash lookup would have closed in thirty seconds.

Hash First, Always

Before you execute the sample, or even open it in a disassembler, compute a SHA-256 and write down where it came from. On Linux that is sha256sum; in PowerShell, Get-FileHash. Record the original filename, the acquisition time, and the host it came from. That context matters later when you correlate against logs.

Then check the hash, not the file, against VirusTotal or whatever intel store you trust. This distinction is not pedantry. Uploading a confidential internal binary to a public service can leak proprietary code and, in a targeted intrusion, tells the operator their sample has been found. If the file is sensitive, use a private multi-engine scanner or keep it off the internet entirely.

Identify the File Type Before Anything Else

file is the cheapest high-value command in the toolbox. Magic bytes outweigh the extension every time. A file named invoice.pdf.exe is a Windows PE. A document that reports back "ELF 64-bit LSB executable, x86-64" is not a document. On Windows, Detect It Easy or PE-bear gives you the same information plus a lot more; on ELF, readelf -h; on macOS, otool -hv.

Look for the Toolchain Fingerprint

This step saves hours more often than any other. Go binaries carry a build ID and function names in the pclntab, so symbols survive even when stripped. Rust programs emit distinctive panic strings. .NET assemblies have a CLR header and decompile almost perfectly with ILSpy or dnSpy. A PyInstaller bundle announces itself in the section names and archive contents. If you are looking at .NET or frozen Python, your "reverse engineering" problem is really a reading-comprehension problem, and you should stop treating it like assembly.

Strings: Cheap, Loud, and Often Enough

Run strings -n 8 sample, and on Windows add -el for 16-bit wide strings, because most Win32 path and registry strings are UTF-16 and a default run will miss them. Then grep for the things that matter:

  • URLs, IP addresses, User-Agent strings, and TLS certificate names
  • Registry paths, especially anything under CurrentVersion\Run or policies keys
  • Service names, scheduled task names, and file paths
  • Mutex names, which frequently identify a family outright
  • Error messages, PDB paths, and build machine names

Hardcoded URLs and mutexes are the two highest-yield finds, because they lead directly to infrastructure or attribution. If the output is thin, FLOSS recovers obfuscated and stack-built strings. But never read sparse strings as a clean bill of health. A well-packed binary is supposed to look empty.

Imports, Sections, and the Linker's Leftovers

On a PE, objdump -p or dumpbin /imports gives you a capability outline. You are reading for markers, not for a verdict:

  • Runtime resolution: LoadLibrary plus GetProcAddress, which hides everything else from the import table
  • Injection: VirtualAllocEx, WriteProcessMemory, CreateRemoteThread, NtUnmapViewOfSection
  • Network and payload fetch: WinInet, WinHTTP, URLDownloadToFile
  • Persistence and evasion: CreateService, registry writes, SetFileAttributes, hooking APIs

Now look at sections: names, sizes, and permissions. Treat an executable section that is also writable as a serious flag. So is a .text with almost no raw data, a four-character random-looking name, or a resource section that is several megabytes of noise. On ELF, readelf -d and nm -D do the same job. Note that statically linked Go and Rust binaries have nearly empty dynamic symbol tables. That is normal, not suspicious.

Entropy and the Packer Question

Entropy measures randomness on a 0 to 8 scale. Above roughly 7.2, a section is compressed or encrypted. That is a signal, not a diagnosis: signed installers, self-extracting archives, and legitimate resource blobs all hit that range. Detect It Easy checks signatures and will name UPX, ASPack, Themida, VMProtect, and friends when it recognizes them.

If it is packed, do not start unpacking during your first hour. Get behavior first, then come back to unpacking when you have a specific question that only unpacked code can answer.

Sandbox Execution: Assume It Will Bite

Only analyze samples you are authorized to handle, and never on a machine you care about. Then work in this order:

  1. Snapshot a disposable VM. No shared folders, no shared clipboard, no mapped drives, no saved credentials.
  2. Use host-only networking or a simulated internet such as INetSim with a fake DNS server, so you can capture requests without letting the sample reach real infrastructure.
  3. Start your monitors before you run anything: Procmon with a filter, Wireshark or tcpdump, Process Hacker or System Informer, and on Linux strace. A monitor started after execution misses the interesting part.
  4. Launch the sample from a working directory you control, then wait. Give it sixty to a hundred and twenty seconds. Persistence and second-stage downloads rarely happen in the first two.
  5. Record what changed: files created, registry keys, services, scheduled tasks, child processes of the sample, and every outbound connection.

If the sample does nothing, that is a data point, not an exoneration. Plenty of malware checks for VM artifacts, debuggers, or a lack of network access before acting. Note the possibility and move on.

Write the Verdict While It Is Fresh

You have an hour's worth of notes. Compress them into one paragraph: what the file is, what it can do, what it did in your environment, and how confident you are. Include the hash, the toolchain fingerprint, and the two or three strongest pieces of evidence. Then choose a path: close it as benign, hand it to deeper reverse engineering, or escalate. If you escalate, write down the specific open questions for the next person.

The One-Hour Timebox

Follow the order, keep a plain text log as you go, and stop when the hour is up. Triage exists to route work, not to finish it. The person waiting on your answer needs to know whether to rebuild a host tonight, and a careful half-answer beats a perfect one delivered next week. Record what you do not know as clearly as what you do.

Photo: Yan Krukau / Pexels

Related Posts

Static vs Dynamic Binary Analysis: Which Should You Use First?
Reverse Engineering

October 12, 2026

Static vs Dynamic Binary Analysis: Which Should You Use First?

Static analysis maps what a binary could do; dynamic analysis shows what it actually does. Here is how to choose your starting workflow...

read more
Embedded Debugging Checklist: Logic Analyzer, SWD, and UART Before You Rewrite Code
Embedded Systems

October 08, 2026

Embedded Debugging Checklist: Logic Analyzer, SWD, and UART Before You Rewrite Code

A hardware-first checklist for embedded targets: verify power, clock, UART, and SWD before assuming your firmware is at fault.

read more
From Source to Silicon: A Beginner's Guide to the Compiler, Assembler, and Linker Pipeline
Architecture

October 03, 2026

From Source to Silicon: A Beginner's Guide to the Compiler, Assembler, and Linker Pipeline

Follow a C file through the preprocessor, compiler, assembler, linker, and loader, and learn the commands that leave every intermediate...

read more