The Credentials page is the central store for every credential captured across a session — NTLM hashes from Responder, plaintext passwords from netexec, Kerberoast tickets, and manually entered credentials. All saved credentials are automatically available in the Saved Credentials dropdown on every authenticated scan modal.
Database schema
Credentials are stored in the credentials table in data/reaper.db.
| Column | Type | Description |
|---|
id | INTEGER | Primary key, auto-incremented |
username | TEXT | Account name |
password | TEXT | Plaintext password (empty string if hash-only) |
hash | TEXT | NTLM or Kerberos hash (empty string if password-only) |
domain | TEXT | Domain or workgroup |
source | TEXT | Capture source (see below) |
hostname | TEXT | Hostname of the system the credential was captured from |
ip | TEXT | IP address of the source system |
discovered_at | TIMESTAMP | When the credential was first recorded |
Capture sources
The source column identifies where a credential came from. Multiple sources are combined into a comma-separated list when the same credential is found in more than one place.
| Source value | Origin |
|---|
Responder | LLMNR/NBT-NS/mDNS poisoning via Responder |
netexec(SMB) | Imported from netexec SMB workspace database |
netexec(LDAP) | Imported from netexec LDAP workspace database |
lsa_secrets | Imported from netexec LSA dump .secrets files |
kerberoast | TGS ticket hashes from Kerberoast scan |
asreproast | AS-REP hashes from AsRepRoast scan |
gmsa | Group Managed Service Account passwords |
certipy-ESC1 | NTLM hash obtained from automated ESC1 attack chain |
secretsdump | Hashes from impacket secretsdump format file import |
file | Plaintext credentials from file import |
manual | Manually entered via the UI or manual import |
API endpoints
List credentials
Returns all credentials ordered by discovered_at descending.
Response
{
"status": "success",
"credentials": [
{
"id": 1,
"username": "administrator",
"password": "",
"hash": "aad3b435b51404eeaad3b435b51404ee:8846f7eaee8fb117ad06bdd830b7586c",
"domain": "CORP",
"source": "netexec(SMB)",
"hostname": "DC01",
"ip": "10.10.10.10",
"discovered_at": "2024-01-15 12:34:56"
}
]
}
Add a single credential
POST /api/credentials/add
Request body
{
"username": "administrator",
"domain": "CORP",
"password": "Password123!",
"hash": "",
"source": "manual"
}
Either password or hash must be non-empty. source defaults to manual.
Delete a credential
DELETE /api/credentials/{cred_id}
Deletes the credential with the given integer ID.
Bulk delete credentials
POST /api/credentials/bulk-delete
Request body
Response
{ "status": "success", "deleted": 3 }
Import methods
Import from netexec workspaces
POST /api/credentials/import/netexec
Scans all workspaces under ~/.nxc/workspaces/ and imports credentials from each protocol database (SMB, LDAP, FTP, SSH, WinRM, MSSQL, NFS). Returns counts per protocol.
Duplicate detection is performed before inserting. If the same credential already exists under a different source, the sources are merged into a comma-separated list rather than creating a duplicate row.
This endpoint reads from netexec’s local SQLite workspace files. Run an authenticated netexec scan first to populate them.
Response
{
"status": "success",
"imported": 12,
"db_credentials": 10,
"lsa_secrets": 2,
"protocols": {
"smb": 8,
"ldap": 2,
"ftp": 0,
"ssh": 0,
"winrm": 0,
"mssql": 0,
"nfs": 0
}
}
Import LSA secrets
POST /api/credentials/import-lsa-secrets
Reads all *.secrets files from ~/.nxc/logs/lsa/ and extracts plaintext credentials. Filters out noise entries (DPAPI keys, machine account credentials, security questions, etc.) using a fixed exclusion list.
Supported line formats:
All imported credentials are tagged with source lsa_secrets.
Import from file (upload)
POST /api/credentials/import/file
Content-Type: multipart/form-data
Accepts a text file upload. Supports two formats:
Secretsdump format — DOMAIN\user:RID:lmhash:nthash:::
CORP\administrator:500:aad3b435b51404eeaad3b435b51404ee:8846f7eaee8fb117ad06bdd830b7586c:::
CORP\jsmith:1103:aad3b435b51404eeaad3b435b51404ee:2b576acbe6bcfda7294d6bd18041b8fe:::
Imported with source secretsdump. Hash stored as lmhash:nthash.
Plaintext user:pass format — one credential per line
Domain is extracted from user@domain or DOMAIN\user prefixes. Falls back to WORKGROUP if no domain is present. Imported with source file.
Manual text entry
POST /api/credentials/import/manual
Request body
{ "text": "administrator:Password123!\nCORP\\jsmith:Summer2024!" }
Accepts the same secretsdump or user:pass formats as file import. Imported with source manual. Deduplication is enforced — rows with an identical (username, domain, password) or (username, domain, hash) tuple are skipped.
Filtering by source
The UI provides a Filter by source dropdown above the credentials table. Selecting a source filters the visible rows client-side. All rows are fetched in a single GET /api/credentials call.
TXT export
The Export TXT button downloads the currently visible credentials as a plain-text file. The format depends on whether each row contains a password or a hash:
- Password:
domain\username:password
- Hash:
domain\username:hash
Deduplication logic
Before inserting any credential, the backend checks for an existing row with the same (username, domain, hash) or (username, domain, password) tuple. If a match is found:
- The new source is appended to the existing
source field (comma-separated) if not already present.
hostname and ip are filled in if the existing row has blank values (COALESCE(NULLIF(hostname, ''), ?)).
- No duplicate row is created.
Hash Calculator
The Hash Calculator is embedded in the Credentials page. It derives NTLM, AES-128, and AES-256 Kerberos keys from a plaintext password using impacket’s RFC 3962 string_to_key implementation.
How it works
NTLM hash — computed as MD4(UTF-16LE(password)) using Python’s hashlib.new("md4", ...).
Kerberos AES keys — require a username and domain to construct the Kerberos salt. The salt formula follows MS-KILE §3.1.5.2:
| Account type | Salt formula |
|---|
| User account | REALM + username (e.g. CORPadministrator) |
Machine account (ends in $) | REALM + "host/" + name.fqdn (e.g. CORPhost/dc01.corp.local) |
The machine account format is auto-detected from the $ suffix. The machine name is lowercased and the domain is appended as the FQDN component.
AES keys are calculated via:
from impacket.krb5.crypto import string_to_key, Enctype
key128 = string_to_key(Enctype.AES128, password, salt)
key256 = string_to_key(Enctype.AES256, password, salt)
API endpoint
Request body
{
"password": "Password123!",
"username": "administrator",
"domain": "CORP.LOCAL"
}
username and domain are optional. If omitted, only the NTLM hash is returned and aes128/aes256 are null.
Response
{
"status": "success",
"ntlm": "58a478135a93ac3bf058a5ea0e8fdb71",
"aes128": "4a9b1e4a6b2c3d5e6f7a8b9c0d1e2f3a",
"aes256": "1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b"
}
All three values are displayed click-to-copy in the UI. The Save to DB button calls POST /api/credentials/add with the NTLM hash and the username/domain entered.
For machine accounts, enter the account name with the $ suffix (e.g. DC01$) and the Kerberos salt will be constructed correctly as REALM + host/dc01.domain.
Saved credentials in scan dropdowns
Every authenticated scan modal (BloodHound, Kerberoast, ADCS, Domain Info, Delegation, SCCM, etc.) includes a Saved Credentials dropdown. This dropdown is populated by a GET /api/credentials call and lists all stored credentials. Selecting one pre-fills the username, password, and domain fields.