Skip to content

Luct0r/MercuryRising

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MercuryRising

Gradually raise the temperature of phishing campaign sender emails/domains!

Overview

A domain warming tool that progressively ramps email volume using a three-phase approach: seed (send between accounts you control), transition (mix of seed and real targets), and target (full outbound). Generates OPSEC-aware headers with X-Mailer-consistent Message-IDs, date jitter, optional thread simulation, and multipart HTML+plaintext bodies.

Designed to run fire-and-forget on a GCP/AWS VM for the duration of an engagement's warm-up period.

Setup

  1. Provision a VM (GCP or AWS) and ensure the sending domain(s) have proper SPF, DKIM, and DMARC records.

  2. Install swaks

    apt install perl -y
    curl -O https://jetmore.org/john/code/swaks/files/swaks-20240103.0/swaks
    chmod 755 ./swaks
  3. Configure your files:

    • config.json — Campaign settings (see Configuration)
    • send.json — Sender credentials
    • receive.json — Recipients with type field (seed or target)
    • messages.json — Message templates with optional HTML and thread simulation

Configuration

config.json controls the campaign behavior:

{
  "campaign_name": "acme-q3",
  "campaign_days": 10,
  "business_hours": {"start": "08:30", "end": "17:00", "timezone_offset": -5},
  "skip_weekends": true,
  "volume_curve": "logarithmic",
  "phase_schedule": {"seed_only_days": 3, "transition_days": 2},
  "per_sender_daily_max": 5,
  "delay_profile": {"min": 30, "max": 300, "distribution": "weighted"},
  "provider": "mailgun",
  "smtp_server": "smtp.mailgun.org",
  "smtp_port": 587,
  "notifications": {"webhook_url": null},
  "credentials_file": "send.json",
  "recipients_file": "receive.json",
  "messages_file": "messages.json"
}
Field Description
campaign_days Total campaign length (default: 10)
volume_curve "logarithmic" (1,2,3,5,8,12,15,20,25,30), "linear" (day N = N), or a custom array [1,2,4,8,16]
phase_schedule Days for seed-only and transition phases before full target sending
per_sender_daily_max Max emails per sender credential per day (prevents single-account spikes)
delay_profile Inter-email delay range and distribution ("weighted" for human-like, "uniform" for flat random)
skip_weekends No sends on Saturday/Sunday
business_hours Sending window in local time (uses timezone_offset from UTC)
notifications.webhook_url Optional Slack/Discord webhook for daily status updates

Recipients — receive.json

[
  {"email": "seed1@yourdomain.com", "type": "seed"},
  {"email": "target@client.com", "type": "target"}
]
  • seed: Mailboxes you control. Used in phase 1 to build sender reputation with guaranteed delivery.
  • target: Actual engagement recipients. Used in phase 2-3 after reputation is established.

Messages — messages.json

[
  {
    "subject": "Follow Up",
    "body": "Following up on our conversation...",
    "body_html": "<p>Following up on our conversation...</p>",
    "thread": true
  }
]
  • body_html (optional): HTML variant for multipart/alternative emails. Most real business email includes both.
  • thread (optional): When true, 50% chance of adding In-Reply-To/References headers and Re: prefix, simulating a reply chain.

Usage

Quick Test

# Preview what would be sent today (no SMTP)
python3 email_sender.py --dry-run

Fire-and-Forget Daemon (Recommended)

# Start long-running daemon — sleeps between business-hours windows
python3 email_sender.py --run-campaign

# Run in background with nohup
nohup python3 email_sender.py --run-campaign > daemon.log 2>&1 &

# Or install as a system service
python3 email_sender.py --install-service   # generates systemd unit or launchd plist

Cron Mode

# Install cron job (with proper cd, logging, weekend skip)
python3 email_sender.py --setup-cron

# Remove cron entry
python3 email_sender.py --remove-cron

Other Commands

# Check campaign progress
python3 email_sender.py --status

# Force send N emails (ignores schedule/phase)
python3 email_sender.py --force-send 5

# Reset campaign to start fresh
python3 email_sender.py --reset

Warming Strategy

The three-phase approach builds sender reputation before touching the client's mail infrastructure:

Phase 1: SEED (days 1-3)
  Send to mailboxes you control → guaranteed delivery, no bounces
  Volume: 1, 2, 3 emails/day

Phase 2: TRANSITION (days 4-5)
  Mix of seed and target recipients, ratio shifts toward targets
  Day 4: ~50/50 seed/target
  Day 5: ~80% target
  Volume: 5, 8 emails/day

Phase 3: TARGET (days 6+)
  Full outbound to engagement targets
  Volume: 12, 15, 20, 25, 30 emails/day

OPSEC Features

  • X-Mailer-consistent Message-IDs: Each email picks a mailer profile (Outlook, Thunderbird, Apple Mail) and generates a Message-ID matching that client's format
  • Date header jitter: Timestamps vary by +/- 3 minutes with timezone matching
  • Thread simulation: Optional In-Reply-To/References headers on messages marked "thread": true
  • Multipart bodies: HTML + plaintext (text-only from "Outlook 16.0" is a detection signal)
  • Business-hours only: Sends within configured window, skips weekends
  • Weighted delays: Beta-distributed inter-email timing with occasional bursts and pauses (not uniform random)
  • Per-sender rate limiting: No single credential sends more than per_sender_daily_max per day
  • Bounce blacklisting: Recipients that bounce (5xx) are permanently excluded

Requirements

  • Python 3.6+ (stdlib only, no pip dependencies)
  • swaks email tool
  • Valid SMTP credentials (Mailgun, SendGrid, SES, or custom)

Security Note

Keep send.json and config.json secure. Never commit real credentials to version control.

Contributing

Adding SMTP Providers

The tool sends via swaks, so adding a provider is just a matter of the right SMTP server and auth flags. Set smtp_server and smtp_port in config.json:

Provider smtp_server smtp_port Notes
Mailgun smtp.mailgun.org 587 Default. Use domain-level SMTP credentials.
SendGrid smtp.sendgrid.net 587 Username is always apikey, password is your API key.
Amazon SES email-smtp.{region}.amazonaws.com 587 Generate SMTP credentials in SES console.
Custom/Postfix Your server IP/hostname 25/587 May need --tls removed from swaks for port 25.

For providers that need additional swaks flags (e.g., different TLS handling), submit a PR adding a provider profile to the send_email function.

About

Gradually raise the temp of emails/domains!

Resources

License

Stars

10 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages