Peekaboo
July 30, 2026 · View on GitHub

peekaboo is a modular framework designed to safely emulate malware behavior. It allows security researchers, red teamers, and blue teamers to reproduce complex threat scenarios - including Command & Control (C2) communication, persistence mechanisms, and lateral movement - without using destructive payloads.
The goal of peekaboo is to accelerate detection engineering and operator training by providing predictable, reproducible, and safe threat artifacts.
key features
- malware source code template - build a payload/stealer from templates (select C2 channel & data collection modules).
- payload generator - automated generation of C/C++ based payloads with built-in obfuscation (API hashing, string encryption).
- AV/EDR bypass - encryption/encoding (syscalls)
- multi-channel C2 - support for various covert channels:
- standard HTTP/S
- GitHub (abusing Issues/Commits)
- Telegram & Discord Webhooks
- TODO: adding all channels from one of my recent research
- exfiltration - staged exfil to controlled endpoints (Github/Discord/Slack/VirusTotal/Azure DevOps/Angelcam).
- evasive persistence - modular implementation of Windows persistence (Registry Run Keys, Winlogon, Screensaver).
- lightweight dashboard - a python-based C2 backend and dashboard for real-time monitoring of active "beacons".
- MITRE ATT&CK R&D - browse 200+ blog post techniques mapped to ATT&CK IDs with inline source code, LLM-extracted TTPs, and per-post GPU-precomputed briefs.
- Malpedia integration - threat actor and malware family lookup with semantic blog post matching via local LLM embeddings.
- AI assistant - direct Ollama gateway; one canned answer for "what is Peekaboo?", everything else streamed live from Ollama; no RAG, no DB lookups at chat time.
- APT campaign pipeline - the research-to-detection spine: Malpedia actor -> threat reports -> TTP extraction -> module selection -> binary compile -> detection overlay, visualized as an interactive tactic-lane graph for campaign analysis, threat hunting, and evidence review.
- YARA rule generator - auto-generate YARA rules from compiled binaries or uploaded samples.
- VirusTotal scanner - submit binaries for AV detection scoring; lookup by SHA256; poll analysis results.
- Artifact Map - 400+ ATT&CK techniques cross-referenced with 4,000+ Sigma rules; per-technique EventID coverage, registry keys, processes, command-line indicators; GPU-precomputed detection briefs per technique.
- single-file config - all API keys and per-service knobs live in one
.envfile. - safe by design - focuses on telemetry generation rather than actual system damage.
architecture
peekaboo consists of 5 main components: First malware module - highly portable C/C++ code designed to build specific "behaviors" (for final agent binary) on the target system.
- crypto (malware, agent) - build-in payload encryption/decryption logic constructor for agents.
- injection (malware, agent) - build-in injection logic constructor for agents.
- persistence (malware, agent) - build-in persistence logic constructor for agents (Registry Run Key, Winlogon, Screensaver).
- stealer (malware, agent) - stealer logic (Telegram, GitHub, VirusTotal, Bitbucket, Azure DevOps, Angelcam).
Second, payloads module - build-in payloads.
- payloads - for simplicity, just messagebox and reverse shell.
Final, peekaboo.py builder in Python.
demo
Run:
python3 peekaboo.py

dashboard
The dashboard is a Flask-based web UI that combines C2 monitoring, malware building, threat intelligence, and AI assistance in a single interface.
cd dashboard && python3 app.py




modules
| module | description |
|---|---|
| Builder | Compile payloads and stealers from source templates with live build log streaming |
| Shellcode | Parse, transform, encode, analyse and reformat shellcode in 11 output formats |
| Module Library | Browse 190+ malware-research modules sourced from the meow knowledge base |
| Samples | Upload and manage compiled samples organized by session |
| APT Campaign | Research-to-detection pipeline with an interactive Campaign/Hunt/Evidence graph, compiled implementations, report evidence, and Sigma/EventID coverage + blind spots |
| VirusTotal | Submit binaries to VirusTotal for AV detection scoring; lookup by SHA256; poll analysis |
| YARA | Auto-generate YARA rules from any binary (From Build, From Session, or Upload) |
| Artifact Map | 400+ ATT&CK techniques cross-referenced with 4,000+ Sigma rules; per-technique event IDs, registry, process, and cmdline artifacts; GPU-precomputed detection briefs |
| MITRE ATT&CK | Browse 200+ blog posts mapped to ATT&CK techniques; Extracted TTPs tab; per-post GPU briefs; inline source code viewer |
| Malpedia | Threat actor and malware family lookup with semantic blog post matching |
| AI Assistant | Direct Ollama gateway; instant canned answer for "what is Peekaboo?", all other questions streamed live from Ollama |
GPU / CPU split
Heavy LLM generation runs once, offline, on a GPU machine via worker.py - embeddings, tags, TTP extraction, summaries, Sigma briefs, actor/family/campaign briefs. Results are stored in dashboard/peekaboo.db. Serving those precomputed results is zero-LLM: the CPU dashboard just reads the DB.
The one exception is live semantic search, which embeds the user's query at request time. That is a single lightweight vector, cached in query_embeddings (so repeated searches cost nothing), and it degrades gracefully: if Ollama is offline the dashboard keeps serving everything else and flags semantic search as paused rather than crashing. Run python worker.py status (GPU) or peekaboo status (CPU) for a readiness verdict.
GPU machine (offline, LLM) CPU machine (dashboard, DB reads)
----------------------------- -------------------------------------
python worker.py embed cosine similarity search
python worker.py tag ----> ATT&CK badge rendering
python worker.py ttp rsync extracted TTP table
python worker.py summarize post + AI assistant summaries
python worker.py sigma artifact map + detection briefs
python worker.py apt campaign brief per session
python worker.py actor actor threat profile briefs
python worker.py family malware family behavioral briefs
(CPU) pipeline detection overlay
Sigma / EventID coverage per TTP,
derived live from the Sigma artifact map
The only runtime LLM call is the search query embed, and it is cached in the
query_embeddings table - so a repeated Malpedia / semantic search costs zero
Ollama round-trips, and with a warm cache the dashboard is effectively zero-LLM.
If Ollama is offline the dashboard keeps serving every precomputed result and
flags semantic search as paused rather than crashing. Check readiness any time
with python worker.py status (GPU) or peekaboo status (CPU).
All worker.py subcommands are resumable - they use NOT IN SQL patterns to skip already-processed rows. Interrupt and re-run at any time.
WAL checkpoint before scp/rsync - SQLite runs in WAL mode, so the DB lives in two files (
peekaboo.db+peekaboo.db-wal). Copying them withscp/rsyncnon-atomically can produce a corrupted DB on the receiving end if the WAL is mid-write. Always checkpoint first:# on the GPU server, before copying sqlite3 ~/hacking/peekaboo/dashboard/peekaboo.db "PRAGMA wal_checkpoint(TRUNCATE);" scp gpu-server:~/hacking/peekaboo/dashboard/peekaboo.db dashboard/peekaboo.dbAlternatively use
.backupfor a guaranteed-consistent snapshot while workers are still running:sqlite3 ~/hacking/peekaboo/dashboard/peekaboo.db ".backup /tmp/peekaboo_snapshot.db" scp gpu-server:/tmp/peekaboo_snapshot.db dashboard/peekaboo.db
scan, init, embed, tag, ttp, summarize, sigma, apt, actor, and family catch KeyboardInterrupt and print a clean resume hint instead of a traceback:
[actor] interrupted at 47/312 (46 saved, 265 remaining)
[actor] resume: python3 worker.py actor --model qwen3:14b

worker.py
worker.py runs from the project root (~/hacking/peekaboo/) and enriches dashboard/peekaboo.db with embeddings, tags, TTPs, and LLM summaries.
python worker.py <subcommand> [options]

subcommands
| subcommand | step | description |
|---|---|---|
scan | CPU | Walk _posts/*.markdown files and import slugs + metadata into kb_docs |
init | CPU | Import library cache JSON into kb_docs (alternative to scan) |
embed | GPU | Compute embedding vectors for all unembedded docs (nomic-embed-text) |
tag | GPU/LLM | Classify each doc with constrained-JSON ATT&CK tags |
ttp | GPU/LLM | Extract MITRE ATT&CK IDs, tactics, confidence, and rationale from source code |
reports | GPU/LLM | Fetch Malpedia-linked HTML/PDF reports and precompute validated report TTPs for offline APT runs |
summarize | GPU/LLM | Precompute one 3-sentence summary per blog post (what/how/detection) |
sigma | CPU+GPU | Parse Sigma rules into artifact map, then precompute detection briefs per technique |
apt | GPU/LLM | Precompute 3-sentence campaign brief per finished pipeline session |
actor | GPU/LLM | Precompute threat profile brief per Malpedia actor |
family | GPU/LLM | Precompute behavioral brief per Malpedia malware family |
refresh | all | One-shot incremental update: scan -> init -> embed -> tag -> (ttp?) -> (summarize?) |
status | CPU | Row/pending/stale counts for all tables, plus a readiness verdict (is the DB ready to serve, is runtime Ollama needed) |
scan
python worker.py scan
python worker.py scan --posts ~/hacking/meow/_posts
Walks markdown files, extracts frontmatter (title, date, category, ATT&CK IDs), finds associated source files (.c, .cpp, .nim, .asm, .s, .py), and writes data/library_cache.json. Note: results are built in memory and written atomically at the end - if interrupted, no data is saved and re-running restarts the scan from scratch (fast, CPU-only).
Ctrl+C safe - prints a clean message on interrupt. Re-run to redo the scan.
init
python worker.py init
Imports data/library_cache.json into kb_docs (idempotent upsert). Each doc is written to DB immediately, so interrupting and re-running will skip already-upserted entries.
Ctrl+C safe - each doc is upserted immediately. Press Ctrl+C at any time; re-run to resume from where it stopped.
embed
python worker.py embed
python worker.py embed --model nomic-embed-text --rebuild
Computes 768-dim embedding vectors for all docs without an embedding. Stored in kb_embeddings. Used by semantic search and Malpedia matching.
| flag | default | description |
|---|---|---|
--model | nomic-embed-text | Ollama embedding model |
--url | http://localhost:11434 | Ollama base URL |
--batch | 32 | Docs per batch |
--rebuild | off | Wipe existing embeddings and recompute |
--watch N | off | Re-run every N seconds |
Ctrl+C safe - each batch is written to DB immediately. Press Ctrl+C at any time; re-run the same command to resume from where it stopped. Also exits
--watchmode cleanly.
tag
python worker.py tag
python worker.py tag --model qwen3:1.7b --rebuild-changed
Asks the LLM to classify each doc with ATT&CK tactic tags (constrained JSON output). Tags are used by the chatbot RAG context and the MITRE Library filter.
| flag | default | description |
|---|---|---|
--model | qwen3:1.7b | Ollama chat model |
--rebuild | off | Wipe all tags and retag |
--rebuild-changed | off | Only retag docs whose source file changed since last tag |
--watch N | off | Re-run every N seconds |
Ctrl+C safe - each tag is written to DB immediately. Press Ctrl+C at any time; re-run the same command to resume from where it stopped. Also exits
--watchmode cleanly.
ttp
python worker.py ttp
python worker.py ttp --model qwen3:14b
Reads each doc's source code file, asks the LLM to extract MITRE ATT&CK IDs with tactic, confidence (high/medium/low), and a one-sentence rationale. Results are stored in ttp_extracted and shown in the Extracted TTPs tab of the MITRE panel.
| flag | default | description |
|---|---|---|
--model | qwen3:14b | Ollama chat model (use a larger model for better accuracy) |
--rebuild | off | Wipe and redo all TTP extraction |
--rebuild-changed | off | Only redo docs whose source changed |
Ctrl+C safe - each result is written to DB immediately. Press Ctrl+C at any time; re-run the same command to resume from where it stopped.
reports
python worker.py reports --actor apt29
python worker.py reports --actor lazarus_group
python worker.py reports --actor turla
python worker.py reports --family win.cobalt_strike
python worker.py reports --family win.agent_tesla
Fetches Malpedia-linked threat reports for one actor/family, extracts text from HTML and PDF reports, asks the LLM for constrained JSON ATT&CK mappings, validates every ID against artifact_map, and stores evidence-backed rows in report_ttps. The APT pipeline reads these rows first, so demo actors run offline and skip live report downloads; if no precomputed rows exist, the old live regex fallback still runs.
| flag | default | description |
|---|---|---|
--actor ID / --family ID | - | Malpedia subject to precompute |
--model | qwen3:14b | Ollama chat model |
--limit | 12 | Max report URLs to process |
--rebuild | off | Wipe and redo this subject/model |
summarize
python worker.py summarize
python worker.py summarize --model qwen3:14b --posts ~/hacking/meow/_posts
Reads both the blog post markdown and the associated source code for each doc, then asks the LLM to write a 3-sentence summary: what the technique does, how it works at the API/syscall level, and what defenders should look for. Summaries are stored in kb_summaries and served by:
- The BRIEF block in the MITRE Library detail card
| flag | default | description |
|---|---|---|
--model | qwen3:14b | Ollama chat model |
--posts PATH | $BLOG_POSTS_ROOT | Root directory of blog post markdown files |
--meow-root PATH | $MEOW_ROOT | Root of the meow source repo (for resolving src paths) |
--rebuild | off | Wipe all summaries and recompute |
--rebuild-changed | off | Only recompute summaries for docs whose source or markdown changed |
--watch N | off | Re-run every N seconds |
Ctrl+C safe - each summary is written to DB immediately. Press Ctrl+C at any time; re-run the same command to resume from where it stopped. Also exits
--watchmode cleanly.
sigma
# Step 1 (CPU) - parse 4,000+ Sigma rules into artifact_map
python worker.py sigma --sigma-path ~/hacking/sigma --parse-only
# Step 2 (GPU) - precompute detection briefs per technique
python worker.py sigma --model qwen3:14b
# Full rebuild (if GPU machine also has the sigma repo)
python worker.py sigma --sigma-path ~/hacking/sigma --rebuild --model qwen3:14b

Step 1 (parse): Walks all .yml Sigma rule files, extracts per-technique event IDs, registry keys, process images, and command-line patterns, and stores them in artifact_map. This is the same data the dashboard "Build from Sigma Rules" button produces - but now runnable from the CLI without a browser.
Step 2 (LLM): For each technique in artifact_map, builds a detection-focused prompt (TID, name, tactic, event IDs, processes, registry keys, rule count) and asks the LLM to write a 3-sentence detection brief: what the adversary does, the most reliable telemetry to detect it, and one detection recommendation. Stored in artifact_summaries.
Briefs appear in the Overview tab of the Artifact Map technique modal with a typing animation.
| flag | default | description |
|---|---|---|
--sigma-path PATH | - | Parse Sigma rules from this directory first |
--parse-only | off | Only parse rules, skip LLM step |
--model | qwen3:14b | Ollama chat model |
--rebuild | off | Wipe existing LLM briefs and redo all |
Ctrl+C safe - each brief is written to DB immediately. Press Ctrl+C at any time; re-run the same command to resume from where it stopped.
Typical GPU/CPU workflow:
# On CPU machine - parse rules, then copy DB to GPU
python worker.py sigma --sigma-path ~/hacking/sigma --parse-only
rsync dashboard/peekaboo.db gpu-server:~/hacking/peekaboo/dashboard/
# On GPU machine - compute briefs
python worker.py sigma --model qwen3:14b
rsync gpu-server:~/hacking/peekaboo/dashboard/peekaboo.db dashboard/
apt
python worker.py apt
python worker.py apt --model qwen3:14b --rebuild
Reads every finished (status='success') pipeline session from pipeline_sessions, builds a prompt from the session's actor ID, ATT&CK technique list, tactics, and implant modules, then asks the LLM to write a 3-sentence campaign brief:
- Sentence 1 - who the actor is and what they targeted
- Sentence 2 - key ATT&CK techniques and tactics used
- Sentence 3 - highest-priority detection recommendation
Briefs are stored in session_summaries and served by /api/apt/brief/<session_id>. In the APT Campaign panel, every row in the sessions table has a [brief] button - clicking it opens the slide panel with the precomputed text and a typing animation. No LLM at render time.
| flag | default | description |
|---|---|---|
--model | qwen3:14b | Ollama chat model |
--url | http://localhost:11434 | Ollama base URL |
--timeout | 120 | Per-call timeout (s) |
--rebuild | off | Wipe existing session briefs and redo all |
Ctrl+C safe - each brief is written to DB immediately. Press Ctrl+C at any time; re-run the same command to resume from where it stopped.
actor
python worker.py actor
python worker.py actor --model qwen3:14b --rebuild
Loads the local Malpedia actor cache (data/malpedia_actors_cache.json), fetches each actor's full profile from the API (name, country, suspected targets, victim sectors, incident type, malware families), and asks the LLM to write a 3-sentence threat actor profile:
- Sentence 1 - who the actor is, suspected origin, and motivation
- Sentence 2 - typical targets and known malware families
- Sentence 3 - a behavioral signature defenders should hunt for
Briefs are stored in actor_summaries and served by /api/malpedia/actor/<id>/brief. In the Malpedia panel, the actor/family detail card shows a [brief] button inline in the title - clicking it opens the slide panel.
In the CLI malpedia sub-REPL, brief <actor-id> now auto-routes to the actor profile (or brief <slug> for KB posts, or brief <family-id> for malware families).
| flag | default | description |
|---|---|---|
--model | qwen3:14b | Ollama chat model |
--url | http://localhost:11434 | Ollama base URL |
--timeout | 120 | Per-call timeout (s) |
--rebuild | off | Wipe existing actor briefs and redo all |
Ctrl+C safe - each brief is written to DB immediately. Press Ctrl+C at any time; re-run the same command to resume from where it stopped.
Prerequisite: Malpedia actor list must be cached first. Run the Malpedia panel in the dashboard (actors tab) or call
list_actors()from themalpediamodule once.
family
python worker.py family
python worker.py family --model qwen3:14b --rebuild
Same flow as actor but for malware families. Fetches each family's description, alt-names, and attribution from the Malpedia API, then generates a 3-sentence behavioral brief:
- Sentence 1 - what the malware does and its primary capabilities
- Sentence 2 - how it persists, evades, or moves laterally
- Sentence 3 - most actionable detection or hunting recommendation
Briefs are stored in family_summaries and served by /api/malpedia/family/<id>/brief.
| flag | default | description |
|---|---|---|
--model | qwen3:14b | Ollama chat model |
--url | http://localhost:11434 | Ollama base URL |
--timeout | 120 | Per-call timeout (s) |
--rebuild | off | Wipe existing family briefs and redo all |
Ctrl+C safe - each brief is written to DB immediately. Press Ctrl+C at any time; re-run the same command to resume from where it stopped.
Prerequisite: Malpedia family list must be cached first. Same as
actor.
refresh
python worker.py refresh
python worker.py refresh --scan --ttp --summarize --meow-root ~/hacking/meow
One-shot incremental pipeline: runs scan (optional) -> init -> embed -> tag -> ttp (optional) -> summarize (optional). Skips already-processed rows in every step.
| flag | default | description |
|---|---|---|
--scan | off | Re-scan local _posts/ before init |
--rebuild | off | Wipe embeddings + tags first |
--ttp | off | Also run TTP extraction |
--summarize | off | Also run summary precompute |
--ttp-model | qwen3:14b | Model for TTP extraction |
--sum-model | qwen3:14b | Model for summarization |
status
python worker.py status
Shows row counts and pending/stale counts for all enrichment tables, followed by a readiness verdict - a one-glance answer to "is this DB ready to serve a CPU dashboard, and is Ollama needed at runtime?":
kb_docs : 309
kb_embeddings : 309 (nomic-embed-text) pending: 0
kb_tags : 309 (qwen3:14b) pending: 0, stale: 0
ttp_extracted : 276 (qwen3:14b) pending: 0, stale: 0
kb_summaries : 309 (qwen3:14b) pending: 0, stale: 0
artifact_summ : 410 (qwen3:14b) pending: 0
actor_summ : 979 (qwen3:14b)
family_summ : 3704 (qwen3:14b)
readiness
✔ docs indexed 309
✔ embeddings ready 309/309
✔ summaries ready 309/309
✔ artifact briefs 410/410
✔ actor briefs 979
✔ family briefs 3704
runtime Ollama needed for LIVE semantic search (query embedding); precomputed briefs need none.
The same verdict is available on the CPU box after copying the DB with peekaboo status.
configuration (.env)
All API keys, credentials, and per-service knobs live in a single .env file at the project root.
cp .env.example .env
$EDITOR .env # fill in real tokens
| group | example variables |
|---|---|
| AI: Ollama | OLLAMA_BASE_URL, OLLAMA_MODEL, OLLAMA_NUM_CTX |
| Threat Intel | MALPEDIA_API_TOKEN, VT_API_KEY |
| Stealer / C2 | TELEGRAM_BOT_TOKEN, GITHUB_TOKEN, BITBUCKET_TOKEN_BASE64, SLACK_WEBHOOK_URL, AZURE_PAT, ANGELCAM_API_KEY |
| APT Pipeline | APT_PIPELINE_COMPILE_EACH, APT_PIPELINE_OLLAMA_NARRATION, APT_PIPELINE_OLLAMA_MODEL |
| Paths | MEOW_ROOT, BLOG_POSTS_ROOT |
.env is gitignored. .env.example is the redacted template.
dashboard panels
Builder
Select malware type (injection or stealer), injection technique, encryption algorithm, payload, stealer channel, and persistence method. Build output streams live to the UI. On success, the compiled binary and persistence binary (if enabled) are available for immediate download.
Build History
Every build is persisted to SQLite. The history table shows build ID, status badge, module/stealer name, compiler options, timestamp, and download links.
Samples / Sessions
Upload binary samples captured during red team exercises. Each session groups files by actor/host, stores upload time, and provides direct download links.
YARA Rule Generator
Auto-generates YARA rules from a binary using string extraction, section name heuristics, import pattern matching, and entropy thresholds.

- From Build - select any compiled build binary
- From Session - select a captured sample
- Upload - drag-and-drop any PE file
VirusTotal Scanner
Submit binaries directly to VirusTotal. Features: upload, From Build, From Session, SHA256 lookup, and poll for pending analysis.


MITRE ATT&CK R&D
The MITRE ATT&CK tab has four sub-tabs:
Techniques - ATT&CK technique browser grouped by tactic; click any technique to see matched blog posts.
Technique Library - all 200+ blog posts indexed from the meow research repository, mapped to ATT&CK IDs.
Filter by category (injection, persistence, evasion, cryptography, linux, macos, etc.)
Each row has a [brief] button - click to show the GPU-precomputed 3-sentence summary inline, without opening the full detail card
Click any row to expand the full detail card with inline source code (C, C++, Nim, assembly), blog post link, and BRIEF block (GPU summary with typing animation)
TTP Implementations - blog posts indexed by extracted ATT&CK ID with tactic, platform, and blog link. The ttp_implementations table is seeded automatically at dashboard startup from the static implementation list in mitre.py (no manual step required). Filter by tactic, platform, or keyword; click any ATT&CK ID badge to open a detection brief.

Extracted TTPs - LLM-inferred ATT&CK mappings per blog post: technique ID, tactic, confidence level, and rationale. Populated by worker.py ttp.

Malpedia integration
The Malpedia tab connects to the Malpedia REST API to browse threat actors and malware families. For each actor or family, related blog posts are matched using semantic similarity - the actor/family description is embedded via nomic-embed-text, then cosine-ranked against all cached post embeddings.

Search actors by name, country, or malware family
Expand any actor/family to see techniques, aliases, and semantically matched blog posts with similarity score
Each actor/family detail card has a [brief] button in the title - shows the GPU-precomputed threat profile or behavioral brief in the slide panel (no LLM at render time; requires worker.py actor / worker.py family)
Each related blog post row has a [brief] button -> KB summary from worker.py summarize
Requires a Malpedia API key in .env (MALPEDIA_API_TOKEN)
APT campaign pipeline
This is the spine of peekaboo - a single research-to-detection pipeline that the rest of the modules feed into:
Malpedia actor -> threat reports -> TTPs -> local modules -> build sample -> detection overlay (Sigma / EventIDs / YARA / VT)
It does not stop at "here is the malware." Every session ends as a purple-team artifact: the simulated attack chain plus what a defender should expect to see for each stage, plus the blind spots where no detection exists.



| # | Stage | What it does |
|---|---|---|
| 1 | Malpedia Fetch | Resolves actor/family ID, retrieves metadata |
| 2 | Report Source | Uses GPU-precomputed report TTPs from report_ttps when present; otherwise downloads linked reports as fallback |
| 3 | TTP Extraction | Uses validated precomputed HTML/PDF report mappings when present; otherwise falls back to local regex/name matching |
| 4 | Module Selection | Weighted random pick per TTP from top-5 candidates (see below) |
| 5 | Binary Compile | Builds a Windows PE ready for EDR testing |
| 6 | Detection Overlay | Cross-references each TTP against the Artifact Map -> expected Sigma rules, Windows EventIDs, registry keys, processes, cmdline indicators; flags TTPs with no coverage as blind spots (no LLM, pure DB join) |

All progress streams live to the UI. Every session is persisted to SQLite and can be inspected through Graph, Reports, TTPs, Detection, and Binary tabs.
Interactive campaign graph
The Graph tab is the default view for a completed session. It builds a deterministic threat path directly from the session data already stored in peekaboo.db; rendering requires no LLM call or network access. ATT&CK tactics are shown as lanes, stages are connected in execution order, and selecting a stage highlights the path leading to it while opening the related intelligence in a compact detail panel.
| Mode | Focus |
|---|---|
| Campaign | Actor-to-stage kill chain grouped by ATT&CK tactic |
| Hunt | Purple-team overlay with per-stage Sigma counts, EventIDs, coverage, and blind spots |
| Evidence | Report -> ATT&CK stage -> blog implementation / compiled source and binary relationships |
The detail panel keeps the evidence quote, source report, matching blog implementation, compiler/platform metadata, downloadable artifacts, Sigma rules, and EventIDs together. The graph supports stage navigation, zoom/pan, fit-to-view, a short deterministic replay, reduced-motion preferences, responsive mobile layout, and fullscreen presentation mode. Cytoscape.js is vendored locally with the dashboard, so the visualization remains available during an offline demo.

Detection overlay (purple-team hunt sheet)
Step 6 turns the attack chain into a defender-facing artifact. For every kill-chain stage, agent_detection_overlay() (pipeline/apt_pipeline.py) joins the stage's ATT&CK ID against the precomputed Artifact Map (400+ techniques x 4,000+ Sigma rules) and attaches, per stage, the Sigma rules, Windows EventIDs, registry keys, processes, and command-line indicators a blue team should hunt for. The session manifest.json gains a detection rollup:
- coverage % - how many stages have any detection at all
- unique Sigma rules / EventIDs across the whole chain
- gaps - the TTPs in this chain with zero Sigma coverage, i.e. the blind spots
This is pure DB cross-reference - no LLM, no network - so it runs in the same sub-minute pass as the source-only build.
Closing the loop. A blind-spot stage that also produced a compiled binary (compile_each: true) gets a starter YARA rule auto-generated from that binary (hunt_<ttp>_stage<NN>.yar, written into the session dir and listed in manifest.json). So a detection gap doesn't just get flagged - it ships with a first-draft detection. Source-only gaps get a hint to compile.
Inspect any session from the terminal - frameless, ASCII, colored:
peekaboo pipeline list # every campaign + coverage bar + gaps
peekaboo pipeline show <session_id> # per-stage hunt sheet: Sigma / EventIDs / blind spots / generated YARA
peekaboo status # readiness: indexed data + whether Ollama is needed
Each session row in the history table has a [brief] button - shows a GPU-precomputed 3-sentence campaign brief (actor, techniques used, detection priority) in the slide panel. No LLM at render time; requires worker.py apt.
Module selection strategy
Running the same actor twice produces a different kill chain each time. This is intentional - the goal is detection coverage breadth, not reproducibility.
pipeline/apt_pipeline.py -> agent_select_modules() uses a three-layer scoring mechanism:
Base score (deterministic, tactic alignment):
| Signal | Points |
|---|---|
| Module category maps to TTP tactic | +5 |
| Windows platform (primary demo target) | +1 |
| Has associated blog post | +1 |
Sophistication score (metadata-driven, no per-module allowlist):
| Signal | Points |
|---|---|
Blog series suffix, e.g. malware-injection-21 | up to +3.6 |
Advanced title markers such as syscall, undocumented, Native API, KernelCallbackTable, ZwQueueApcThread, callback, thread hijacking | +1.8 |
This biases shared ATT&CK buckets such as T1055 toward the more interesting blog examples (malware-injection-21, malware-injection-15, malware-injection-14, etc.) instead of repeatedly picking the introductory injection-1 / injection-2 posts.
Session deduplication (hard constraint):
-10 if the module's source file was already selected in this session -> guarantees no two stages compile the same .c/.cpp/.nim file
Cross-session rotation (soft pressure):
-3 if the module ID appeared in any of the last 10 pipeline sessions -> naturally rotates through the library across repeated runs of the same actor
Jitter (variety):
+[0, 2) uniform random added to every candidate score -> breaks ties and ensures even equal-scoring modules vary across runs
The top-5 candidates by adjusted score are then passed to random.choices() with weights proportional to (score - min + 1). Quality still wins most of the time, but lower-ranked alternatives get a real shot (~20-40% depending on score gaps).
Result: same actor, same extracted TTPs, different malware assembly every run - wider technique coverage for blue team detection tuning.
Artifact Map
Cross-references 400+ ATT&CK techniques with 4,000+ Sigma detection rules. For each technique, the map extracts:
Windows event IDs (Sysmon + Security)
Registry key patterns
Process image names
Command-line indicators
Logsource categories

Building the map:
Option A - browser: open the Artifact Map panel -> click ⚙ Build from Sigma Rules. Progress streams live.
Option B - CLI (recommended for GPU workflows):
python worker.py sigma --sigma-path ~/hacking/sigma --parse-only
Detection briefs: after building the map, run worker.py sigma on the GPU to precompute a detection-focused 3-sentence brief per technique. Briefs appear in the Overview tab of each technique's modal with a typing animation - no LLM call at render time.
AI assistant
Direct Ollama gateway for technical malware research questions.

How responses work:
"what is Peekaboo?" - instant canned answer; no LLM call.
everything else - streamed directly from Ollama /api/chat; no RAG, no DB lookups.
provider: configure via OLLAMA_BASE_URL, OLLAMA_MODEL, and OLLAMA_BEARER_TOKEN in .env.
Recommended and tested: qwen25-coder-offensive:v1-q8
CLI (peekaboo_cli.py)
Peekaboo has two terminal interfaces backed by the same SQLite data and dashboard modules:
- TUI mode: running
peekabooin an interactive terminal opens the full-screen application. - Classic mode: subcommands keep stable, pipe-friendly output for scripts and automation.
The TUI provides nine navigable workspaces: Overview, APT Campaigns, Research Library, MITRE ATT&CK, Detection, Threat Intel, Build History, Samples, and Toolkit. It uses the dashboard's purple palette and includes live AND-search, compact and wide layouts, record drill-down, a full-screen Monokai source viewer, the AI assistant, confirmed local module builds, and YARA generation from build history.

Install the peekaboo entry point in an isolated environment:
python3 -m venv .venv
.venv/bin/python -m pip install -e .
.venv/bin/peekaboo
Launch a specific workspace directly:
.venv/bin/peekaboo tui --view campaigns
.venv/bin/peekaboo tui --view detection
TUI navigation follows the keyboard-first model used by focused terminal tools:
| key | action |
|---|---|
1...9 | Switch workspace |
[ / ] | Previous / next workspace |
/ | Live search in the current workspace |
arrows or j / k | Move through records |
enter | Open full record detail |
g / G | First / last record |
s | Open source for a Research Library or ATT&CK implementation |
a | Open the AI assistant |
b | Build the selected Research Library module after confirmation |
y | Generate YARA for the selected build |
o | Open the selected public report or blog URL |
r | Reload local data |
? | Keyboard reference |
q | Quit |
The source viewer reads the complete local file when available, falls back to the cached snippet, and uses Monokai highlighting with line numbers and two-axis keyboard scrolling.

Direct classic execution remains supported. When stdout is redirected or captured, a bare invocation prints the classic home instead of trying to open a TUI:
python3 peekaboo_cli.py examples
python3 peekaboo_cli.py pipeline list

Use examples for the common workflows:
python3 peekaboo_cli.py examples

Global flags work before or after a command:
python3 peekaboo_cli.py --help
python3 peekaboo_cli.py --version
peekaboo artifacts stats --json # raw JSON, no Rich formatting
peekaboo --color never pipeline list # auto, always, or never
peekaboo --offline search injection # hard network-disable switch
peekaboo --db /path/to/peekaboo.db doctor
Quick workflows:
# Local readiness and cross-domain search
peekaboo doctor --demo
peekaboo search "process injection"
# Campaign intelligence
peekaboo pipeline list
peekaboo pipeline show <session> --view campaign
peekaboo pipeline show <session> --view hunt
peekaboo pipeline show <session> --view evidence
peekaboo pipeline diff <session-a> <session-b>
peekaboo pipeline export <session> --format navigator -o campaign.json
peekaboo pipeline export <session> --format markdown -o campaign.md
# Malpedia threat intelligence
peekaboo malpedia search lazarus
peekaboo malpedia actor lazarus_group
peekaboo malpedia reports --limit 10
# ATT&CK implementations and detection coverage
peekaboo ttp search "process injection"
peekaboo ttp show T1055
peekaboo artifacts show T1055
peekaboo artifacts rules T1059.001 --level high
# Research library
peekaboo library list --category injection
peekaboo library show malware-injection-17
# Local shellcode and build workflows
peekaboo shellcode analyse payload.bin
peekaboo shellcode convert payload.bin --to python --transform xor_key --xor-key 0x41
peekaboo builder build malware-injection-17
peekaboo yara gen-build <build-id> --save /tmp/rule.yar
# Upload is explicit; non-interactive VT uploads require --yes
peekaboo vtscan scan <build-id> --yes
peekaboo vtscan lookup <sha256>
Malpedia search returns matching actors/families and gives direct next steps:

ATT&CK TTP detail links techniques back to local buildable research modules:

Detection artifacts expose ATT&CK-to-Sigma coverage and severity filtering:

The research library remains browsable from the terminal:

library show renders full source code with Rich/Pygments syntax highlighting,
line numbers, indentation guides, and language detection for C/C++, Rust,
Python, Assembly, Nim, Go, shell, YARA, and other Pygments-supported languages.


Command groups:
| command | description |
|---|---|
examples | Show common workflows |
status | Readiness verdict: indexed data + whether runtime Ollama is needed |
tui | Launch the full-screen terminal application, optionally at a named workspace |
doctor | Read-only SQLite, demo filesystem, report/blog linkage, and toolchain verification |
search | Unified local search across techniques, modules, artifacts, campaigns, actors, and families |
pipeline | Campaign/Hunt/Evidence views, session diff, and Navigator/Markdown export |
library | Browse/search research modules and source code |
malpedia | Threat actors, malware families, reports, and Malpedia YARA |
ttp | MITRE ATT&CK techniques mapped to local implementations |
artifacts | ATT&CK x Sigma coverage, EventIDs, registry/process/cmdline artifacts |
builder | List/build compilable research modules and inspect build history |
yara | Generate YARA rules from files or build outputs |
vtscan | Upload binaries, poll analyses, and lookup VirusTotal reports |
shellcode | Analyse binary/text payloads and convert them through 11 formats and 7 transforms |
Notes:
--jsonwrites machine-readable JSON directly to stdout; errors use stderr.--offlineblocks Malpedia detail/report downloads and all VirusTotal operations. Cached Malpedia IDs, briefs, database search, campaign views, builds, YARA, and shellcode remain local.- TUI browsing is local and database-driven. In
--offlinemode, the AI assistant allows its built-in Peekaboo answer but blocks live Ollama requests. --color autois the default and respects non-TTY output andNO_COLOR; usealwaysonly when recording ANSI intentionally.- Session IDs accept an unambiguous prefix. Export writes atomically when
--outputis used. - VirusTotal uploads ask for confirmation and require
--yesin scripts.
Attention
This tool is a Proof of Concept and is for Educational Purposes Only!!! Author takes no responsibility of any damage you cause