<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
---
name: analyzing-packed-malware
description: >-
  Identify, unpack, and analyze packed or crypted malware samples using static
  heuristics, dynamic unpacking, and manual memory dumping techniques.
domain: cybersecurity
subdomain: malware-analysis
tags:
  - unpacking
  - packers
  - upx
  - themida
  - vmprotect
  - pe-analysis
  - entropy-analysis
  - malware-analysis
version: "1.0"
author: defconxt
license: AGPL-3.0
metadata:
  mitre-attack: ["T1027.002"]
---

# Analyzing Packed Malware

## Overview

Malware authors use packers, crypters, and protectors to compress, encrypt, or obfuscate executables to evade signature-based detection and hinder static analysis. Packed samples exhibit high entropy sections, minimal imports (often just `LoadLibrary`/`GetProcAddress`), and a small original entry point stub that decompresses the real payload at runtime. Analysts must identify the packer, apply automated or manual unpacking techniques, and recover the original executable for further analysis.

## Prerequisites

- Python 3.10+ with `pefile`, `yara-python`, `lief`
- UPX (`upx -d` for UPX-packed samples)
- Unipacker (generic PE unpacker)
- x64dbg / x32dbg for manual unpacking
- PE-sieve / Hollows Hunter for runtime process scanning
- Detect It Easy (DiE) or Exeinfo PE for packer identification
- REMnux or FlareVM analysis environment

## Key Concepts

### Packer Identification Heuristics

High entropy (>7.0) in code/data sections, small import table with only loader functions, section names matching known packers (`.upx`, `.vmp`, `.themida`), and entry point outside the first section are strong packer indicators.

### Common Packers

| Packer | Indicators | Unpacking Method |
|--------|-----------|-----------------|
| UPX | Section names UPX0/UPX1 | `upx -d` |
| Themida | `.themida` section, VM handlers | Manual OEP finding |
| VMProtect | `.vmp` sections, virtualized code | Devirtualization tools |
| ASPack | `.aspack` section | ASPackDie or manual |
| MPRESS | `.MPRESS1/.MPRESS2` sections | Manual dump at OEP |
| Custom | No known signatures | Dynamic dump at OEP |

### Entropy Analysis

Shannon entropy measures randomness in data. Unpacked code typically has entropy 5.0–6.5; packed/encrypted sections score 7.0–8.0 (near random). Per-section entropy analysis reveals which sections are packed.

## Workflow

### Step 1: Identify Packing

```bash
# Detect It Easy (command-line)
diec sample.exe

# Check entropy per section
python3 -c "
import pefile, math
pe = pefile.PE('sample.exe')
for s in pe.sections:
    name = s.Name.decode().rstrip('\x00')
    e = s.get_entropy()
    flag = '⚠ PACKED' if e > 7.0 else '  normal'
    print(f'{name:10s} entropy={e:.2f} vsize={s.Misc_VirtualSize:>8d} rsize={s.SizeOfRawData:>8d} {flag}')
print(f'Imports: {len(pe.DIRECTORY_ENTRY_IMPORT) if hasattr(pe, \"DIRECTORY_ENTRY_IMPORT\") else 0} DLLs')
"

# YARA-based packer detection
yara packer_rules.yar sample.exe
```

### Step 2: Automated Unpacking

```bash
# UPX unpacking
upx -d sample.exe -o unpacked.exe

# Unipacker for generic PE unpacking
unipacker sample.exe

# PE-sieve: scan running process for hollowed/injected code
pe-sieve.exe /pid 1234 /shellc /iat 2 /data 2

# Hollows Hunter: scan all processes
hollows_hunter.exe /iat 2 /shellc
```

### Step 3: Manual Unpacking with x64dbg

```
# Manual unpacking strategy:
# 1. Load sample in x64dbg
# 2. Set breakpoints on common OEP transfer APIs:
bp VirtualProtect    # Packer changes section permissions before jumping to OEP
bp VirtualAlloc      # Packer allocates memory for unpacked code
bp NtResumeThread    # Process hollowing handoff

# 3. Run until VirtualProtect with PAGE_EXECUTE_READWRITE on .text
# 4. Step through until the tail jump (jmp eax / push+ret / jmp [addr])
# 5. At OEP: use Scylla to dump and fix IAT

# Scylla plugin in x64dbg:
# Plugins → Scylla → IAT Autosearch → Get Imports → Dump → Fix Dump
```

### Step 4: Validate Unpacked Sample

```python
#!/usr/bin/env python3
"""Validate unpacking by comparing packed vs unpacked PE properties."""
import pefile

def compare_pe(packed_path: str, unpacked_path: str) -> None:
    packed = pefile.PE(packed_path)
    unpacked = pefile.PE(unpacked_path)

    print("=== Packed ===")
    p_imports = len(packed.DIRECTORY_ENTRY_IMPORT) if hasattr(packed, "DIRECTORY_ENTRY_IMPORT") else 0
    print(f"Imports: {p_imports}")
    print(f"Sections: {len(packed.sections)}")

    print("\n=== Unpacked ===")
    u_imports = len(unpacked.DIRECTORY_ENTRY_IMPORT) if hasattr(unpacked, "DIRECTORY_ENTRY_IMPORT") else 0
    print(f"Imports: {u_imports}")
    print(f"Sections: {len(unpacked.sections)}")

    for pe_obj, label in [(packed, "Packed"), (unpacked, "Unpacked")]:
        avg_entropy = sum(s.get_entropy() for s in pe_obj.sections) / len(pe_obj.sections)
        print(f"\n{label} avg entropy: {avg_entropy:.2f}")

compare_pe("sample.exe", "unpacked.exe")
```

### Step 5: Extract Strings and Imports

```bash
# String extraction from unpacked binary
strings -a -n 6 unpacked.exe | sort -u > strings_unpacked.txt
floss unpacked.exe > floss_output.txt

# Import analysis
python3 -c "
import pefile
pe = pefile.PE('unpacked.exe')
for entry in pe.DIRECTORY_ENTRY_IMPORT:
    print(f'\n{entry.dll.decode()}:')
    for imp in entry.imports:
        if imp.name:
            print(f'  {imp.name.decode()}')
"
```

## YARA Rule

```yara
rule Packed_Malware_Generic {
    meta:
        description = "Detects generically packed PE with high entropy and minimal imports"
        author = "NERF"
        date = "2026-03-17"
        mitre_attack = "T1027.002"
        severity = "medium"
    strings:
        $mz = { 4D 5A }
        $upx0 = "UPX0" ascii
        $upx1 = "UPX1" ascii
        $vmp = ".vmp" ascii
        $themida = ".themida" ascii
    condition:
        $mz at 0 and
        filesize < 5MB and
        (any of ($upx*) or $vmp or $themida or
         math.entropy(0, filesize) > 7.2)
}
```

## Detection

```yaml
title: Packed Malware Detection
id: b297c304-2d86-4725-bdb9-0be96c8ead79
status: experimental
description: Detects suspicious activity related to analyzing packed malware techniques in malware analysis context
logsource:
  category: process_creation
  product: windows
detection:
  selection:
    CommandLine: "*analyzing*packed*"
  condition: selection
level: high
tags:
  - attack.t1027.002
  - attack.execution
falsepositives:
  - Sandbox detonation environments analyzing submitted samples
```

## Verification

- [ ] Packer identified (type, version if possible)
- [ ] Unpacked binary produced with valid PE structure
- [ ] Import table recovered and functional
- [ ] Entropy of unpacked sections within normal range (5.0–6.5)
- [ ] Strings extractable from unpacked sample
- [ ] Unpacked sample executes in sandbox (functional validation)
- [ ] Original packed sample documented with packer metadata

## References

- [UPX — Ultimate Packer for eXecutables](https://upx.github.io/)
- [Unipacker — Automatic PE Unpacker](https://github.com/unipacker/unipacker)
- [PE-sieve — Process Scanner](https://github.com/hasherezade/pe-sieve)
- [Detect It Easy (DiE)](https://github.com/horsicq/Detect-It-Easy)
- [MITRE ATT&CK T1027.002 — Software Packing](https://attack.mitre.org/techniques/T1027/002/)
