How to Modify CUPP to Add New Password Generation Patterns

To add new password generation patterns in CUPP, you modify the generate_wordlist_from_profile function in cupp.py to create additional combinations using the komb or concats helpers, store them in the kombi dictionary with a unique key, and extend the deduplication loop to include your new entries.

CUPP (Common User Passwords Profiler) generates wordlists by combining personal data points through specific concatenation algorithms. According to the Mebus/cupp source code, all pattern logic resides in the interactive profile generator, where you can inject custom string combinations to expand the attack surface beyond default behaviors.

Understanding CUPP's Pattern Architecture

CUPP constructs password candidates using two core helper functions defined in cupp.py:

  • concats (lines 103–107): Appends numeric ranges to base strings
  • komb (lines 110–114): Combines two sequences with an optional separator

The main orchestrator, generate_wordlist_from_profile (starting around line 171), builds a massive candidate list by populating a dictionary called kombi (keys 1 through 21). Each key stores a list of generated strings. When you modify CUPP to add new password generation patterns, you insert additional entries into this dictionary and ensure the final deduplication loop processes them.

Step-by-Step Guide to Adding Custom Patterns

Locate the Wordlist Generator

Open cupp.py and find the generate_wordlist_from_profile function. This is where CUPP assembles dates, names, and special characters into combinatorial lists. The function already initializes variables like kombinaa (name combinations) and years (birthdate years) before feeding them into komb.

Create and Combine New Source Lists

Identify which existing lists you want to combine, or create new ones. For example, to combine names with a custom separator plus years:


# Inside generate_wordlist_from_profile, after year lists are built

custom_pattern = list(komb(kombinaa, years, "_!"))
kombi[22] = custom_pattern

Use komb(source_list, modifier_list, separator) for string combinations, or concats(base_string, start, end) for numeric ranges.

Update the Deduplication Loop

CUPP deduplicates entries using a loop that currently processes keys 1–21. If you added key 22 (or higher), extend the range:


# Around line 197 in the deduplication section

for i in range(1, 23):  # Increased from 22 to include new key

    komb_unique[i] = list(dict.fromkeys(kombi[i]).keys())

Test Your Changes

Save cupp.py and run CUPP with the interactive flag:

python cupp.py -i

Verify that your new pattern appears in the generated output file.

Practical Code Examples

Adding a Custom Separator Pattern

To create passwords combining pet names with birth years using a double underscore separator:


# After profile data extraction in generate_wordlist_from_profile

pet_year_combo = list(komb(profile["pet"], years, "__"))
kombi[22] = pet_year_combo

Adding a Reverse Name Combination

To append reversed names to pet names without a separator:


# After the reverse list is constructed (around line 639)

rev_name_pet = [rev_name + profile["pet"] for rev_name in rev_name]
kombi[23] = rev_name_pet

Integrating Static Words from Configuration

You can externalize patterns via cupp.cfg. First, add a section to the config:

[custom]
static_words = admin,password,login

Then reference it in generate_wordlist_from_profile:


# Assuming CONFIG is populated by read_config()

static = CONFIG["custom"]["static_words"].split(",")
profile["words"].extend(static)

Leveraging cupp.cfg for Dynamic Patterns

The cupp.cfg file stores default years, special characters, and numeric ranges. When you modify CUPP to add new password generation patterns, you can parameterize them through this config rather than hardcoding values. The read_config function already parses this file into a global CONFIG dictionary accessible throughout cupp.py.

For example, to make a separator configurable:


# In cupp.cfg

[custom]
separator = _!

# In generate_wordlist_from_profile

sep = CONFIG["custom"]["separator"]
custom_entries = list(komb(kombinaa, years, sep))

Summary

  • CUPP generates passwords in cupp.py using the komb and concats helper functions within generate_wordlist_from_profile.
  • New patterns are stored as additional entries in the kombi dictionary using keys above 21.
  • You must extend the range(1, 22) deduplication loop to include your new dictionary keys.
  • Externalize pattern parameters via cupp.cfg to avoid code modifications for simple separator or word changes.
  • All changes compile directly with existing imports and require no modifications to print_to_file or other output functions.

Frequently Asked Questions

What is the kombi dictionary in CUPP?

The kombi dictionary is a storage structure in generate_wordlist_from_profile that holds lists of generated password candidates. Keys 1 through 21 contain standard combinations like name+date or name+special character. When you add new patterns, you assign them to unused keys (22 and above) so the final deduplication and output routines can process them automatically.

How do I add a pattern without modifying the core code?

While CUPP requires Python code changes for new combination logic, you can minimize hardcoding by utilizing cupp.cfg. Add custom sections to the configuration file and read them via the existing CONFIG object. This allows you to adjust separators, static word lists, or numeric ranges without touching the komb function calls directly.

Where are the password patterns actually generated in CUPP?

Password patterns are generated in the generate_wordlist_from_profile function inside cupp.py (starting around line 171). This function calls komb (lines 110–114) to combine user input data and concats (lines 103–107) to append numeric sequences. The results are aggregated into the kombi dictionary before being deduplicated and written to disk.

Can I add patterns that use numeric ranges only?

Yes. Use the concats helper function to generate patterns that append numeric ranges to base strings. For example, concats("admin", 0, 999) produces admin0 through admin999. Insert these results into the kombi dictionary just like string-based combinations to include them in the final wordlist.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →