Snaffler Impacket port - find credentials and sensitive data on SMB shares
Project description
snaffler-ng
Impacket port of Snaffler.
snaffler-ng is a post-exploitation / red teaming tool designed to discover readable SMB shares, walk directory trees, and identify credentials and sensitive data on Windows systems. Also works as a local filesystem scanner and a Python library for integration into C2 frameworks and custom tooling.
Features
- SMB share discovery via SRVSVC (NetShareEnum)
- DFS namespace discovery via LDAP (v1 + v2), merged and deduplicated with share enumeration
- Local filesystem scanning (
--local-fs) — same classification engine, no SMB required - Python library API — two-phase classification for C2 integration, duck-typed transport
- Parallel directory tree walking with intra-share fan-out
- 103 built-in regex-based file and content classification rules
- NTLM authentication (password or pass-the-hash)
- Kerberos authentication (with ccache support)
- Multithreaded scanning (DNS / share / tree / file stages) with automatic thread rebalancing
- DNS pre-resolution with TCP port 445 probe to filter stale AD objects
- Archive peeking — scan filenames inside ZIP, 7z, and RAR archives without extraction
- Tree depth limiting (
--max-depth) - Finding post-filter (
--match) — regex filter on findings by hostname, filename, rule, or content - Host exclusion file (
--exclusions) - Optional file download ("snaffling")
- Resume support via SQLite state database (auto-resume on existing DB)
- Share and path filtering by glob pattern (
--share,--exclude-share,--exclude-unc) - Compatible with original and custom TOML rule sets
- Deterministic, ingestion-friendly logging (plain / JSON / TSV)
- Custom DNS resolution (
--nameserver) for internal AD hostname resolution through SOCKS tunnels - SOCKS proxy pivoting (
--socks) - OPSEC mode (
--stealth) — pads LDAP queries to break IDS signatures - Live web dashboard (
--web) for real-time scan monitoring snaffler resultssubcommand to query findings from a scan database (plain / JSON / HTML)- Runtime hotkeys: press
dfor DEBUG,ifor INFO during a scan - Pipe-friendly: accepts NetExec (nxc)
--sharesoutput via--stdin
Installation
pip / pipx
pip install snaffler-ng
# or
pipx install snaffler-ng
Optional extras:
pip install snaffler-ng[socks] # SOCKS proxy support
pip install snaffler-ng[web] # Live web dashboard
pip install snaffler-ng[7z] # 7-Zip archive peeking
pip install snaffler-ng[rar] # RAR archive peeking
# pipx: use --pip-args
pipx install snaffler-ng --pip-args="[socks,web]"
Standalone Binary
Pre-built single-file executables (no Python required) are attached to each GitHub Release:
| Platform | File |
|---|---|
| Linux x86_64 | snaffler-linux-x86_64 |
| Linux aarch64 | snaffler-linux-aarch64 |
| Windows x86_64 | snaffler-windows-x86_64.exe |
Kali / Debian
sudo dpkg -i snaffler-ng_*.deb
Quick Start
Full Domain Discovery
Providing only a domain triggers full domain discovery:
snaffler \
-u USERNAME \
-p PASSWORD \
-d DOMAIN.LOCAL
This will automatically:
- Query Active Directory for computer objects
- Discover DFS namespace targets via LDAP (v1
fTDfs+ v2msDFS-Linkv2) - Resolve hostnames and probe port 445 reachability
- Enumerate SMB shares on discovered hosts
- Merge and deduplicate DFS and SMB share paths
- Scan all readable shares
When using Kerberos, set KRB5CCNAME to a valid ticket cache and use hostnames/FQDNs:
snaffler \
-k \
--use-kcache \
-d DOMAIN.LOCAL \
--dc-host CORP-DC02
Targeted Scans
Scan a specific UNC path (no discovery):
snaffler \
-u USERNAME \
-p PASSWORD \
--unc //192.168.1.10/Share
Scan multiple computers (share discovery enabled):
snaffler \
-u USERNAME \
-p PASSWORD \
--computer 192.168.1.10 \
--computer 192.168.1.11
Load target computers from file:
snaffler \
-u USERNAME \
-p PASSWORD \
--computer-file targets.txt
Local Filesystem Scanning
Scan local directories without any SMB or network configuration:
snaffler --local-fs /mnt/share
snaffler --local-fs /tmp/extracted --local-fs /home/user/Documents
Uses the same classification engine, rules, and multithreaded pipeline as SMB mode — just reads from the local filesystem instead. Useful for:
- Scanning mounted NFS/CIFS shares
- Post-compromise triage of extracted filesystems
- Offline analysis of forensic images
- Testing rules against local data
--local-fs is mutually exclusive with --unc, --computer, --domain, and --stdin.
Archive Peeking
snaffler-ng can look inside ZIP, 7z, and RAR archives without extracting files. Archive members are matched against file rules — if an archive contains web.config or id_rsa, it gets flagged:
# ZIP works out of the box. For 7z and RAR, install optional extras:
pip install snaffler-ng[7z,rar]
Filtering Shares and Directories
Only scan specific shares:
snaffler -u USER -p PASS -d DOMAIN.LOCAL --share "SYSVOL" --share "IT*"
Exclude shares and paths by glob:
snaffler -u USER -p PASS -d DOMAIN.LOCAL \
--exclude-share "IPC$" --exclude-share "print$" \
--exclude-unc "*/Windows/*" --exclude-unc "*/.snapshot/*"
# --exclude-unc works with --local-fs too
snaffler --local-fs /mnt/share --exclude-unc "*/node_modules/*" --exclude-unc "*/.git/*"
Depth Limiting and Post-Filtering
Limit directory recursion depth to avoid deep trees:
snaffler -u USER -p PASS -d DOMAIN.LOCAL --max-depth 5
Filter findings by regex (matches against hostname, filename, rule name, or content):
snaffler -u USER -p PASS -d DOMAIN.LOCAL --match "password|connectionstring"
Exclude specific hosts from scanning:
snaffler -u USER -p PASS -d DOMAIN.LOCAL --exclusions hosts_to_skip.txt
Pipe from NetExec (nxc)
Pipe nxc smb --shares output directly into snaffler-ng with --stdin:
nxc smb 10.8.50.20 -u user -p pass --shares | snaffler -u user -p pass --stdin
This parses NXC's share output, extracts UNC paths, and feeds them into the file scanner. Snaffler's existing share/directory rules handle filtering.
Custom DNS Server
Use --nameserver (or --ns) to resolve hostnames through a specific DNS server instead of the system resolver. Useful for lab environments, split DNS, or any setup where the system resolver can't reach the target domain:
# Point at the DC for name resolution
snaffler -u USER -p PASS -d DOMAIN.LOCAL --dc-host 192.168.201.11 --ns 192.168.201.11
# Combine with SOCKS — DNS queries use TCP and route through the tunnel automatically
snaffler -u USER -p PASS -d DOMAIN.LOCAL --dc-host 192.168.201.11 \
--socks socks5://127.0.0.1:1080 --ns 192.168.201.11
Web Dashboard
Launch a live web dashboard to monitor scan progress and findings in a browser:
snaffler -u USER -p PASS -d DOMAIN.LOCAL --web --web-port 8080
Requires the web extra (pip install snaffler-ng[web]).
Logging & Output Formats
snaffler-ng supports three output formats, each with a distinct purpose:
Plain(default, human-readable)JSON(structured, SIEM-friendly)TSV(flat, ingestion-friendly)
When using -o/--output, the format is auto-detected from the file extension (.json → JSON, .tsv → TSV). Use --log-type to override.
Resume Support
Large environments are expected. Scan state is tracked in a SQLite database (snaffler.db by default).
Scans auto-resume when the state database exists:
# First run — creates snaffler.db
snaffler -u USER -p PASS --computer-file targets.txt
# Interrupted? Just re-run the same command — it picks up where it left off
snaffler -u USER -p PASS --computer-file targets.txt
Use --state to specify a custom database path, or --fresh to ignore existing state and start clean:
snaffler -u USER -p PASS -d DOMAIN.LOCAL --state /tmp/scan1.db
snaffler -u USER -p PASS -d DOMAIN.LOCAL --fresh
Querying Results
After a scan, use snaffler results to query findings from the state database:
snaffler results # plain text summary
snaffler results -f json # JSON output
snaffler results -f html > report.html # HTML report with search bar
snaffler results -b 2 # Red+ severity only
snaffler results -s /path/to/snaffler.db # custom DB path
Library API
snaffler-ng can be used as a Python library for integration into C2 frameworks, custom tooling, or automated pipelines.
Walk a directory
from snaffler import Snaffler
for finding in Snaffler().walk("/mnt/share"):
print(f"[{finding.triage.label}] {finding.file_path}")
if finding.match:
print(f" matched: {finding.match}")
Two-phase classification (for C2 integration)
Minimize beacon traffic — most files are skipped at phase 1 (metadata-only, zero I/O):
from snaffler import Snaffler
from snaffler.api import FileCheckStatus
s = Snaffler()
# Phase 1: metadata only — instant, no file read
check = s.check_file(path, size=4096, mtime_epoch=1700000000.0)
if check.status == FileCheckStatus.NEEDS_CONTENT:
# Phase 2: only download + classify when needed
result = s.scan_content(file_bytes, prior=check)
elif check.status == FileCheckStatus.MATCHED:
result = check.result # matched on filename alone (e.g. ntds.dit)
Custom transport (duck-typed)
Plug in any transport — no ABC required, just implement walk_directory and read:
class BeaconWalker:
def walk_directory(self, path, on_file=None, on_dir=None, cancel=None):
for entry in beacon.ls(path):
if entry.is_dir:
if on_dir: on_dir(entry.path)
elif on_file:
on_file(entry.path, entry.size, entry.mtime)
return [e.path for e in beacon.ls(path) if e.is_dir]
class BeaconReader:
def read(self, path, max_bytes=None):
return beacon.download(path, max_bytes)
s = Snaffler(walker=BeaconWalker(), reader=BeaconReader())
for finding in s.walk("C:\\Users"):
beacon.report(finding.file_path, finding.triage.label)
Constructor parameters
| Parameter | Default | Description |
|---|---|---|
walker |
LocalTreeWalker() |
Directory listing provider |
reader |
LocalFileAccessor() |
File content reader |
rule_dir |
None |
Custom TOML rules directory |
min_interest |
0 |
Minimum severity (0=all, 3=Black only) |
max_read_bytes |
2MB |
Content scan byte limit |
match_context_bytes |
200 |
Context bytes around regex matches |
cert_passwords |
built-in list | Passwords to try on PKCS12 certs |
exclude_unc |
None |
Glob patterns to skip directories (works on any path format despite the name) |
match_filter |
None |
Regex post-filter on findings |
max_depth |
None |
Maximum directory recursion depth |
Authentication Options
- NTLM username/password
- NTLM pass-the-hash (
--hash) - Kerberos (
-k) - Kerberos via existing ccache (
--use-kcache) - SOCKS proxy pivoting (
--socks) - Custom DNS server (
--nameserver/--ns)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file snaffler_ng-1.4.1.tar.gz.
File metadata
- Download URL: snaffler_ng-1.4.1.tar.gz
- Upload date:
- Size: 179.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
20da61dca04f2a38596fb68f6d10798c765dd73b693a4eadfd13fd64535ae426
|
|
| MD5 |
77b1f13c54db1e6ae1eae9dbc93eb6e7
|
|
| BLAKE2b-256 |
e3f722c19cb15ab8950adce09b94a8f342d68a3634aca52e195cca4b234ee7ce
|
File details
Details for the file snaffler_ng-1.4.1-py3-none-any.whl.
File metadata
- Download URL: snaffler_ng-1.4.1-py3-none-any.whl
- Upload date:
- Size: 225.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3b2747c89e4fe08c63ea477bb58279f82dd9919bd3408a0c368053e6e5dc3a41
|
|
| MD5 |
4d66aaabbfd5bb7c9ba35caf65d91b46
|
|
| BLAKE2b-256 |
c7da40ebcbe0c59b5bb854c6bd9e54042a7018d31ce1de5f782e1d68a275d67d
|