โ๏ธ CrimsonWare - Module Development Guide
Version: CW-DEV-2026.V1
Complete guide to creating custom modules for the CrimsonWare Security Intelligence Framework.
๐ฏ Introduction
CrimsonWare modules are self-contained Python classes that follow a specific structure.
Each module handles its own UI, user input, and logic, and must provide a run() function
that CrimsonWare can call.
๐ Module Locations
Modules are organized by category in the modules/ directory:
modules/osint/- Open Source Intelligence toolsmodules/recon/- Network reconnaissancemodules/exploit/- Exploitation toolsmodules/forensics/- Digital forensicsmodules/analysis/- Data analysis
๐ Module File Structure
Every CrimsonWare module follows this pattern:
#!/usr/bin/env python3
"""
CrimsonWare - Your Module Name
Brief description of what your module does
"""
import os
import sys
import time
import json
from datetime import datetime
# Rich imports for beautiful output
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn
from rich.prompt import Prompt, Confirm
from rich import box
from rich.rule import Rule
console = Console()
class YourModule:
"""Main YourModule class"""
def __init__(self):
self.name = "Your Module Name"
self.version = "1.0"
# Your module's data and configuration
self.some_data = {}
self.output_dir = "your_module_output"
def show_banner(self):
"""Show module banner"""
banner = Panel(
f"[bold bright_red]๐ง {self.name} v{self.version}[/bold bright_red]\n"
"[yellow]Brief description of what your module does[/yellow]",
border_style="bright_red",
box=box.HEAVY,
padding=(1, 2)
)
console.print(banner)
console.print()
def some_function(self, param):
"""Your module's core functionality"""
# Implement your logic here
pass
def display_results(self, results):
"""Display results using rich tables"""
table = Table(
title="[bold bright_red]RESULTS[/bold bright_red]",
box=box.HEAVY,
border_style="bright_red",
header_style="bold yellow"
)
table.add_column("Column 1", style="cyan")
table.add_column("Column 2", style="white")
# Add rows
table.add_row("Value 1", "Value 2")
console.print(table)
def interactive_mode(self):
"""Run in interactive mode"""
self.show_banner()
while True:
console.print()
console.print(Rule("[bold yellow]YOUR MODULE MENU[/bold yellow]"))
console.print()
# Get user input
user_input = Prompt.ask("[yellow]Enter something[/yellow]")
if user_input.lower() in ['exit', 'quit', 'back']:
break
# Process input
self.some_function(user_input)
console.print()
again = Prompt.ask(
"[bright_black]Do another?[/bright_black]",
choices=["y", "n"],
default="y"
)
if again.lower() != 'y':
break
def run(self):
"""Main entry point for the module"""
try:
self.interactive_mode()
except KeyboardInterrupt:
console.print(f"\n[yellow]Interrupted by user[/yellow]")
except Exception as e:
console.print(f"[red]Error: {e}[/red]")
finally:
console.print(f"\n[cyan]Returning to main menu...[/cyan]")
time.sleep(1)
# For direct testing
if __name__ == "__main__":
module = YourModule()
module.run()
# Define the run function that CrimsonWare expects
def run():
"""Function called by CrimsonWare"""
module = YourModule()
module.run()
โ ๏ธ CRITICAL REQUIREMENTS
๐จ ABSOLUTELY REQUIRED
Your module MUST have a run() function at the bottom!
This is what CrimsonWare calls when a user selects your module:
"""Function called by CrimsonWare"""
module = YourModule()
module.run()
๐ Required Components
| Component | Required | Purpose | Example |
|---|---|---|---|
class YourModule: |
YES | Main class containing all functionality | class UsernameTracker: |
__init__(self) |
Recommended | Initialize module properties | self.name = "Module Name" |
show_banner(self) |
Recommended | Display module banner on startup | Uses rich Panel with crimson theme |
interactive_mode(self) |
Common pattern | Handle user interaction loop | Gets input, calls functions, handles exit |
run(self) |
YES (class method) | Main entry point for the class | Calls interactive_mode() with error handling |
def run(): (global) |
YES (CRITICAL) | Function CrimsonWare actually calls | Creates instance and calls instance.run() |
if __name__ == "__main__": |
Recommended | Allow direct testing | Run module standalone for debugging |
๐ Registering Your Module in CrimsonWare
To make your module appear in the CrimsonWare menus, you need to import it and add it to the module_mappings dictionary in crimsonware.py:
# In the imports section, add your module:
from modules.your_category import your_module
# In the CrimsonWare class __init__, find module_mappings:
self.module_mappings = {
# ... existing mappings ...
# Add your module with (category, tool_number): ("Module Name", module_object)
# Category numbers: 1=OSINT, 2=RECON, 3=EXPLOIT, 4=FORENSICS, 5=ANALYSIS
(1, 13): ("Your Module Name", your_module), # OSINT category, tool #13
# ... rest of mappings ...
}
๐ก Category Numbers
- Category 1 - OSINT Tools
- Category 2 - Reconnaissance
- Category 3 - Exploitation
- Category 4 - Forensics
- Category 5 - Cyber Analysis
Choose a tool number that's not already used in that category.
๐ง Step-by-Step Module Creation
Step 1: Choose Your Category and Filename
$ cd modules/osint/
# Create your module file (use lowercase with underscores)
$ touch my_awesome_tool.py
Step 2: Copy the Template
Use the template above and customize:
- Change the class name to match your tool (e.g.,
class MyAwesomeTool:) - Update the docstring with your module description
- Set
self.nameandself.versionin__init__ - Add your module's data structures and configuration
- Implement your core functionality in separate methods
- Create beautiful output with rich tables
Step 3: Implement Your Core Logic
Look at the example modules for inspiration:
- username_tracker.py - Shows threading, API calls, and result tables
- wifi_analyzer.py - Shows system commands, data analysis, and channel visualization
- email_forensics.py - Shows file parsing, attachment handling, and complex data structures
- buffer_overflow.py - Shows mathematical operations and pattern generation
Step 4: Test Your Module Standalone
$ python3 modules/osint/my_awesome_tool.py
๐ Common Patterns from Real Modules
1. The Interactive Loop Pattern
From username_tracker.py:
def interactive_mode(self):
self.show_banner()
while True:
username = Prompt.ask("[yellow]Enter username to search[/yellow]")
if username.lower() in ['exit', 'quit', 'back']:
break
self.search(username)
again = Prompt.ask("[bright_black]Search another?[/bright_black]", choices=["y", "n"])
2. Progress Bars for Long Operations
From username_tracker.py:
with Progress(
SpinnerColumn(),
TextColumn("[progress.description]{task.description}"),
BarColumn(),
console=console
) as progress:
task = progress.add_task("[bright_red]Searching...[/bright_red]", total=len(self.platforms))
3. Threading for Speed
From username_tracker.py:
with ThreadPoolExecutor(max_workers=10) as executor:
future_to_platform = {
executor.submit(self.check_username, platform, url, username): platform
for platform, url in self.platforms.items()
}
4. Saving Results to JSON
From username_tracker.py:
def save_results(self, username, found, not_found):
if not os.path.exists("results"):
os.makedirs("results")
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"results/username_username_timestamp.json"
with open(filename, 'w') as f:
json.dump(data, f, indent=4)
5. Beautiful Tables with Rich
From wifi_analyzer.py:
table = Table(
title=f"[bold bright_red]WiFi Networks ({len(networks)})[/bold bright_red]",
box=box.HEAVY,
border_style="bright_red",
header_style="bold yellow"
)
table.add_column("SSID", style="cyan")
table.add_column("BSSID", style="white")
table.add_column("Channel", style="green")
table.add_column("Signal", style="yellow")
๐ฏ Complete Working Example
Here's a minimal but complete module that demonstrates all required components:
#!/usr/bin/env python3
"""
CrimsonWare - IP Geolocation Lookup
Get geolocation data for an IP address
"""
import requests
import time
import json
from datetime import datetime
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich.prompt import Prompt
from rich import box
from rich.rule import Rule
console = Console()
class IPGeoLookup:
"""Main IP Geolocation class"""
def __init__(self):
self.name = "IP Geolocation Lookup"
self.version = "1.0"
self.api_url = "http://ip-api.com/json/"
def show_banner(self):
"""Show module banner"""
banner = Panel(
f"[bold bright_red]๐ {self.name} v{self.version}[/bold bright_red]\n"
"[yellow]Get geolocation data for any IP address[/yellow]",
border_style="bright_red",
box=box.HEAVY,
padding=(1, 2)
)
console.print(banner)
console.print()
def lookup(self, ip):
"""Look up IP geolocation"""
console.print(f"\n[cyan]Looking up: [bold]{ip}[/bold][/cyan]")
try:
response = requests.get(self.api_url + ip, timeout=10)
data = response.json()
if data.get('status') == 'success':
self.display_results(data)
self.save_results(ip, data)
else:
console.print("[red]Invalid IP or API error[/red]")
except Exception as e:
console.print(f"[red]Error: {e}[/red]")
def display_results(self, data):
"""Display geolocation results"""
table = Table(
title="[bold bright_red]GEOLOCATION RESULTS[/bold bright_red]",
box=box.HEAVY,
border_style="bright_red",
header_style="bold yellow"
)
table.add_column("Field", style="cyan", width=15)
table.add_column("Value", style="white", width=40)
fields = [
("IP", "query"),
("Country", "country"),
("Region", "regionName"),
("City", "city"),
("ZIP", "zip"),
("Latitude", "lat"),
("Longitude", "lon"),
("ISP", "isp"),
("Organization", "org"),
("AS Number", "as"),
("Timezone", "timezone")
]
for label, key in fields:
if key in data and data[key]:
table.add_row(label, str(data[key]))
console.print(table)
def save_results(self, ip, data):
"""Save results to JSON file"""
import os
if not os.path.exists("ip_lookups"):
os.makedirs("ip_lookups")
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"ip_lookups/ip_timestamp.json"
with open(filename, 'w') as f:
json.dump(data, f, indent=2)
console.print(f"\n[green]โ Results saved to: {filename}[/green]")
def interactive_mode(self):
"""Run in interactive mode"""
self.show_banner()
while True:
console.print()
console.print(Rule("[bold yellow]IP GEOLOCATION[/bold yellow]"))
console.print()
ip = Prompt.ask("[yellow]Enter IP address (or 'exit')[/yellow]")
if ip.lower() in ['exit', 'quit', 'back']:
break
self.lookup(ip)
console.print()
again = Prompt.ask(
"[bright_black]Look up another IP?[/bright_black]",
choices=["y", "n"],
default="y"
)
if again.lower() != 'y':
break
def run(self):
"""Main entry point for the module"""
try:
self.interactive_mode()
except KeyboardInterrupt:
console.print(f"\n[yellow]Interrupted by user[/yellow]")
except Exception as e:
console.print(f"[red]Error: {e}[/red]")
finally:
console.print(f"\n[cyan]Returning to main menu...[/cyan]")
time.sleep(1)
# For direct testing
if __name__ == "__main__":
module = IPGeoLookup()
module.run()
# Define the run function that CrimsonWare expects
def run():
"""Function called by CrimsonWare"""
module = IPGeoLookup()
module.run()
๐งช Testing Your Module
Test Standalone:
Test in CrimsonWare:
โ Best Practices
๐ DO:
- Always include the global
run()function - This is critical for CrimsonWare to find your module - Include
if __name__ == "__main__":- Allows standalone testing - Use rich for output - Maintain CrimsonWare's professional look
- Handle KeyboardInterrupt - Let users exit gracefully with Ctrl+C
- Create output directories - Save results in organized folders
- Use threading for network operations - Keep the UI responsive
- Add docstrings - Document what each function does
โ DON'T:
- Don't forget the global run() function - Your module won't appear in CrimsonWare
- Don't use print() - Use
console.print()from rich - Don't block indefinitely - Always provide a way to exit
- Don't hardcode sensitive data - Use config files or prompts
- Don't ignore exceptions - Show user-friendly error messages
๐ง Troubleshooting
| Problem | Solution |
|---|---|
| Module doesn't appear in menu | Check that you added it to module_mappings in crimsonware.py and that the global run() function exists |
| "Module not found" error | Verify the import path in crimsonware.py and that the file exists in the correct category folder |
| Module runs but has no output | Check that you're using console.print() instead of print() |
| Rich formatting not working | Ensure from rich.console import Console and console = Console() at the top of your file |
| Can't exit module | Add exit condition in your interactive loop (check for 'exit', 'quit', 'back') |
๐ Ready to Create?
You now have everything you need to create custom CrimsonWare modules:
- โ Complete template with all required components
- โ Examples from real modules
- โ Registration instructions
- โ Testing procedures
- โ Best practices and troubleshooting
Remember: The global run() function at the bottom is REQUIRED!