Static vs Dynamic Analysis in Malware RE
Compare static vs dynamic analysis for malware reverse engineering: pros, cons, when to use each, and how anti-analysis tricks defeat both.
Reverse engineers spend a lot of time choosing between two complementary lenses: examining a program at rest, or watching it run. Understanding static vs dynamic analysis — when each shines, where each fails, and how malware authors weaponize that gap — is foundational to any malware analysis workflow.
What Is Static Analysis?
Static analysis is the inspection of a sample without executing it. You work from the bytes on disk: the file headers, embedded strings, imports, resources, and the disassembled or decompiled code.
Typical static techniques include:
- Reading PE/ELF headers to understand sections, entry points, and imports.
- Extracting strings to surface URLs, registry keys, and error messages.
- Disassembly and decompilation (IDA, Ghidra, Binary Ninja) to recover control flow and logic.
- Computing hashes and signatures (YARA rules, import hashing) for triage and clustering.
Because nothing runs, static analysis is inherently safe and gives you, in principle, complete code coverage — every branch is visible, even the ones a single execution would never reach.
What Is Dynamic Analysis?
Dynamic analysis runs the sample inside an instrumented, isolated environment — a sandbox, a VM, or under a debugger — and records what it actually does. Instead of reasoning about code, you observe effects.
Typical dynamic techniques include:
- Sandboxing to capture file system, registry, and process activity.
- Network monitoring to reveal C2 domains and exfiltration.
- Debugging (x64dbg, WinDbg, GDB) to step through and dump memory.
- API and syscall tracing to see exactly which functions the sample calls.
The big advantage: packers and obfuscation that hide code on disk are irrelevant once the payload unpacks itself in memory. You see the real behavior — but only along the paths that execution happens to take.
Static vs Dynamic Analysis: Comparison Table
| Dimension | Static Analysis | Dynamic Analysis |
|---|---|---|
| Sample executed? | No | Yes |
| Safety | High — code never runs | Lower — needs strong isolation |
| Code coverage | Complete in principle | Only executed paths |
| Speed of triage | Fast for simple samples | Slower; needs setup and runtime |
| Defeated by | Packers, obfuscation, encryption | Anti-debug, anti-VM, timing checks |
| Reveals real behavior? | Inferred, not observed | Directly observed |
| Environment | Disassembler / hex editor | Sandbox / VM / debugger |
When to Use Which
Choose your starting lens based on the sample and your goal:
- Start static for triage, classification, and when you need full coverage of logic — for example writing detection rules or mapping every command in a backdoor's dispatcher.
- Start dynamic when the sample is packed, when static review stalls, or when you specifically need runtime artifacts like C2 addresses, dropped files, or decrypted configuration.
- Use static to guide dynamic. Identify an interesting function statically, then set a breakpoint there at runtime.
- Use dynamic to unblock static. Let the sample unpack in memory, dump the cleartext payload, then return to the disassembler with readable code.
How the Two Approaches Complement Each Other
In practice the workflow is a loop, not a fork. A common pattern: triage statically, run the sample to let it self-decrypt, dump the unpacked image, and re-analyze that dump statically. Strings recovered dynamically tell you where to look in the disassembly; control flow recovered statically tells you which breakpoints matter. The browsable index of reverse engineering techniques is organized around exactly this interplay, and the glossary defines the underlying terms.
How Anti-Analysis Tricks Target Each Approach
Malware authors know which lens you will reach for, and they build countermeasures aimed at each one specifically. This is where the static-vs-dynamic distinction stops being academic.
Defeating static analysis
The goal here is to make the bytes on disk unreadable or misleading.
- Packing compresses or encrypts the payload behind a small unpacking stub. Your disassembler sees the stub, not the malware. See the packing techniques category.
- Obfuscation mangles otherwise visible logic — control-flow flattening, opaque predicates, and junk code. Browse the obfuscation techniques category.
- Stackstrings build strings one byte at a time on the stack so they never appear in a strings dump. See stackstrings.
- API hashing resolves imports by hash at runtime, so the import table reveals nothing useful statically. See API hashing.
Each of these specifically blunts a static technique while leaving runtime behavior intact — which is exactly why analysts pivot to dynamic analysis when static review hits a wall.
Defeating dynamic analysis
Here the goal is to notice that the sample is being watched, then misbehave or go dormant.
- Anti-debugging detects breakpoints, debugger flags, and attached processes.
- Anti-VM fingerprints virtualized hardware, sandbox artifacts, and suspicious environments.
- Timing checks such as RDTSC timing measure how long operations take; single-stepping or instrumentation slows execution enough to give the analysis away.
The full range of these countermeasures lives in the anti-analysis techniques category. Defeating them usually means patching checks, hardening the sandbox, or hooking the relevant APIs to lie back to the malware.
The Takeaway
Static and dynamic analysis are not competitors — they are two halves of one investigation. Static gives you reach and safety; dynamic gives you ground truth. Anti-analysis tricks exploit the seam between them, which is precisely why a competent reverse engineer keeps both lenses within arm's reach and switches the moment one stalls.
Ready to go deeper? Explore the full catalog of reverse engineering techniques to see exactly how each anti-analysis trick works — and how to defeat it — across both static and dynamic workflows.