Summary :
Modern malware uses self-modifying code to dodge static detection.
-
Polymorphic = same logic, different ciphertext each run (decryptor stub + new key).
-
Metamorphic = same logic, different plaintext each run (rewritten instructions, control-flow).
Because disk bytes keep changing, defenders grab decrypted code from memory while it runs, then analyze the truth.
1) What’s the difference?
Polymorphic code
-
Keeps a small decryptor stub and encrypted payload.
-
On start: alloc → decrypt → mark RX → jump to OEP (original entry point).
-
Disk signature changes every build, but decrypted payload in RAM is the same family.
Metamorphic code
-
Rewrites itself between builds: instruction substitution, block reordering, register renaming, garbage insertion, opaque predicates, CFG flattening.
-
Payload in RAM is also semantically identical but structurally different → harder than polymorphic.
Goal: break YARA/SIGs, thwart AV/ML features (n-grams, import graphs), and frustrate reverse engineers.
2) How attackers implement self-modification (common patterns)
-
Packers/cryptors: runtime decrypt → VirtualAlloc/VirtualProtect → memcpy → jump.
-
Process injection: WriteProcessMemory + CreateRemoteThread / APC / Thread Hijack.
-
Process hollowing: unmap legit image → map malicious payload → resume.
-
API hashing & dynamic resolution: avoid static imports.
-
JIT-style emit: build executable pages on the fly (RW → RX transitions).
Red flags: RWX pages, frequent PAGE_EXECUTE_READWRITE, high-entropy allocations, imports of VirtualAlloc/Protect, NtUnmapViewOfSection, WriteProcessMemory, CreateThread.
3) Analyst playbook — “snapshot memory for decrypted code”
Objective: catch the payload after it decrypts and before/while it executes.
A. Triage (static hints)
-
Very few imports + high section entropy → likely packed.
-
Tiny entrypoint → jumps/loops touching a blob → decryptor stub.
-
Suspicious TLS callbacks, self-checks, anti-VM strings.
B. Dynamic capture (single-host)
-
Detonate in an instrumented VM (no internet or through a broker).
-
Set hooks/breakpoints on:
-
VirtualAlloc/VirtualProtect(look for RW→RX) -
WriteProcessMemory,NtUnmapViewOfSection(hollowing) -
Thread creation APIs
-
-
When decrypt completes (RX memory created), dump regions:
-
Tools: PE-sieve/pe-sieve, Scylla, x64dbg + ScyllaHide, Process Hacker, Process Dump, Dumpulator.
-
-
Rebuild the PE and import table (Scylla), fix base, locate OEP.
-
Now do normal reversing (IDA/Ghidra) on the true decrypted code.
C. Live memory forensics (post-incident)
-
Snapshot RAM → Volatility/Rekall to enumerate processes, malfind, VADs, injected code, DLLs.
-
Carve PE from memory ranges with RX and high entropy; hash & classify.
D. Anti-evasion tips
-
Use time dilation / API shims to defeat sleep.
-
Hardware breakpoints instead of software (evade anti-dbg).
-
Record CFG traces to catch metamorphic variants (semantics > bytes).
-
Emulate decrypt loops in a sandboxed emulator (no real exec).
4) Detection ideas for blue teams
Behavioral rules
-
Alert on RWX or rapid RW→RX flips.
-
New RX regions not backed by image files.
-
WriteProcessMemoryinto foreign process + thread start. -
Unbacked modules with high entropy; hollowed images (mismatch between headers and mapped VADs).
Telemetry
-
ETW:
VirtualAlloc,VirtualProtect, image load, process/create thread events. -
EDR: code-injection TTPs, LOLBins launching unusual children, signed process with unknown RX pages.
Hunting/YARA (safe approach)
-
Match decryptor stubs / API hashing loops rather than full payload bytes.
-
Heuristics on PE anomalies (zeroed import table + runtime resolve).
5) Hardening & prevention
-
Block RWX policy (Exploit Protection, ASR, macOS Hardened Runtime, Linux W^X).
-
App control (WDAC/AppLocker), Code Integrity Guard for browser-spawned code.
-
Memory scanning (AV/EDR AMSI-like in-mem PE detection).
-
Network containment (Egress rules, DNS sinkhole) to neuter staging/decryption keys.
-
Least privilege & attack surface reduction (block unsigned drivers, script abuse).
-
Supply-chain hygiene: signed updates, SBOM/SLSA provenance to avoid packed third-party components.
6) Quick incident checklist
-
Isolate host → snapshot RAM.
-
Dump suspect process memory; carve RX regions.
-
Rebuild dump, fix IAT, locate OEP.
-
Classify family; search estate for same behaviors (not just hashes).
-
Rotate creds/tokens; review persistence; clean & reimage if needed.
-
Add detections for RW→RX, API-hash loops, hollowing flow.
Author: CyberDudeBivash • www.cyberdudebivash.com
Daily Threat Intel • AI & Cyber Defense Apps
#CyberDudeBivash #MalwareAnalysis #Polymorphic #Metamorphic #MemoryForensics #EDR #ReverseEngineering #ThreatIntel
