Static Analysis Basics
You can learn a lot about a binary without ever running it, and you should look before you leap.
What you will learn
- -Fingerprint a sample with cryptographic hashes and check it against threat feeds
- -Pull readable strings to surface URLs, filenames, and commands
- -Read PE headers and the import table to guess what the binary does
Before you detonate anything, spend ten minutes with the file at . is reading the binary without executing it, and it answers cheap questions fast: Have I seen this before? What does it talk to? What Windows APIs does it call? A packed will hide most of this from you, but even knowing it's packed is a finding. You look first because running blind wastes a snapshot on a sample you could have half-understood from the .
Hash it first, always
The hash is the sample's fingerprint. Compute it before you touch anything else, because it's how you identify the file, track it in your notes, and check whether the world already knows it.
$sha256sum sample.exe.vir$md5sum sample.exe.vir$file sample.exe.virTake that -256 and search it on VirusTotal or MalwareBazaar. A known hash with 55 of 70 engines flagging it tells you the family and saves you hours. A hash nobody has seen means either it's fresh or it's been repacked to change the hash, which is itself worth noting.
Do not upload a 's sample to VirusTotal without permission. An upload is public: it becomes searchable, and adversaries watch VT for their own samples appearing, which tips them off that they've been caught. Search by hash freely. Upload only when you're cleared to make the file public.
Strings: the free intel
Run strings and you every readable sequence of characters in the file. authors leak more than they think here: hardcoded URLs, IP addresses, keys, mutex names, filenames it drops, and error messages. On a plain unpacked binary this alone can hand you half your indicators.
$strings -n 8 sample.exe.vir | grep -iE 'http|\\.exe|\\.dll|HKEY|cmd|powershell'Windows binaries often store in both ASCII and Unicode, so run strings -el as well to catch the wide-character ones you'd otherwise miss. If strings comes back with almost nothing readable and a lot of high- garbage, the binary is probably packed. That's your cue to move to unpacking, covered later in this module.
PE headers and the import table
Windows executables use the PE (Portable Executable) format. The header tells you the target architecture, when it was compiled, and how the file is laid out in sections. The import table is the part you actually care about first: it lists the DLLs and functions the binary calls, which is a strong hint at behavior.
See WININET.dll with InternetOpenUrl and HttpSendRequest? It talks to the . CreateProcess, WriteProcessMemory, and VirtualAllocEx together are the classic process-injection trio. RegSetValueEx under a Run key means . CryptEncrypt in something that also enumerates files smells like .
$pip install pefile$python3 -c "import pefile,sys;pe=pefile.PE(sys.argv[1]);print(hex(pe.FILE_HEADER.TimeDateStamp))" sample.exe.vir$python3 -c "import pefile,sys;pe=pefile.PE(sys.argv[1]);[print(i.dll.decode(),[f.name.decode() for f in i.imports if f.name]) for i in pe.DIRECTORY_ENTRY_IMPORT]" sample.exe.virSection entropy is the other tell. A normal .text code section sits around 5 to 6.5 bits per byte. A section reading close to 8 is compressed or encrypted, which again means packed. pefile exposes section.get_entropy() per section, so you can spot a packed sample in one line instead of guessing.
A sample's import table shows VirtualAllocEx, WriteProcessMemory, and CreateRemoteThread. What behavior does that combination most strongly suggest?