WordSmith

Custom Wordlist Generator from The Undergrid

About WordSmith

WordSmith is a powerful and customizable Python-based wordlist generator built for offensive security professionals. It allows you to forge smart, targeted dictionaries using keywords, leetspeak, number ranges, and more — perfect for password attacks, red teaming, or Wi-Fi cracking.

How It Works

šŸ“‚ File Overview

cli.py — This is the main entry point. It handles argument parsing, profile loading, passes parameters to the generator, controls the chunking logic, displays the banner, and shows a summary at the end.

core.py — Contains the logic that generates the wordlist. It builds permutations from the keywords using toggles for uppercase, reversed, leetspeak, numbers, and special characters. Outputs a randomized unique list.

output.py — Responsible for saving the final wordlist to disk. Supports saving in text, CSV, or JSON format with clean and minimal formatting logic.

profiles/*.json — Optional reusable config files to define keywords, numbers, formatting and options. Makes running preconfigured attacks easier without passing long CLI arguments.

Full Python Code (cli.py)


        import argparse
        import json
        import sys  # āœ… Added to check for args
        from core import generate_wordlist
        from fileio import save_wordlist
        
        def load_profile(profile_path):
            with open(profile_path, "r") as f:
                return json.load(f)
        
        def parse_numbers(input_str):
            result = []
            parts = input_str.split(',')
            for part in parts:
                if '-' in part:
                    try:
                        start, end = map(int, part.split('-'))
                        result.extend([str(n) for n in range(start, end + 1)])
                    except ValueError:
                        continue
                else:
                    result.append(part.strip())
            return result
        
        def parse_specials(input_str):
            return [s.strip() for s in input_str.split(',') if s.strip()]
        
        def main():
            print(r"""
        ā–ˆ     ā–ˆā–‘ ā–’ā–ˆā–ˆā–ˆā–ˆā–ˆ   ā–ˆā–ˆā–€ā–ˆā–ˆā–ˆ  ā–“ā–ˆā–ˆā–ˆā–ˆā–ˆā–„   ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆ  ā–ˆā–ˆā–ˆā–„ ā–„ā–ˆā–ˆā–ˆā–“ ā–ˆā–ˆā–“ā–„ā–„ā–„ā–ˆā–ˆā–ˆā–ˆā–ˆā–“ ā–ˆā–ˆā–‘ ā–ˆā–ˆ 
        ā–“ā–ˆā–‘ ā–ˆ ā–‘ā–ˆā–‘ā–’ā–ˆā–ˆā–’  ā–ˆā–ˆā–’ā–“ā–ˆā–ˆ ā–’ ā–ˆā–ˆā–’ā–’ā–ˆā–ˆā–€ ā–ˆā–ˆā–Œā–’ā–ˆā–ˆ    ā–’ ā–“ā–ˆā–ˆā–’ā–€ā–ˆā–€ ā–ˆā–ˆā–’ā–“ā–ˆā–ˆā–’ā–“  ā–ˆā–ˆā–’ ā–“ā–’ā–“ā–ˆā–ˆā–‘ ā–ˆā–ˆā–’
        ā–’ā–ˆā–‘ ā–ˆ ā–‘ā–ˆ ā–’ā–ˆā–ˆā–‘  ā–ˆā–ˆā–’ā–“ā–ˆā–ˆ ā–‘ā–„ā–ˆ ā–’ā–‘ā–ˆā–ˆ   ā–ˆā–Œā–‘ ā–“ā–ˆā–ˆā–„   ā–“ā–ˆā–ˆ    ā–“ā–ˆā–ˆā–‘ā–’ā–ˆā–ˆā–’ā–’ ā–“ā–ˆā–ˆā–‘ ā–’ā–‘ā–’ā–ˆā–ˆā–€ā–€ā–ˆā–ˆā–‘
        ā–‘ā–ˆā–‘ ā–ˆ ā–‘ā–ˆ ā–’ā–ˆā–ˆ   ā–ˆā–ˆā–‘ā–’ā–ˆā–ˆā–€ā–€ā–ˆā–„  ā–‘ā–“ā–ˆā–„   ā–Œ  ā–’   ā–ˆā–ˆā–’ā–’ā–ˆā–ˆ    ā–’ā–ˆā–ˆ ā–‘ā–ˆā–ˆā–‘ā–‘ ā–“ā–ˆā–ˆā–“ ā–‘ ā–‘ā–“ā–ˆ ā–‘ā–ˆā–ˆ 
        ā–‘ā–‘ā–ˆā–ˆā–’ā–ˆā–ˆā–“ ā–‘ ā–ˆā–ˆā–ˆā–ˆā–“ā–’ā–‘ā–‘ā–ˆā–ˆā–“ ā–’ā–ˆā–ˆā–’ā–‘ā–’ā–ˆā–ˆā–ˆā–ˆā–“ ā–’ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–’ā–’ā–’ā–ˆā–ˆā–’   ā–‘ā–ˆā–ˆā–’ā–‘ā–ˆā–ˆā–‘  ā–’ā–ˆā–ˆā–’ ā–‘ ā–‘ā–“ā–ˆā–’ā–‘ā–ˆā–ˆā–“
        ā–‘ ā–“ā–‘ā–’ ā–’  ā–‘ ā–’ā–‘ā–’ā–‘ā–’ā–‘ ā–‘ ā–’ā–“ ā–‘ā–’ā–“ā–‘ ā–’ā–’ā–“  ā–’ ā–’ ā–’ā–“ā–’ ā–’ ā–‘ā–‘ ā–’ā–‘   ā–‘  ā–‘ā–‘ā–“    ā–’ ā–‘ā–‘    ā–’ ā–‘ā–‘ā–’ā–‘ā–’
          ā–’ ā–‘ ā–‘    ā–‘ ā–’ ā–’ā–‘   ā–‘ā–’ ā–‘ ā–’ā–‘ ā–‘ ā–’  ā–’ ā–‘ ā–‘ā–’  ā–‘ ā–‘ā–‘  ā–‘      ā–‘ ā–’ ā–‘    ā–‘     ā–’ ā–‘ā–’ā–‘ ā–‘
          ā–‘   ā–‘  ā–‘ ā–‘ ā–‘ ā–’    ā–‘ā–‘   ā–‘  ā–‘ ā–‘  ā–‘ ā–‘  ā–‘  ā–‘  ā–‘      ā–‘    ā–’ ā–‘  ā–‘       ā–‘  ā–‘ā–‘ ā–‘
            ā–‘        ā–‘ ā–‘     ā–‘        ā–‘          ā–‘         ā–‘    ā–‘            ā–‘  ā–‘  ā–‘
                                    ā–‘                                                
                          
                            šŸ›   WordSmith - Custom Wordlist Generator
                                        Developed by - 4c1d.burn
                  
        
        """)
        
            parser = argparse.ArgumentParser(description="WordSmith - Advanced Wordlist Generator")
            parser.add_argument("--profile", help="Path to a JSON profile file")
            parser.add_argument("--keywords", help="Comma-separated keywords")
            parser.add_argument("--uppercase", action="store_true", help="Include uppercase versions")
            parser.add_argument("--reversed", action="store_true", help="Include reversed versions")
            parser.add_argument("--leetspeak", action="store_true", help="Apply leetspeak mutations")
            parser.add_argument("--numbers", default="", help="Append/prepend numbers (e.g. 0-100 or 1,2,3 or ranges mixed)")
            parser.add_argument("--specials", default="", help="Append/prepend symbols (e.g. !,@,#)")
            parser.add_argument("--chunks", type=int, default=4, help="How many wordlists to generate")
            parser.add_argument("--format", choices=["1", "2", "3"], default="1", help="Output format: 1=txt, 2=csv, 3=json")
            parser.add_argument("--basename", default="wordlist", help="Base filename for output")
        
            # āœ… If no args are provided, show help and exit
            if len(sys.argv) == 1:
                parser.print_help()
                sys.exit(0)
        
            args = parser.parse_args()
        
            if args.profile:
                profile = load_profile(args.profile)
                args.keywords = ",".join(profile.get("keywords", []))
                args.uppercase = profile.get("uppercase", False)
                args.reversed = profile.get("reversed", False)
                args.leetspeak = profile.get("leetspeak", False)
                args.numbers = profile.get("numbers", "")
                args.specials = profile.get("specials", "")
                args.chunks = profile.get("chunks", 4)
                args.format = profile.get("format", "1")
                args.basename = profile.get("basename", "wordlist")
        
            keywords = [k.strip() for k in args.keywords.split(',')]
            numbers = parse_numbers(args.numbers) if args.numbers else []
            specials = parse_specials(args.specials) if args.specials else []
        
            wordlist = generate_wordlist(
                keywords,
                args.uppercase,
                args.reversed,
                numbers,
                specials,
                args.leetspeak
            )
        
            total_available = len(wordlist)
            print(f"\nšŸ”¢ Total words generated: {total_available}")
        
            sizes = [10000, 50000, 250000, 1000000]
            while len(sizes) < args.chunks:
                sizes.append(sizes[-1] * 2)
        
            if sum(sizes[:args.chunks]) > total_available:
                step = total_available // args.chunks
                sizes = [step] * args.chunks
                print("āš ļø Not enough entries for large chunk sizes. Adjusted to even split.")
        
            start = 0
            for i, size in enumerate(sizes[:args.chunks]):
                chunk = wordlist[start:start+size]
                filename = f"{args.basename}_{size}"
                save_wordlist(chunk, filename, args.format)
                print(f"āœ… Saved {len(chunk)} entries to {filename}")
                start += size
        
            print("\nšŸ“Š Summary Report")
            print("────────────────────────────────────")
            print(f"šŸ“ Base filename   : {args.basename}")
            print(f"🧠 Keywords used   : {args.keywords}")
            print(f"šŸ”  Uppercase       : {args.uppercase}")
            print(f"šŸ” Reversed        : {args.reversed}")
            print(f"šŸ¤– Leetspeak       : {args.leetspeak}")
            print(f"#ļøāƒ£ Numbers        : {args.numbers}")
            print(f"šŸ”£ Specials        : {args.specials}")
            print(f"šŸ“¦ Chunks created  : {args.chunks}")
            print(f"šŸ’¾ Output format   : {args.format}")
            print("────────────────────────────────────\n")
        
        if __name__ == "__main__":
            main()
      

Full Python Code (core.py)


        import random

        def apply_leetspeak(word):
            leet_map = {'a': '@', 's': '$', 'o': '0', 'i': '1', 'e': '3'}
            return ''.join(leet_map.get(c.lower(), c) for c in word)
        
        def generate_wordlist(base_keywords, include_uppercase, include_reversed, numbers_list, specials, leetspeak=False):
            wordlist = set()
        
            for word in base_keywords:
                wordlist.add(word)
                if include_uppercase:
                    wordlist.add(word.upper())
                if include_reversed:
                    wordlist.add(word[::-1])
                if leetspeak:
                    wordlist.add(apply_leetspeak(word))
        
            if numbers_list:
                for word in list(wordlist):
                    for num in numbers_list:
                        wordlist.add(word + num)
                        wordlist.add(num + word)
        
            if specials:
                for word in list(wordlist):
                    for special in specials:
                        wordlist.add(word + special)
                        wordlist.add(special + word)
        
            result = list(wordlist)
            random.shuffle(result)
            return result
      

Full Python Code (fileio.py)


        import json
        import csv
        
        def save_wordlist(wordlist, filename, format_choice):
            if format_choice == "1":
                filename += ".txt"
                with open(filename, "w") as f:
                    for word in wordlist:
                        f.write(word + "\n")
            elif format_choice == "2":
                filename += ".csv"
                with open(filename, "w", newline="") as csvfile:
                    writer = csv.writer(csvfile)
                    writer.writerow(["word"])
                    for word in wordlist:
                        writer.writerow([word])
            elif format_choice == "3":
                filename += ".json"
                with open(filename, "w") as f:
                    json.dump(wordlist, f, indent=4)
            else:
                filename += ".txt"
                with open(filename, "w") as f:
                    for word in wordlist:
                        f.write(word + "\n")
      

Full Python Code (profile.json)


        {
          "keywords": ["cyberforge", "admin", "secure", "pa$$word", "nexus"],
          "uppercase": true,
          "reversed": true,
          "leetspeak": true,
          "numbers": "0-25,2023,2024",
          "specials": "!,$,@,#",
          "chunks": 3,
          "format": "1",
          "basename": "cyberforge_hybrid"
        }