pawpy-cli 1.0.0b0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pawpy_cli-1.0.0b0/PKG-INFO +721 -0
- pawpy_cli-1.0.0b0/README.md +663 -0
- pawpy_cli-1.0.0b0/pawpy/__init__.py +8 -0
- pawpy_cli-1.0.0b0/pawpy/__main__.py +6 -0
- pawpy_cli-1.0.0b0/pawpy/api/__init__.py +1 -0
- pawpy_cli-1.0.0b0/pawpy/api/dashboard.py +183 -0
- pawpy_cli-1.0.0b0/pawpy/api/rest.py +145 -0
- pawpy_cli-1.0.0b0/pawpy/cli.py +341 -0
- pawpy_cli-1.0.0b0/pawpy/config.py +60 -0
- pawpy_cli-1.0.0b0/pawpy/data/__init__.py +6 -0
- pawpy_cli-1.0.0b0/pawpy/data/common_passwords.py +139 -0
- pawpy_cli-1.0.0b0/pawpy/data/updater.py +49 -0
- pawpy_cli-1.0.0b0/pawpy/filters/__init__.py +1 -0
- pawpy_cli-1.0.0b0/pawpy/filters/policy.py +59 -0
- pawpy_cli-1.0.0b0/pawpy/generator/__init__.py +5 -0
- pawpy_cli-1.0.0b0/pawpy/generator/core.py +314 -0
- pawpy_cli-1.0.0b0/pawpy/generator/gpu.py +64 -0
- pawpy_cli-1.0.0b0/pawpy/generator/hybrid.py +99 -0
- pawpy_cli-1.0.0b0/pawpy/generator/sorter.py +136 -0
- pawpy_cli-1.0.0b0/pawpy/mutations/__init__.py +20 -0
- pawpy_cli-1.0.0b0/pawpy/mutations/dates.py +72 -0
- pawpy_cli-1.0.0b0/pawpy/mutations/keyboard.py +99 -0
- pawpy_cli-1.0.0b0/pawpy/mutations/leet.py +65 -0
- pawpy_cli-1.0.0b0/pawpy/mutations/mangle.py +238 -0
- pawpy_cli-1.0.0b0/pawpy/mutations/markov.py +125 -0
- pawpy_cli-1.0.0b0/pawpy/mutations/templates.py +131 -0
- pawpy_cli-1.0.0b0/pawpy/profile/__init__.py +5 -0
- pawpy_cli-1.0.0b0/pawpy/profile/base.py +161 -0
- pawpy_cli-1.0.0b0/pawpy/profile/multi.py +93 -0
- pawpy_cli-1.0.0b0/pawpy/profile/plugins/__init__.py +55 -0
- pawpy_cli-1.0.0b0/pawpy/profile/plugins/example.py +22 -0
- pawpy_cli-1.0.0b0/pawpy/scoring/__init__.py +1 -0
- pawpy_cli-1.0.0b0/pawpy/scoring/scorer.py +66 -0
- pawpy_cli-1.0.0b0/pawpy/utils.py +135 -0
- pawpy_cli-1.0.0b0/pawpy_cli.egg-info/PKG-INFO +721 -0
- pawpy_cli-1.0.0b0/pawpy_cli.egg-info/SOURCES.txt +50 -0
- pawpy_cli-1.0.0b0/pawpy_cli.egg-info/dependency_links.txt +1 -0
- pawpy_cli-1.0.0b0/pawpy_cli.egg-info/entry_points.txt +2 -0
- pawpy_cli-1.0.0b0/pawpy_cli.egg-info/requires.txt +19 -0
- pawpy_cli-1.0.0b0/pawpy_cli.egg-info/top_level.txt +1 -0
- pawpy_cli-1.0.0b0/pyproject.toml +6 -0
- pawpy_cli-1.0.0b0/setup.cfg +4 -0
- pawpy_cli-1.0.0b0/setup.py +85 -0
- pawpy_cli-1.0.0b0/tests/test_dates.py +36 -0
- pawpy_cli-1.0.0b0/tests/test_hybrid.py +49 -0
- pawpy_cli-1.0.0b0/tests/test_keyboard.py +18 -0
- pawpy_cli-1.0.0b0/tests/test_leet.py +34 -0
- pawpy_cli-1.0.0b0/tests/test_mangle.py +84 -0
- pawpy_cli-1.0.0b0/tests/test_markov.py +34 -0
- pawpy_cli-1.0.0b0/tests/test_policy.py +47 -0
- pawpy_cli-1.0.0b0/tests/test_profile.py +54 -0
- pawpy_cli-1.0.0b0/tests/test_templates.py +48 -0
|
@@ -0,0 +1,721 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pawpy-cli
|
|
3
|
+
Version: 1.0.0b0
|
|
4
|
+
Summary: Advanced wordlist generator for OSINT, pentesting, and security research
|
|
5
|
+
Home-page: https://github.com/Danyalkhattak/pawpy
|
|
6
|
+
Author: Danyal Khattak
|
|
7
|
+
Author-email: Danyalkhattak739@icloud.com
|
|
8
|
+
Project-URL: Bug Reports, https://github.com/Danyalkhattak/pawpy/issues
|
|
9
|
+
Project-URL: Source, https://github.com/Danyalkhattak/pawpy
|
|
10
|
+
Project-URL: Documentation, https://github.com/Danyalkhattak/pawpy#readme
|
|
11
|
+
Keywords: wordlist,password,osint,pentesting,cybersecurity,security,dictionary,generator,cli,redteam
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Education
|
|
15
|
+
Classifier: Intended Audience :: Information Technology
|
|
16
|
+
Classifier: Intended Audience :: System Administrators
|
|
17
|
+
Classifier: Topic :: Security
|
|
18
|
+
Classifier: Topic :: Utilities
|
|
19
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
20
|
+
Classifier: Programming Language :: Python :: 3
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
27
|
+
Classifier: Operating System :: OS Independent
|
|
28
|
+
Classifier: Environment :: Console
|
|
29
|
+
Requires-Python: >=3.8
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
Requires-Dist: rich>=13.0.0
|
|
32
|
+
Requires-Dist: pyfiglet>=0.8.post1
|
|
33
|
+
Requires-Dist: zxcvbn>=4.4.28
|
|
34
|
+
Provides-Extra: api
|
|
35
|
+
Requires-Dist: fastapi>=0.104.0; extra == "api"
|
|
36
|
+
Requires-Dist: uvicorn>=0.24.0; extra == "api"
|
|
37
|
+
Provides-Extra: gpu
|
|
38
|
+
Requires-Dist: cupy; extra == "gpu"
|
|
39
|
+
Provides-Extra: websocket
|
|
40
|
+
Requires-Dist: websockets>=12.0; extra == "websocket"
|
|
41
|
+
Provides-Extra: all
|
|
42
|
+
Requires-Dist: fastapi>=0.104.0; extra == "all"
|
|
43
|
+
Requires-Dist: uvicorn>=0.24.0; extra == "all"
|
|
44
|
+
Requires-Dist: cupy; extra == "all"
|
|
45
|
+
Requires-Dist: websockets>=12.0; extra == "all"
|
|
46
|
+
Dynamic: author
|
|
47
|
+
Dynamic: author-email
|
|
48
|
+
Dynamic: classifier
|
|
49
|
+
Dynamic: description
|
|
50
|
+
Dynamic: description-content-type
|
|
51
|
+
Dynamic: home-page
|
|
52
|
+
Dynamic: keywords
|
|
53
|
+
Dynamic: project-url
|
|
54
|
+
Dynamic: provides-extra
|
|
55
|
+
Dynamic: requires-dist
|
|
56
|
+
Dynamic: requires-python
|
|
57
|
+
Dynamic: summary
|
|
58
|
+
|
|
59
|
+
# Pawpy
|
|
60
|
+
|
|
61
|
+
**The Most Powerful Wordlist Generator**
|
|
62
|
+
|
|
63
|
+
<p align="center">
|
|
64
|
+
<img src="https://img.shields.io/badge/version-1.0.0-blue" alt="Version" />
|
|
65
|
+
<img src="https://img.shields.io/badge/python-3.8+-green" alt="Python" />
|
|
66
|
+
<img src="https://img.shields.io/badge/license-MIT-orange" alt="License" />
|
|
67
|
+
<img src="https://img.shields.io/badge/purpose-educational%20%7C%20authorised%20testing-red" alt="Purpose" />
|
|
68
|
+
</p>
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## ⚠️ Ethical Use Only
|
|
73
|
+
|
|
74
|
+
Pawpy is designed **exclusively** for authorised security testing, password audits, and educational purposes. Unauthorised use against systems or accounts you do not own or have explicit permission to test is **illegal and unethical**. By using this tool, you confirm you have proper authorisation.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Table of Contents
|
|
79
|
+
|
|
80
|
+
- [Overview](#overview)
|
|
81
|
+
- [Features](#features)
|
|
82
|
+
- [Installation](#installation)
|
|
83
|
+
- [Quick Start](#quick-start)
|
|
84
|
+
- [CLI Reference](#cli-reference)
|
|
85
|
+
- [Profile Format](#profile-format)
|
|
86
|
+
- [Mutation Engine](#mutation-engine)
|
|
87
|
+
- [Scoring & Filtering](#scoring--filtering)
|
|
88
|
+
- [API & Dashboard](#api--dashboard)
|
|
89
|
+
- [OSINT Plugins](#osint-plugins)
|
|
90
|
+
- [Project Structure](#project-structure)
|
|
91
|
+
- [Development](#development)
|
|
92
|
+
- [License](#license)
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Overview
|
|
97
|
+
|
|
98
|
+
Pawpy is an open-source, terminal-based wordlist generator a powerful mutation engine, Markov chain blending, hashcat rule-file support, hybrid mask attacks, and a built-in web dashboard. It transforms target profile information into comprehensive, policy-compliant password candidate lists suitable for authorised penetration testing and security research.
|
|
99
|
+
|
|
100
|
+
The tool follows a modular pipeline architecture: profile data flows through successive mutation stages (leet-speak, mangle rules, date permutations, keyboard walks, Markov blending, custom templates, hashcat rules, hybrid masks) before optional scoring and policy filtering produces the final deduplicated, sorted wordlist.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Features
|
|
105
|
+
|
|
106
|
+
### Core
|
|
107
|
+
|
|
108
|
+
| Feature | Description |
|
|
109
|
+
|---------|-------------|
|
|
110
|
+
| **Interactive Profiling** | Questionnaire for collecting target information |
|
|
111
|
+
| **JSON Import** | Load single or multi-target profiles from JSON files |
|
|
112
|
+
| **Multi-Target Cross-Referencing** | Merge multiple profiles for cross-referenced word generation |
|
|
113
|
+
| **OSINT Plugin System** | Auto-discovery and execution of OSINT plugins from `profile/plugins/` |
|
|
114
|
+
| **Embedded Top 10K Passwords** | Ships with common passwords; auto-updatable from SecLists |
|
|
115
|
+
|
|
116
|
+
### Mutation Engine
|
|
117
|
+
|
|
118
|
+
| Mutation | Description |
|
|
119
|
+
|----------|-------------|
|
|
120
|
+
| **Leet Speak** | 3 substitution levels (basic, extended, aggressive) with combinatorial expansion |
|
|
121
|
+
| **Date Permutations** | 20+ variants per date: DDMM, MMDD, YYYY, YY, with separator combinations |
|
|
122
|
+
| **Common Mangle Rules** | Capitalise, upper, lower, reverse, swapcase, append/prepend digits & symbols |
|
|
123
|
+
| **Hashcat Rule Engine** | Full parser for hashcat/John-style `.rule` files (l, u, c, r, $X, ^X, sXY, iNX, oNX, d, p, z, [N, ]N) |
|
|
124
|
+
| **Static Keyboard Walks** | 25+ built-in classic patterns (qwerty, asdf, zxcvbn, 1qaz2wsx, ...) |
|
|
125
|
+
| **Dynamic Keyboard Walks** | BFS-generated walks on QWERTY adjacency graph up to configurable length |
|
|
126
|
+
| **Two-Word Combinations** | All pairs of base words with 8 separator variants and case combinations |
|
|
127
|
+
| **Year-Word Blends** | Append/prepend years (1990–current) and two-digit years to all base words |
|
|
128
|
+
| **Markov Blending** | Character-level Markov chain (order 1–4) trained on corpus + profile words |
|
|
129
|
+
| **Custom Templates** | Pattern engine: `[FirstName][Year][!]` with token resolution and combinatorial expansion |
|
|
130
|
+
| **Hybrid Mask Attacks** | Simulates hashcat `-a 6` (word + right mask) and `-a 7` (left mask + word) |
|
|
131
|
+
|
|
132
|
+
### Scoring & Filtering
|
|
133
|
+
|
|
134
|
+
| Feature | Description |
|
|
135
|
+
|---------|-------------|
|
|
136
|
+
| **zxcvbn Scoring** | Optional strength-based pruning (scores 0–4) to remove trivially weak candidates |
|
|
137
|
+
| **Policy Filtering** | Enforce minimum length, uppercase, lowercase, digit, and special character requirements |
|
|
138
|
+
|
|
139
|
+
### API & Dashboard
|
|
140
|
+
|
|
141
|
+
| Feature | Description |
|
|
142
|
+
|---------|-------------|
|
|
143
|
+
| **REST API** | FastAPI endpoint (`POST /generate`) accepting profile JSON, returning download URL |
|
|
144
|
+
| **Web Dashboard** | Browser-based UI with real-time WebSocket progress logging |
|
|
145
|
+
|
|
146
|
+
### Performance
|
|
147
|
+
|
|
148
|
+
| Feature | Description |
|
|
149
|
+
|---------|-------------|
|
|
150
|
+
| **Multi-Process** | Configurable worker count via `-t` / `--threads` |
|
|
151
|
+
| **GPU Acceleration** | Optional CuPy-based GPU rule application (graceful fallback to CPU) |
|
|
152
|
+
| **External Merge Sort** | Billion-scale sorting with k-way heap merge for very large wordlists |
|
|
153
|
+
|
|
154
|
+
### Modes
|
|
155
|
+
|
|
156
|
+
| Mode | Flag | Behaviour |
|
|
157
|
+
|------|------|----------|
|
|
158
|
+
| **Normal** | *(default)* | All standard mutations |
|
|
159
|
+
| **Lite** | `--lite` | Skips two-word combos, Markov, large hybrid, dynamic keyboard walks |
|
|
160
|
+
| **Extreme** | `--extreme` | Enables year blends, Markov, dynamic keyboard walks, all heavy mutations |
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Installation
|
|
165
|
+
|
|
166
|
+
### From PyPI (recommended)
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
pip install pawpy
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### From Source
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
git clone https://github.com/Danyalkhattak/pawpy.git
|
|
176
|
+
cd pawpy
|
|
177
|
+
pip install -r requirements.txt
|
|
178
|
+
pip install -e .
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Optional Dependencies
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
# API & Dashboard
|
|
185
|
+
pip install fastapi uvicorn websockets
|
|
186
|
+
|
|
187
|
+
# GPU acceleration (requires CUDA)
|
|
188
|
+
pip install cupy-cuda11x # or cupy-cuda12x depending on your CUDA version
|
|
189
|
+
|
|
190
|
+
# Password strength scoring
|
|
191
|
+
pip install zxcvbn
|
|
192
|
+
|
|
193
|
+
# All optional
|
|
194
|
+
pip install -e ".[all]"
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Quick Start
|
|
200
|
+
|
|
201
|
+
### Interactive Mode
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
pawpy
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
This launches the questionnaire. Answer the prompts (blank answers are fine) and Pawpy generates a wordlist to `pawpy_wordlist.txt`.
|
|
208
|
+
|
|
209
|
+
### From JSON Profile
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
pawpy -j profile.json -o wordlist.txt
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Multi-Target Mode
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
pawpy --multi targets.json --extreme
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### With Hashcat Rules
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
pawpy -j profile.json --rules best64.rule
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Hybrid Mask Attack
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
pawpy -j profile.json --hybrid-right ?d?d?d
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### With Scoring & Policy Filter
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
pawpy -j profile.json --min-strength 2 --min-length 8 --require-upper --require-digit
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Update Common Passwords
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
pawpy update-passwords
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Start API Server
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
pawpy api
|
|
249
|
+
# Server runs at http://127.0.0.1:8000
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Launch Dashboard
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
pawpy dashboard
|
|
256
|
+
# Dashboard runs at http://127.0.0.1:8080
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## CLI Reference
|
|
262
|
+
|
|
263
|
+
```
|
|
264
|
+
usage: pawpy [-h] [-o FILE] [-j FILE] [--multi FILE] [--rules FILE]
|
|
265
|
+
[--template TMPL] [--hybrid-left MASK] [--hybrid-right MASK]
|
|
266
|
+
[--markov] [--markov-order N] [--markov-count N]
|
|
267
|
+
[--min-strength N] [--min-length N]
|
|
268
|
+
[--require-upper] [--require-lower] [--require-digit]
|
|
269
|
+
[--require-special] [--lite] [--extreme]
|
|
270
|
+
[--gpu] [-t N] [-v] [--verbose]
|
|
271
|
+
|
|
272
|
+
Options:
|
|
273
|
+
-o, --output FILE Output file (default: pawpy_wordlist.txt)
|
|
274
|
+
-j, --import-json FILE Import single profile from JSON
|
|
275
|
+
--multi FILE Import multiple profiles from JSON array
|
|
276
|
+
--rules FILE Load hashcat rule file
|
|
277
|
+
--template TEMPLATE Custom pattern template (repeatable)
|
|
278
|
+
--hybrid-left MASK Left mask for hybrid attack (?l?d)
|
|
279
|
+
--hybrid-right MASK Right mask for hybrid attack (?d?d?d)
|
|
280
|
+
--markov Enable Markov chain blending
|
|
281
|
+
--markov-order N Markov chain order (default: 2)
|
|
282
|
+
--markov-count N Number of Markov words (default: 5000)
|
|
283
|
+
--min-strength N Minimum zxcvbn score (0-4)
|
|
284
|
+
--min-length N Minimum password length
|
|
285
|
+
--require-upper Require uppercase letter
|
|
286
|
+
--require-lower Require lowercase letter
|
|
287
|
+
--require-digit Require digit
|
|
288
|
+
--require-special Require special character
|
|
289
|
+
--lite Fast mode (skip heavy combos)
|
|
290
|
+
--extreme Enable all heavy mutations
|
|
291
|
+
--gpu Use GPU acceleration if available
|
|
292
|
+
-t, --threads N Worker process count (default: CPU count)
|
|
293
|
+
-v, --version Show version
|
|
294
|
+
--verbose Enable debug logging
|
|
295
|
+
|
|
296
|
+
Sub-commands:
|
|
297
|
+
update-passwords Download latest common passwords from SecLists
|
|
298
|
+
api Start REST API server
|
|
299
|
+
dashboard Launch web dashboard
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Profile Format
|
|
305
|
+
|
|
306
|
+
### Single Profile (JSON)
|
|
307
|
+
|
|
308
|
+
```json
|
|
309
|
+
{
|
|
310
|
+
"firstname": "John",
|
|
311
|
+
"lastname": "Doe",
|
|
312
|
+
"nickname": "Johnny",
|
|
313
|
+
"birthdate": "01011990",
|
|
314
|
+
"partner": "Jane",
|
|
315
|
+
"partner_nick": "Janey",
|
|
316
|
+
"partner_bdate": "02021992",
|
|
317
|
+
"pet": "Rex",
|
|
318
|
+
"company": "Acme",
|
|
319
|
+
"hometown": "Metropolis",
|
|
320
|
+
"favourite_color": "blue",
|
|
321
|
+
"children": ["Alice", "Bob"],
|
|
322
|
+
"keywords": ["guitar", "hiking"]
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Multi-Target Profile (JSON Array)
|
|
327
|
+
|
|
328
|
+
```json
|
|
329
|
+
[
|
|
330
|
+
{ "firstname": "John", "lastname": "Doe", "pet": "Rex" },
|
|
331
|
+
{ "firstname": "Jane", "lastname": "Doe", "pet": "Buddy" }
|
|
332
|
+
]
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
When using `--multi`, Pawpy merges all profiles into a unified cross-referenced profile. This means base words from all targets are combined, enabling the mutation engine to generate cross-target combinations (e.g., John's first name paired with Jane's pet name).
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## Mutation Engine
|
|
340
|
+
|
|
341
|
+
The mutation pipeline processes base words through multiple stages in sequence:
|
|
342
|
+
|
|
343
|
+
```
|
|
344
|
+
Base Words
|
|
345
|
+
│
|
|
346
|
+
├── Leet Speak (3 levels)
|
|
347
|
+
├── Common Mangle Rules (capitalize, reverse, append/prepend)
|
|
348
|
+
├── Date Permutations (20+ variants per date)
|
|
349
|
+
├── Hashcat Rules (if --rules provided)
|
|
350
|
+
├── Custom Templates (if --template provided)
|
|
351
|
+
├── Keyboard Walks (static + optional dynamic)
|
|
352
|
+
├── Markov Blending (if --markov)
|
|
353
|
+
├── Year-Word Blends (if not --lite)
|
|
354
|
+
├── Two-Word Combinations (if not --lite)
|
|
355
|
+
├── Hybrid Masks (if --hybrid-left/right)
|
|
356
|
+
└── Top 10K Common Passwords
|
|
357
|
+
│
|
|
358
|
+
▼
|
|
359
|
+
Scoring & Policy Filtering
|
|
360
|
+
│
|
|
361
|
+
▼
|
|
362
|
+
Deduplication & Sort → Final Wordlist
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### Leet Speak Levels
|
|
366
|
+
|
|
367
|
+
| Level | Substitutions |
|
|
368
|
+
|-------|---------------|
|
|
369
|
+
| 1 (Basic) | a→@, e→3, i→1, o→0, s→$, t→7 |
|
|
370
|
+
| 2 (Extended) | + i→!, s→5 |
|
|
371
|
+
| 3 (Aggressive) | + a→4, l→1, b→8, g→9, h→# |
|
|
372
|
+
|
|
373
|
+
### Hashcat Rule Support
|
|
374
|
+
|
|
375
|
+
Supported rule commands:
|
|
376
|
+
|
|
377
|
+
| Rule | Description | Example |
|
|
378
|
+
|------|-------------|--------|
|
|
379
|
+
| `l` | Lowercase all | `hello` → `hello` |
|
|
380
|
+
| `u` | Uppercase all | `hello` → `HELLO` |
|
|
381
|
+
| `c` | Capitalise first | `hello` → `Hello` |
|
|
382
|
+
| `s` | Swap case | `Hello` → `hELLO` |
|
|
383
|
+
| `r` | Reverse | `hello` → `olleh` |
|
|
384
|
+
| `d` | Duplicate whole word | `hi` → `hihi` |
|
|
385
|
+
| `p` | Duplicate first char | `hi` → `hhi` |
|
|
386
|
+
| `z` | Duplicate last char | `hi` → `hii` |
|
|
387
|
+
| `$X` | Append char X | `$!` → `pass!` |
|
|
388
|
+
| `^X` | Prepend char X | `^1` → `1pass` |
|
|
389
|
+
| `[N` | Keep first N chars | `[3` → `pas` |
|
|
390
|
+
| `]N` | Keep last N chars | `]3` → `ssw` |
|
|
391
|
+
| `iNX` | Insert char X at pos N | `i2X` → `paXssword` |
|
|
392
|
+
| `oNX` | Overwrite char at pos N with X | `o0X` → `Xassword` |
|
|
393
|
+
| `'XY` | Replace all X with Y | `'a@` → `p@ssword` |
|
|
394
|
+
|
|
395
|
+
### Template Tokens
|
|
396
|
+
|
|
397
|
+
| Token | Resolves To |
|
|
398
|
+
|-------|-------------|
|
|
399
|
+
| `[FirstName]` | First name (original, Capitalised, UPPER, lower) |
|
|
400
|
+
| `[LastName]` | Last name |
|
|
401
|
+
| `[Nickname]` | Nickname |
|
|
402
|
+
| `[Pet]` | Pet name |
|
|
403
|
+
| `[Company]` | Company name |
|
|
404
|
+
| `[Color]` / `[Favourite_Color]` | Favourite colour |
|
|
405
|
+
| `[Partner]` | Partner's first name |
|
|
406
|
+
| `[Child]` / `[Children]` | Children's names |
|
|
407
|
+
| `[Keyword]` / `[Keywords]` | Keywords / interests |
|
|
408
|
+
| `[Year]` | 1986–current year |
|
|
409
|
+
| `[Year2]` | Two-digit years |
|
|
410
|
+
| `[Date]` | Birthdate from profile |
|
|
411
|
+
| `[Digit]` | 0–9 |
|
|
412
|
+
| `[Special]` | !@#$%^&*?._- |
|
|
413
|
+
| `[Upper]` | A–Z |
|
|
414
|
+
| `[Lower]` | a–z |
|
|
415
|
+
| `[Sep]` | Separators: _ - . @ # (empty) |
|
|
416
|
+
| `[123]` | 123, 1234, 12345, !@#, 1q2w3e |
|
|
417
|
+
|
|
418
|
+
Example: `[FirstName][Sep][Year]` with profile `firstname=John` generates:
|
|
419
|
+
`john_2024`, `john-2024`, `john.2024`, `John_2024`, `john@2024`, etc.
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
## Scoring & Filtering
|
|
424
|
+
|
|
425
|
+
### zxcvbn Strength Scoring
|
|
426
|
+
|
|
427
|
+
When `--min-strength N` is provided (requires `zxcvbn` package), each candidate is scored on a 0–4 scale:
|
|
428
|
+
|
|
429
|
+
| Score | Strength | Description |
|
|
430
|
+
|-------|----------|-------------|
|
|
431
|
+
| 0 | Very Weak | Trivially guessable (e.g., `123456`) |
|
|
432
|
+
| 1 | Weak | Easily guessable (e.g., `password1`) |
|
|
433
|
+
| 2 | Fair | Moderately guessable |
|
|
434
|
+
| 3 | Strong | Uncommon but not resistant to targeted attacks |
|
|
435
|
+
| 4 | Very Strong | Highly resistant to cracking |
|
|
436
|
+
|
|
437
|
+
Candidates scoring below the threshold are pruned. This reduces wordlist size by removing trivially weak entries while keeping genuinely strong candidates.
|
|
438
|
+
|
|
439
|
+
### Policy Filtering
|
|
440
|
+
|
|
441
|
+
Combine policy flags to enforce password complexity requirements:
|
|
442
|
+
|
|
443
|
+
```bash
|
|
444
|
+
# At least 8 chars, one uppercase, one digit
|
|
445
|
+
pawpy -j profile.json --min-length 8 --require-upper --require-digit
|
|
446
|
+
|
|
447
|
+
# Complex: 10+ chars, mixed case, digit, special
|
|
448
|
+
pawpy -j profile.json --min-length 10 --require-upper --require-lower \
|
|
449
|
+
--require-digit --require-special
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
---
|
|
453
|
+
|
|
454
|
+
## API & Dashboard
|
|
455
|
+
|
|
456
|
+
### REST API
|
|
457
|
+
|
|
458
|
+
Start the API server:
|
|
459
|
+
|
|
460
|
+
```bash
|
|
461
|
+
pawpy api
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
Endpoints:
|
|
465
|
+
|
|
466
|
+
| Method | Path | Description |
|
|
467
|
+
|--------|------|-------------|
|
|
468
|
+
| GET | `/` | Health check |
|
|
469
|
+
| POST | `/generate` | Generate wordlist (multipart: profile JSON file + options) |
|
|
470
|
+
| GET | `/download/{job_id}` | Download generated wordlist |
|
|
471
|
+
| GET | `/jobs` | List all generation jobs |
|
|
472
|
+
|
|
473
|
+
Example with `curl`:
|
|
474
|
+
|
|
475
|
+
```bash
|
|
476
|
+
curl -X POST http://127.0.0.1:8000/generate \
|
|
477
|
+
-F "profile=@target.json" \
|
|
478
|
+
-F "output=my_wordlist.txt" \
|
|
479
|
+
-F "extreme=true"
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
### Web Dashboard
|
|
483
|
+
|
|
484
|
+
```bash
|
|
485
|
+
pawpy dashboard
|
|
486
|
+
# Open http://127.0.0.1:8080 in your browser
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
The dashboard provides a dark-themed web interface where you can:
|
|
490
|
+
|
|
491
|
+
- Upload a profile JSON file
|
|
492
|
+
- Select generation mode (Normal / Lite / Extreme)
|
|
493
|
+
- Toggle Markov blending and zxcvbn scoring
|
|
494
|
+
- Monitor real-time generation progress via WebSocket
|
|
495
|
+
- Download the resulting wordlist
|
|
496
|
+
|
|
497
|
+
---
|
|
498
|
+
|
|
499
|
+
## OSINT Plugins
|
|
500
|
+
|
|
501
|
+
Pawpy includes a plugin system that auto-discovers Python modules in `pawpy/profile/plugins/`. Each plugin must define a `collect(profile: dict) -> dict` function that enriches the profile dict with OSINT-derived data.
|
|
502
|
+
|
|
503
|
+
### Creating a Plugin
|
|
504
|
+
|
|
505
|
+
Create a new `.py` file in `pawpy/profile/plugins/`:
|
|
506
|
+
|
|
507
|
+
```python
|
|
508
|
+
# pawpy/profile/plugins/my_plugin.py
|
|
509
|
+
|
|
510
|
+
from typing import Any, Dict
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
def collect(profile: Dict[str, Any]) -> Dict[str, Any]:
|
|
514
|
+
"""Enrich profile with OSINT data."""
|
|
515
|
+
# Your OSINT logic here
|
|
516
|
+
# e.g., look up public social media profiles,
|
|
517
|
+
# check for breached credentials (with consent), etc.
|
|
518
|
+
|
|
519
|
+
if profile.get("firstname"):
|
|
520
|
+
keywords = profile.get("keywords", [])
|
|
521
|
+
if isinstance(keywords, str):
|
|
522
|
+
keywords = [keywords]
|
|
523
|
+
# Add OSINT-discovered keywords
|
|
524
|
+
keywords.append("discovered_keyword")
|
|
525
|
+
profile["keywords"] = keywords
|
|
526
|
+
|
|
527
|
+
return profile
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
### Important Rules for Plugin Authors
|
|
531
|
+
|
|
532
|
+
- **Respect rate-limiting** and terms of service of any external APIs or websites.
|
|
533
|
+
- **Only use OSINT data for authorised security testing.**
|
|
534
|
+
- **Follow responsible disclosure** practices.
|
|
535
|
+
- Handle exceptions gracefully so plugin failures don't crash the pipeline.
|
|
536
|
+
|
|
537
|
+
---
|
|
538
|
+
|
|
539
|
+
## Project Structure
|
|
540
|
+
|
|
541
|
+
```
|
|
542
|
+
pawpy/
|
|
543
|
+
├── pawpy/
|
|
544
|
+
│ ├── __init__.py # Package version and metadata
|
|
545
|
+
│ ├── __main__.py # python -m pawpy entry point
|
|
546
|
+
│ ├── cli.py # Full CLI with argparse
|
|
547
|
+
│ ├── config.py # PawpyConfig dataclass
|
|
548
|
+
│ ├── utils.py # Banner, logging, dedup, progress
|
|
549
|
+
│ ├── profile/
|
|
550
|
+
│ │ ├── __init__.py
|
|
551
|
+
│ │ ├── base.py # ProfileCollector (interactive + JSON)
|
|
552
|
+
│ │ ├── multi.py # Multi-target cross-referencing
|
|
553
|
+
│ │ └── plugins/
|
|
554
|
+
│ │ ├── __init__.py # Plugin discovery and loader
|
|
555
|
+
│ │ └── example.py # Example no-op plugin template
|
|
556
|
+
│ ├── mutations/
|
|
557
|
+
│ │ ├── __init__.py
|
|
558
|
+
│ │ ├── leet.py # Leet-speak (3 levels, combinatorial)
|
|
559
|
+
│ │ ├── dates.py # Date permutations (20+ variants)
|
|
560
|
+
│ │ ├── mangle.py # Common rules + hashcat rule engine
|
|
561
|
+
│ │ ├── markov.py # Markov chain training & generation
|
|
562
|
+
│ │ ├── keyboard.py # Static + dynamic keyboard walks
|
|
563
|
+
│ │ └── templates.py # Custom pattern template engine
|
|
564
|
+
│ ├── generator/
|
|
565
|
+
│ │ ├── __init__.py
|
|
566
|
+
│ │ ├── core.py # Main 15-stage pipeline orchestrator
|
|
567
|
+
│ │ ├── hybrid.py # Hybrid mask attacks (hashcat -a 6/7)
|
|
568
|
+
│ │ ├── sorter.py # Billion-scale external merge sort
|
|
569
|
+
│ │ └── gpu.py # Optional CuPy GPU acceleration
|
|
570
|
+
│ ├── scoring/
|
|
571
|
+
│ │ ├── __init__.py
|
|
572
|
+
│ │ └── scorer.py # zxcvbn-based strength pruning
|
|
573
|
+
│ ├── filters/
|
|
574
|
+
│ │ ├── __init__.py
|
|
575
|
+
│ │ └── policy.py # Password complexity policy filter
|
|
576
|
+
│ ├── api/
|
|
577
|
+
│ │ ├── __init__.py
|
|
578
|
+
│ │ ├── rest.py # FastAPI REST endpoints
|
|
579
|
+
│ │ └── dashboard.py # WebSocket web dashboard
|
|
580
|
+
│ └── data/
|
|
581
|
+
│ ├── __init__.py
|
|
582
|
+
│ ├── common_passwords.py # Embedded top 100 + SecLists loader
|
|
583
|
+
│ └── updater.py # Auto-update from SecLists
|
|
584
|
+
├── tests/
|
|
585
|
+
│ ├── __init__.py
|
|
586
|
+
│ ├── test_leet.py
|
|
587
|
+
│ ├── test_dates.py
|
|
588
|
+
│ ├── test_mangle.py
|
|
589
|
+
│ ├── test_markov.py
|
|
590
|
+
│ ├── test_keyboard.py
|
|
591
|
+
│ ├── test_templates.py
|
|
592
|
+
│ ├── test_profile.py
|
|
593
|
+
│ ├── test_hybrid.py
|
|
594
|
+
│ └── test_policy.py
|
|
595
|
+
├── .github/
|
|
596
|
+
│ └── workflows/
|
|
597
|
+
│ └── lint.yml # CI: flake8 + black + isort
|
|
598
|
+
├── requirements.txt
|
|
599
|
+
├── setup.py
|
|
600
|
+
└── README.md
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
---
|
|
604
|
+
|
|
605
|
+
## Development
|
|
606
|
+
|
|
607
|
+
### Setup
|
|
608
|
+
|
|
609
|
+
```bash
|
|
610
|
+
git clone https://github.com/Danyalkhattak/pawpy.git
|
|
611
|
+
cd pawpy
|
|
612
|
+
pip install -e ".[all]"
|
|
613
|
+
pip install pytest
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
### Running Tests
|
|
617
|
+
|
|
618
|
+
```bash
|
|
619
|
+
pytest tests/ -v
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
### Code Quality
|
|
623
|
+
|
|
624
|
+
```bash
|
|
625
|
+
# Lint
|
|
626
|
+
flake8 pawpy/
|
|
627
|
+
|
|
628
|
+
# Format
|
|
629
|
+
black pawpy/
|
|
630
|
+
isort pawpy/
|
|
631
|
+
|
|
632
|
+
# All checks (also run by CI)
|
|
633
|
+
flake8 pawpy/ && black --check pawpy/ && isort --check-only pawpy/
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
### Adding a New Mutation
|
|
637
|
+
|
|
638
|
+
Create a new `.py` file in `pawpy/mutations/` with a function that takes a list of words and returns a list of mutated candidates:
|
|
639
|
+
|
|
640
|
+
```python
|
|
641
|
+
# pawpy/mutations/my_mutation.py
|
|
642
|
+
|
|
643
|
+
def my_mutation(word: str) -> list[str]:
|
|
644
|
+
"""Apply custom mutation to a word."""
|
|
645
|
+
return [word + "_custom", word.upper() + "123"]
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
Then import and call it in `pawpy/generator/core.py` within the `PipelineOrchestrator.run()` method.
|
|
649
|
+
|
|
650
|
+
---
|
|
651
|
+
|
|
652
|
+
## Architecture & Data Flow
|
|
653
|
+
|
|
654
|
+
```
|
|
655
|
+
User Input (CLI / JSON / API)
|
|
656
|
+
│
|
|
657
|
+
▼
|
|
658
|
+
┌─────────────────────┐
|
|
659
|
+
│ Profile Collection │ Interactive / JSON / OSINT Plugins
|
|
660
|
+
└──────────┬──────────┘
|
|
661
|
+
│
|
|
662
|
+
▼
|
|
663
|
+
┌─────────────────────┐
|
|
664
|
+
│ Base Word Extract │ All text fields → lowercase, deduplicated
|
|
665
|
+
│ + Date Extraction │
|
|
666
|
+
└──────────┬──────────┘
|
|
667
|
+
│
|
|
668
|
+
▼
|
|
669
|
+
┌──────────────────────────────────────────┐
|
|
670
|
+
│ Mutation Pipeline │
|
|
671
|
+
│ ┌──────────┐ ┌──────────┐ ┌───────────┐ │
|
|
672
|
+
│ │ Leet │ │ Mangle │ │ Dates │ │
|
|
673
|
+
│ └──────────┘ └──────────┘ └───────────┘ │
|
|
674
|
+
│ ┌──────────┐ ┌──────────┐ ┌───────────┐ │
|
|
675
|
+
│ │ Keyboard │ │ Markov │ │ Templates │ │
|
|
676
|
+
│ └──────────┘ └──────────┘ └───────────┘ │
|
|
677
|
+
│ ┌──────────┐ ┌──────────┐ ┌───────────┐ │
|
|
678
|
+
│ │ Hybrid │ │ Rules │ │ Combos │ │
|
|
679
|
+
│ └──────────┘ └──────────┘ └───────────┘ │
|
|
680
|
+
└────────────────────┬─────────────────────┘
|
|
681
|
+
│
|
|
682
|
+
▼
|
|
683
|
+
┌──────────────────────────────────────────┐
|
|
684
|
+
│ Scoring & Filtering │
|
|
685
|
+
│ zxcvbn strength │ Policy compliance │
|
|
686
|
+
└────────────────────┬─────────────────────┘
|
|
687
|
+
│
|
|
688
|
+
▼
|
|
689
|
+
┌──────────────────────────────────────────┐
|
|
690
|
+
│ Sort + Deduplicate │
|
|
691
|
+
│ (in-memory or external merge sort) │
|
|
692
|
+
└────────────────────┬─────────────────────┘
|
|
693
|
+
│
|
|
694
|
+
▼
|
|
695
|
+
Final Wordlist File
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
---
|
|
699
|
+
|
|
700
|
+
## Performance Notes
|
|
701
|
+
|
|
702
|
+
- **Throughput**: On an 8-core CPU, the system targets ≥10 million passwords/minute for basic mutations.
|
|
703
|
+
- **Memory**: By default, stays under 2 GB RAM. For very large generation jobs, the external merge sorter handles disk-backed processing.
|
|
704
|
+
- **Output**: Written sequentially for optimal I/O. Sorted chunks are merge-sorted efficiently.
|
|
705
|
+
- **GPU**: Optional CuPy acceleration for rule application. Falls back gracefully to CPU if CuPy is not installed.
|
|
706
|
+
|
|
707
|
+
---
|
|
708
|
+
|
|
709
|
+
## License
|
|
710
|
+
|
|
711
|
+
MIT License. See [LICENSE](LICENSE) for details.
|
|
712
|
+
|
|
713
|
+
---
|
|
714
|
+
|
|
715
|
+
## Acknowledgements
|
|
716
|
+
|
|
717
|
+
- [CUPP](https://github.com/Mebus/cupp) – Original inspiration for interactive profiling
|
|
718
|
+
- [Hashcat](https://hashcat.net/wiki/doku.php?id=rule_based_attack) – Rule engine format
|
|
719
|
+
- [SecLists](https://github.com/danielmiessler/SecLists) – Common password data source
|
|
720
|
+
- [zxcvbn](https://github.com/dropbox/zxcvbn) – Password strength estimation
|
|
721
|
+
- [Rich](https://github.com/Textualize/rich) – Beautiful terminal output
|