RedRoom : Architecture & Project Structure

I already gave a rough image of what the structure of the RedRoom has been designed until today but now I’m going to dig deeper and analyze in more detail my tool’s logic and architectural design.

Architecture.

How can we evaluate the architecture of a project and deem it efficient and good?
How will architectural differences affect the tool’s efficiency — and mine at the same time?

Those were the first questions I asked myself from the beginning — and so should you — because they define the form of this deep “web” we call a project.
Once we invest and expand too much into it, we can hardly turn back to change its form.

The architecture I decided to follow was clearly hierarchical. Each file handles its children and is handled by its parent.
But how would I define which file handles what?


Structure.

The first thing I did was draw.
I drew a rough shape of what categories the tool would have, then what tools those categories would include, and then what methods those tools would use.
You see where I’m going with this?

I mapped out 4 major categories:

  • Reconnaissance

  • Vulnerability analysis

  • Exploitation

  • Post-Exploitation

The idea was to have a main.py file and a cli.py file at the top of the food chain:

  • cli.py handles the rules of what flags the user can write in the command prompt

  • main.py reads those arguments and calls the appropriate logic


Let’s sneak peek into the first tool of RedRoom in recon — the hostscan.


cli.py code snippet for hostscan:

import argparse

def add_common_args(parser):
    """Adds common arguments shared across all tools."""
    parser.add_argument('--timeout', type=float, default=2.0,
                        help='Timeout in seconds to wait for each probe (default: 2.0)')
    parser.add_argument('--retries', type=int, default=2,
                        help='Number of retries if no response (default: 2)')
    parser.add_argument('--output', type=str, default=None,
                        help='Output to save results on a file')
    parser.add_argument('--format', choices=['json', 'csv'], default=None,
                        help='Format to save results (json or csv)')
    parser.add_argument('--silent', action='store_true',
                        help='Suppress output (silent mode)')
def get_parser():
    parser = argparse.ArgumentParser(
        prog='redroom',
        description='RedRoom: All-in-one Hacking Toolkit'
    )

    hostscan = recon_subparsers.add_parser('hostscan', help='Perform host discovery')
    hostscan.add_argument('-r', '--range', required=True, help='Target IP or CIDR range')
    hostscan.add_argument('-m', '--method', choices=['arp', 'tcp', 'icmp'], help='Discovery method')
    add_common_args(hostscan)

    return parser

def parse_args():
    parser = get_parser()
    args, unknown = parser.parse_known_args()
    args.extra = unknown
    return args

As you see, I made some universal “common” flags throughout the file, and for each tool, I create a different object to add its specific flags.
Mainly to restrict the user from using irrelevant flags on unrelated tools — and to keep the logic clear and pleasing to the eye.


main.py code snippet for hostscan:

def main():     
    args = parse_args()

    valid_categories = {"recon","analysis","exploit","postexploit"}
    valid_tools = {"hostscan"}
    if args.category not in valid_categories:
        print(f"[!] Error: Invalid category '{args.category}'. Valid options: {', '.join(valid_categories)}")
        return

    if args.tool not in valid_tools:
        print(f"[!] Error: Invalid tool '{args.tool}'. Valid options: {', '.join(valid_tools)}")
        return

    if args.category == "recon":
        if args.tool == "hostscan":
            try:
                hostscan.run(args)
            except Exception as e:
                print(f"[!] Unexpected error during scan: {e}")

So as you see, categories in the project aren’t particular files — but folder names — each containing the corresponding tools, and each tool having a folder with the corresponding methods.

From main.py, as the example shows, we shift to hostscan, specifically:

Categories/Recon/hostscan.py

hostscan.py itself — among other things — works as a handler too.
Depending on the tool I’m building, the amount of logic each tool handles varies — but all of them handle the user’s selected method (e.g., ARP vs ICMP for scanning).

It could be automated — and it is — but I still want to give the user some control over how the tool behaves.
Besides this, the tools also handle post-processing like saving the results to a file or printing them in a clean format in the terminal.


Conclusion.

Overall, I believe figuring out the architecture and structure of your project before you even complete your first file makes a huge difference in your workflow and efficiency — both for you and for the system you're building.
I tried to accomplish that to the best of my ability. It’s far from perfect, but it’s a start…

0
Subscribe to my newsletter

Read articles from Ektoras Kalantzis directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Ektoras Kalantzis
Ektoras Kalantzis