# How Leet Mode Affects Password Generation in CUPP: Configuration and Implementation

> Discover how Leet mode in CUPP transforms password generation by substituting letters with leet-speak equivalents and appending variants to wordlists. Learn configuration and implementation details.

- Repository: [Mebus/cupp](https://github.com/Mebus/cupp)
- Tags: deep-dive
- Published: 2026-07-01

---

**Leet mode in CUPP transforms generated passwords by substituting letters with leet-speak equivalents (such as `a → 4` and `e → 3`) and appends these variants to the final wordlist rather than replacing the original candidates.**

The Common User Passwords Profiler (CUPP) is a widely-used tool for generating targeted wordlists for security testing and password auditing. According to the Mebus/cupp source code, the optional leet mode feature systematically expands password candidates by applying character substitutions defined in external configuration files. This transformation significantly increases wordlist coverage by including common "1337 speak" variations that users frequently employ to obfuscate simple passwords.

## Configuration of Leet Mode Mappings

The leet mode transformation relies on a configurable mapping stored in the **[`cupp.cfg`](https://github.com/Mebus/cupp/blob/main/cupp.cfg)** file. Within the **[leet]** section of this configuration file, specific letter-to-number substitutions are defined (for example, `a=4`, `e=3`, `i=1`, `o=0`).

During initialization, CUPP parses these mappings into the `CONFIG["LEET"]` dictionary. As implemented in [`cupp.py`](https://github.com/Mebus/cupp/blob/main/cupp.py) lines 78-84, the parser reads each key-value pair from the configuration section and stores them for use during the transformation process. This modular approach allows users to customize the leet-speak substitutions without modifying the core Python code.

## The make_leet Conversion Function

The actual transformation logic resides in the **`make_leet()`** helper function found in [`cupp.py`](https://github.com/Mebus/cupp/blob/main/cupp.py) lines 95-99. This function iterates over the `CONFIG["LEET"]` dictionary and repeatedly replaces each plain letter with its corresponding leet counterpart.

For example, when processing the word "password", the function systematically substitutes characters according to the configuration rules, potentially producing variants like `p4ssw0rd` or `p@ssw0rd` depending on the defined mappings. The implementation performs these replacements sequentially across the entire mapping table, ensuring comprehensive coverage of all configured substitutions.

## When Leet Mode Is Applied

Leet mode operates as an optional post-processing step that can be triggered in two different execution modes within the Mebus/cupp codebase.

### Interactive Mode (-i)

When running CUPP in interactive mode with the `-i` flag, the script prompts the user with `> Leet mode? (i.e. leet = 1337) Y/[N]:` after building the normal wordlist (as seen in [`cupp.py`](https://github.com/Mebus/cupp/blob/main/cupp.py) lines 66-67). If the user responds with `y`, the script passes every entry in the intermediate list `unique_lista` through the `make_leet()` function. The transformed strings are then appended to the final output list, as implemented in lines 84-92.

### Dictionary Improvement Mode (-w)

In dictionary improvement mode (`-w`), which enhances existing wordlists, a similar prompt appears later in the execution flow (lines 40-41). When enabled, the script transforms each generated word in `unique_lista` using `make_leet()` and merges the results back into the output list, as shown in lines 74-84. This ensures that even when improving existing dictionaries, users can benefit from leet-speak variations.

## Impact on Password Generation

The critical architectural decision in CUPP's leet mode implementation is that **transformed passwords are added to the normal candidates, not substituted for them**. This means the final wordlist contains both the original passwords (such as `john1990`, `admin`) and their leet variants (such as `j0hn1990`, `@dm1n`).

This append-only strategy effectively doubles or triples the wordlist size depending on the number of applicable substitutions, maximizing the probability of matching real-world passwords that employ leet-speak obfuscation. The transformation applies to all candidate types, including concatenations, words with special characters, and date-appended variants.

## Practical Examples

To generate a wordlist with leet mode enabled in interactive mode:

```bash
$ python3 cupp.py -i
> First Name: john
> Surname: doe
> Birthdate (DDMMYYYY): 15051990
...
> Leet mode? (i.e. leet = 1337) Y/[N]: y
[+] Now making a dictionary...

```

The resulting [`john.txt`](https://github.com/Mebus/cupp/blob/main/john.txt) file will contain entries such as:
- `john`
- `john1990`
- `john1990!`
- `j0hn`
- `j0hn1990`
- `j0hn1990!`

To improve an existing wordlist with leet transformations:

```bash
$ python3 cupp.py -w mylist.txt
> Do you want to concatenate all words from wordlist? Y/[N]: n
> Do you want to add special chars at the end of words? Y/[N]: n
> Do you want to add some random numbers at the end of words? Y/[N]: n
> Leet mode? (i.e. leet = 1337) Y/[N]: y
[+] Now making a dictionary...

```

The output file [`mylist.txt.cupp.txt`](https://github.com/Mebus/cupp/blob/main/mylist.txt.cupp.txt) will contain the original words plus leet-transformed copies (for example, `password` → `p4ssw0rd`).

## Summary

- **Leet mode** is configured through the **[leet]** section in [`cupp.cfg`](https://github.com/Mebus/cupp/blob/main/cupp.cfg), mapping letters to numbers like `a=4` and `e=3`.
- The **`make_leet()`** function in [`cupp.py`](https://github.com/Mebus/cupp/blob/main/cupp.py) (lines 95-99) performs the actual character substitution using the `CONFIG["LEET"]` dictionary.
- It can be activated in both **interactive mode** (`-i`) and **dictionary improvement mode** (`-w`) through user prompts defined in the source code.
- Transformed passwords are **appended** to the original wordlist rather than replacing them, significantly expanding coverage.
- This feature targets common user behaviors of replacing vowels with visually similar numbers, increasing the effectiveness of password audits.

## Frequently Asked Questions

### What characters does CUPP replace in leet mode?

The specific character substitutions depend on the **[leet]** section defined in [`cupp.cfg`](https://github.com/Mebus/cupp/blob/main/cupp.cfg). Common defaults include `a=4`, `e=3`, `i=1`, `o=0`, and `s=5`, though users can customize these mappings by editing the configuration file before running the tool.

### Does enabling leet mode replace the original passwords in the wordlist?

No, enabling leet mode does not replace the original passwords. According to the implementation in [`cupp.py`](https://github.com/Mebus/cupp/blob/main/cupp.py) lines 84-92 and 74-84, the leet-transformed variants are appended to the existing wordlist, meaning the final output contains both the original candidates and their leet-speak equivalents.

### Can I use leet mode when improving an existing wordlist?

Yes, leet mode is available in dictionary improvement mode (`-w`). When processing an existing wordlist with the `-w` flag, CUPP prompts users with "Leet mode? (i.e. leet = 1337) Y/[N]:" after other transformation options, allowing you to generate leet variants of existing dictionary entries.

### Where is the leet mode configuration stored in CUPP?

The leet mode configuration is stored in the **[`cupp.cfg`](https://github.com/Mebus/cupp/blob/main/cupp.cfg)** file in the repository root. The Python script parses this file at startup (specifically lines 78-84 in [`cupp.py`](https://github.com/Mebus/cupp/blob/main/cupp.py)) and stores the mappings in the `CONFIG["LEET"]` dictionary, which the `make_leet()` function references during transformation.