MALWARE · LESSON 01

Behavior & Triage

20 min

Learning Objectives

  • Run a fast static triage on an unknown sample
  • Build a hypothesis from strings, imports, and metadata
  • Know when to move from static to dynamic analysis
  • Document findings as you go
  • Classify malware family by capability profile
  • Generate initial IOCs from static analysis

Triage Is Rapid Hypothesis

You have an unknown binary and no time to reverse it fully. Triage is the 10-minute scan that tells you where to focus.

The Triage Sequence

  1. File type & metadata — file, hash it (SHA-256), note size and compile time.
  2. Strings — URLs, registry keys, mutexes, PowerShell, suspicious paths.
  3. Imports — capabilities: network? injection? persistence?
  4. Sections/entropy — packed? RWX?
  5. Resources — embedded binaries, config, icons.
  6. Hypothesis — write it down: “likely a downloader that persists via Run key.”

Detailed Triage Checklist

1. File Identification

# Hashes
sha256sum sample.exe
md5sum sample.exe

# File info
file sample.exe
# PE32+ executable (GUI) x86-64, for MS Windows

# PE headers (with pefile, CFF Explorer, PE-bear)
# - Machine: 0x8664 (x64) or 0x14c (x86)
# - TimeDateStamp: compile time (may be forged)
# - Subsystem: GUI (2) vs Console (3)
# - DLL Characteristics: ASLR, DEP, CFG, etc.

2. Strings (Triaged)

# Full scan, both encodings
strings -a -n 6 sample.exe > strings_ascii.txt
strings -el -n 6 sample.exe > strings_unicode.txt

# Categorize immediately:
grep -iE "http|https|ftp" strings_ascii.txt        # C2
grep -iE "run|runonce|service|startup" strings_ascii.txt  # Persistence
grep -iE "global\\|local\\|mutex" strings_ascii.txt  # Mutex
grep -iE "%appdata%|%temp%|%system%" strings_ascii.txt # Paths
grep -iE "powershell|cmd\.exe|wscript|cscript" strings_ascii.txt # Scripting

High-value strings: Specific to malware behavior (URLs, mutex names, registry paths). Low-value strings: Generic format strings, error messages, CRT artifacts.

3. Imports = Capability Fingerprint

CapabilityKey ImportsMITRE ATT&CK
Network/C2InternetOpen, InternetConnect, HttpSendRequest, WSASocket, connect, WSAConnectT1071
Process InjectionOpenProcess, VirtualAllocEx, WriteProcessMemory, CreateRemoteThread, VirtualProtectExT1055
PersistenceRegSetValueEx, RegCreateKeyEx, CreateService, CopyFile, SHGetFolderPathT1547
Credential AccessLsaEnumerateLogonSessions, CredEnumerate, CryptUnprotectData, LsaGetLogonSessionDataT1003
DiscoveryGetSystemInfo, GetVersionEx, EnumProcesses, NetShareEnum, GetAdaptersInfoT1082
Defense EvasionIsDebuggerPresent, CheckRemoteDebuggerPresent, VirtualProtect (RWX), SetThreadContextT1622
ExecutionCreateProcess, WinExec, ShellExecute, CreateThread, QueueUserAPCT1059
Lateral MovementWNetAddConnection2, NetUseAdd, CreateRemoteThread (remote), SMB APIsT1021

4. Sections & Entropy

# pefile entropy scan
python3 -c "
import pefile, math
pe = pefile.PE('sample.exe')
for s in pe.sections:
    data = s.get_data()
    entropy = -sum((data.count(b)/len(data))*math.log2(data.count(b)/len(data)) for b in set(data))
    print(f'{s.Name.decode().strip():10s} VA={s.VirtualAddress:08X} VS={s.Misc_VirtualSize:08X} RS={s.SizeOfRawData:08X} Entropy={entropy:.2f}')
"

Interpretation:

  • Code (.text): 6.0-7.2 (normal), >7.5 = packed/encrypted
  • Data (.rdata, .data): 4.0-6.5
  • Resources (.rsrc): Variable
  • Packed: High entropy in ALL sections, few/no imports, entry point in weird section

5. Resources

# Dump resources
wrestool -x -t14 sample.exe  # RT_GROUP_ICON
wrestool -x -t16 sample.exe  # RT_VERSION
wrestool -x sample.exe       # All resources

Look for:

  • Embedded binaries (RT_RCDATA, custom types)
  • Version info (company, product, copyright — often fake)
  • Manifests (requestedExecutionLevel = admin?)

6. Packer Detection

IndicatorMeaning
Few imports (only LoadLibrary/GetProcAddress)Manual import resolution
High entropy sectionsPacked/encrypted
Section names: UPX0, UPX1, .aspack, .themida, .vmp0Known packer
Entry point in last section / not in .textPacker stub
TLS callbacks presentPre-entry unpacking
VirtualProtect on own .text at runtimeSelf-modifying/unpacking

Static vs Dynamic — When to Switch

Static analysis is safe but limited (encrypted strings, packed code defeat it). Move to dynamic when:

  • The sample is packed — you need runtime to unpack it.
  • Strings/imports are deliberately stripped.
  • You need to observe behavior (what does it actually do?).

Always dynamic-analyze in an isolated VM with snapshots and no network access to the real internet.


Hypothesis Template

From minute one, keep notes:

=== SAMPLE TRIAGE ===
SHA-256:      a1b2c3d4e5f6...
File Type:    PE32+ executable (GUI) x86-64
Size:         124 KB
Compile Time: 2024-01-15 14:32:10 (may be forged)

STRINGS (high-value):
  C2:         http://c2.example.com/beacon
  Mutex:      Global\Mutex_A1B2C3
  Persistence: Software\Microsoft\Windows\CurrentVersion\Run
  Paths:      %APPDATA%\svchost.exe

IMPORTS (capabilities):
  Network:    InternetOpen, InternetConnect, HttpSendRequest
  Injection:  VirtualAllocEx, WriteProcessMemory, CreateRemoteThread
  Persistence: RegSetValueEx
  Anti-Debug: IsDebuggerPresent

SECTIONS:
  .text:  Entropy 6.8 (normal)
  .rdata: Entropy 5.2
  .data:  Entropy 4.1
  No suspicious section names.

HYPOTHESIS: 
  Implant/Beacon with process injection capability.
  Persists via Run key. Single-instance mutex.
  C2 over HTTP. Likely a RAT or loader.

NEXT STEPS:
  1. Dynamic: Run in VM with Procmon/Regshot
  2. Dump memory after unpack (if packed)
  3. Extract full C2 config from memory
  4. YARA rule from strings + imports

Classification by Capability Profile

ProfileCapabilitiesTypical Family
DownloaderNetwork onlyEmotet, TrickBot (loader)
DropperNetwork + File WriteVarious
InjectorInjection + NetworkCobalt Strike, custom
RAT/ImplantNetwork + Injection + Persistence + DiscoveryAsyncRAT, njRAT, custom
RansomwareFile Encrypt + Persistence + Network (C2)LockBit, Conti
WiperDisk/Filesystem destroyNotPetya, Shamoon
Spyware/StealerCredential Access + NetworkRedLine, Vidar
BotnetNetwork + Persistence + LateralMirai, QakBot

Documentation Habit

Documentation is not optional — it’s how you track reasoning across hours.


Interactive: Triage a Sample

The hex dump below contains suspicious strings. Apply the triage sequence and form a hypothesis.


Takeaway

Triage is fast hypothesis, not deep analysis. Find the interesting corner, then dig.

Next: Persistence Mechanisms.


Practice Exercises

  1. Triage Drill: Given 5 samples (from MalwareBazaar), spend 5 min each. Write hypothesis for each.
  2. Entropy Scan: Write a script to flag PE sections with entropy > 7.5.
  3. Import Classifier: Build a dictionary mapping API → ATT&CK technique. Auto-tag samples.
  4. String Clustering: Group samples by shared strings (mutex, C2 domain, PDB path).
  5. Packer ID: Collect 10 packed samples. Identify packer by section names/entry point/imports.
  6. False Positive Hunt: Find a legitimate binary with “suspicious” imports (e.g., VirtualAllocEx in a debugger). Why is it benign?

Interactive