Skip to main content

AdPentestAI-Python

Version 2.14.213.78.21.13 updates the PyPI user guide with an emphasis on Kerberos evidence and backward compatibility. Runtime behavior is unchanged from .12: website entrypoint inventory, detailed JSON/HTML reports, explicit F5/FortiGate access review and existing diagnostics remain compatible.

User guide

Install and choose a profile

Use Python 3.10 or newer in a virtual environment:

python -m venv .venv
python -m pip install --upgrade "adpentest==2.14.213.78.21.13"
python -c "import adpentest; print(adpentest.__version__)"

Activate the environment before the last two commands: source .venv/bin/activate on Linux/macOS, or .\.venv\Scripts\Activate.ps1 in Windows PowerShell. The adpentest console command and python -m adpentest use the same dispatcher. Use ./python only when a Python executable actually exists in the current directory.

Select the profile explicitly; their parsers accept different options:

Goal Profile Data collected
Inventory public login gateways --entrypoint-check Bounded DNS, HTTP and TLS observations
Map one host's TCP/VPN UDP ports --ALL-PORTS, or --port-map Nmap port states
Review F5/FortiGate API access --entrypoint-check --vpn-access-check both Unauthenticated API responses and public login controls
Inventory exported AD accounts --ldap-spn-data FILE Local JSON records and SPN observations
Review existing Kerberos tickets --ticket-inventory Current user's local cache metadata
Other legacy AD workflows No explicit profile above Existing broad legacy scanner; see the reference below

Examples use reserved documentation domains. Replace them with systems covered by your approved scope. For the network profiles below, the default dry-run does no DNS queries or remote requests, but can write local reports and SQLite history. --mode active --scope-confirmed enables traffic; the flag records your scope declaration, rather than independently establishing authorization.

Website and organization login gateways

Start with a preview:

python -m adpentest --entrypoint-check --target https://www.example.com --domain example.com --ALL-PORTS --mode dry-run --db-path ./scan_history.db --info-report ./entrypoints-plan.json --html-report ./entrypoints-plan.html

For an approved active inventory, use new output filenames:

python -m adpentest --entrypoint-check --target https://www.example.com --domain example.com --ALL-PORTS --mode active --scope-confirmed --db-path ./scan_history.db --info-report ./entrypoints.json --html-report ./entrypoints.html

--domain explicitly defines the organization scope when the website is a subdomain. Without it, the profile uses the exact target hostname as its domain; it does not infer a parent from www. Additional approved hosts can be supplied with repeatable --entrypoint-host HOST inside that domain.

In this profile, --ALL-PORTS alone expands gateway candidates, without mapping ports. Its fixed candidates are vpn, remote, sso, login, portal, mail, webmail, adfs and rdweb under the explicit domain. The inventory remains bounded: at most 16 hosts, 32 HTTP requests and 64 KiB per response body, with a default 60-second total inventory deadline. Set --timeout between 1 and 120 seconds to change that deadline. This is a bounded inventory rather than exhaustive subdomain discovery.

Active inventory uses approved public DNS addresses, verified TLS and fixed read-only HTTP paths. It does not follow redirects, submit login forms, send credentials or retain response bodies. Private or mixed public/private DNS answers block a website host; a private AD controller belongs to a separate workflow. Product markers are candidates requiring owner review.

Combined port map and F5/FortiGate access review

The following previews gateway inventory, full TCP mapping and both vendor access reviews on the exact target host:

python -m adpentest --entrypoint-check --target adfs.example.com --domain example.com --ALL-PORTS --port-map --port-map-timeout 600 --vpn-access-check both --mode dry-run --db-path ./scan_history.db --info-report ./combined-plan.json --html-report ./combined-plan.html

For the approved active run:

python -m adpentest --entrypoint-check --target adfs.example.com --domain example.com --ALL-PORTS --port-map --port-map-timeout 600 --vpn-access-check both --mode active --scope-confirmed --db-path ./scan_history.db --info-report ./combined.json --html-report ./combined.html

--port-map adds Nmap TCP ports 1–65535 and the fixed VPN UDP ports 500, 1194, 1701, 4500 and 51820 when combined with --ALL-PORTS. This does not map every discovered subdomain. Install Nmap separately and put it on PATH; the entrypoint profile never automatically installs external tools. UDP discovery may need elevated local privileges. A 600-second mapping deadline can expire before all ports finish; inspect status and truncation indicators. For a selected TCP range, replace --ALL-PORTS with --ports 443,8443 and keep --port-map. The two port-selection options cannot be combined.

If the actual VPN gateway differs from the website target, select it explicitly:

python -m adpentest --entrypoint-check --target adfs.example.com --domain example.com --vpn-access-check both --vpn-access-host vpn.example.com --mode dry-run --db-path ./scan_history.db --info-report ./vpn-plan.json --html-report ./vpn-plan.html

--vpn-access-check accepts f5, forti or both. Repeat --vpn-access-host for up to four approved hosts inside the domain. The default is the exact website target; gateway discovery never automatically enables access checks on every subdomain. Selecting a VPN host does not move the diagnostic port map to that host: use a separate one-host port-map command if that gateway also needs mapping.

The vendor review performs credential-free GET requests to the F5 management status endpoint and login control, or the FortiGate system status endpoint and login control. It records denials, redirects without following them, missing endpoints, login pages, errors and recognized unauthenticated API responses. Only bounded classifications, metadata and body hashes are retained; API values are omitted. Public login pages or HTTP 200 alone do not establish bypass. Even a recognized status response requires the owner's access-policy review. VPN tunnel access, MFA bypass and CVE exploitation are not tested or confirmed. See the detailed entrypoint reference.

Detailed reports and existing databases

Output Option Contents
JSON evidence --info-report ./review.json Scope, coverage, planned/performed/skipped requests, HTTP timings, DNS answers/TTLs, TLS metadata, errors, VPN review and combined diagnostics
Standalone HTML --html-report ./review.html The same evidence in readable tables, full request details, review guidance and print styles; no external scripts or resources
SQLite history --db-path ./scan_history.db Existing diagnostic ORM records and entrypoint results, with persistence receipts

Choose distinct, new report paths in an existing directory. Report files are not overwritten. Reusing an existing database preserves its older tables; required ORM tables are added. Combined diagnostics and entrypoint inventory have their own persisted records. Check the JSON persistence receipts rather than assuming the presence of a report proves a successful database write.

Read coverage, errors and skipped work before interpreting results. A dry-run report is a plan. Timeouts, blocked addresses, missing tools and unperformed checks leave coverage incomplete. Port states and tentative vendor markers do not prove vulnerabilities. Older reports retain missing evidence as Not recorded in the HTML renderer.

Kerberos review: SPNs, encryption and existing tickets

Keep three kinds of evidence distinct: an account's exported configuration, an already issued ticket in the current user's local cache, and a remote port state. These profiles do not perform a Kerberos login or enumerate users by testing guessed account names against a KDC.

Evidence What to inspect Limit of the observation
Exported servicePrincipalName Parsed service class, hostname, optional port and duplicate owners Registration does not prove that the service is reachable or the account can authenticate.
Exported msDS-SupportedEncryptionTypes Advertised DES, RC4 and AES bits; unknown/missing values Effective ticket encryption remains not_assessed; a missing value does not prove RC4.
Exported account status/timestamps UAC-derived disabled state and supplied password/logon dates Export metadata does not establish current access or a complete authentication history.
Local TGT and service tickets Client/server principals, ticket/session encryption, flags and validity timestamps Current user's default cache only; no other sessions or directory-wide user inventory.
TCP 88/464 port states A limited endpoint connectivity observation Open ports do not establish successful Kerberos authentication, service identity or a CVE.

Use the offline account command in the next section to review SPNs and advertised encryption. Duplicate-SPN groups identify different GUID/DN owners in the supplied export; reconcile them with the directory administrator. An account without an SPN still appears in accounts.

For existing tickets, preview and then collect metadata locally:

python -m adpentest --ticket-inventory --mode dry-run --domain lab.example --db-path ./scan_history.db --ticket-report ./tickets-plan.json
python -m adpentest --ticket-inventory --mode active --domain lab.example --db-path ./scan_history.db --ticket-report ./tickets.json

This independent route uses the system klist for the current user's existing default cache. active enables the local collector, without selecting a remote target; --domain only groups saved results. Use --ticket-report for its JSON file, rather than the website profile's report options. It saves sanitized metadata through the existing ORM and discards raw command output. Ticket bytes and session-key values are not exported. Collection does not request, renew, purge, inject or replay tickets.

Inspect inventory.status and ticket_count. Missing klist, unsupported localization/format, incomplete or truncated output means unknown coverage, rather than zero tickets. English Windows and MIT Kerberos output are supported; there is a 256-ticket parser limit. Timestamps retain their source format, without guessing timezones or expiration state. Observed RC4/DES algorithm names are manual configuration-review findings, not confirmed vulnerabilities. See the ticket inventory reference.

If TCP port mapping is needed, select a controller already identified and approved by its administrator, rather than assuming an ADFS website is a KDC:

python -m adpentest --port-map --ports 88,464 --target dc.lab.example --domain lab.example --mode dry-run --db-path ./scan_history.db

This maps only the selected TCP ports using Nmap. It does not test UDP Kerberos, request tickets or authenticate. For an approved remote run, change to --mode active --scope-confirmed. Effective encryption, preauthentication, delegation policy and KDC security-update status require separate administrator evidence; the metadata profiles do not verify them. Microsoft references: klist and encryption attribute.

AD users: analyze an existing authorized export

A public website or ADFS login page cannot supply a complete AD user directory through the entrypoint profile. There is no FULLY SCAN FOR DETECTION USERS switch. Use an existing authorized directory export for account inventory:

python -m adpentest --ldap-spn-data ad-users.json > ad-users-report.json

This route reads local files and outputs JSON. It accepts a JSON array of flat account records, ldap3-style { "dn": "...", "attributes": { ... } } entries, or an { "entries": [ ... ], "rootdse": { ... } } envelope. UTF-8 with an optional BOM is supported. Limits are 8 MiB per input file, 50,000 records and 200,000 SPN values. Split larger exports into appropriately scoped files; duplicate-SPN analysis then covers only the records in each file.

The report includes every supplied account, including accounts without SPNs: sAMAccountName, GUID/DN identity, object classes, UAC-derived disabled status, supplied timestamps, advertised encryption types and parsed SPNs. It also reports duplicate SPNs and unknown account status. An exported username is an observation, not a live authentication check. Missing UAC remains unknown.

An optional RootDSE export can be supplied with --ldap-spn-rootdse rootdse.json. Use --ldap-spn-complete only to record your own completeness declaration; directory_completeness_verified remains false. A website scan, RootDSE response or successful parse cannot verify a complete domain/forest account inventory. Do not combine this offline route with --domain, --mode, --db-path, --info-report or --html-report; it has a separate parser and no automatic ORM or HTML output. In PowerShell, use explicit UTF-8 output instead of legacy >:

python -m adpentest --ldap-spn-data ad-users.json | Set-Content -Encoding utf8 ad-users-report.json

Try the synthetic two-account JSON export, supplied in the source distribution. Download it as ad-users.json; its expected coverage is two entries, one disabled account and one SPN. It contains no real organization data.

Administrator export example

On a Windows administration workstation with the ActiveDirectory PowerShell module, directory connectivity and an account authorized to read the selected scope, export the supported attributes from an explicit approved controller:

Import-Module ActiveDirectory
$dc = 'dc.lab.example'
$searchBase = 'OU=Users,DC=lab,DC=example'
$entries = @(Get-ADUser -Server $dc -SearchBase $searchBase -Filter * -ErrorAction Stop -Properties userAccountControl,servicePrincipalName,msDS-SupportedEncryptionTypes,pwdLastSet,lastLogonTimestamp |
    Select-Object distinguishedName,sAMAccountName,userAccountControl,'msDS-SupportedEncryptionTypes',pwdLastSet,lastLogonTimestamp,
        @{Name='objectGUID';Expression={$_.ObjectGUID.ToString()}},
        @{Name='objectClass';Expression={@('top','person','organizationalPerson','user')}},
        @{Name='servicePrincipalName';Expression={@($_.servicePrincipalName)}})
ConvertTo-Json -InputObject $entries -Depth 6 | Set-Content -Encoding utf8 ad-users.json
python -m adpentest --ldap-spn-data ad-users.json | Set-Content -Encoding utf8 ad-users-report.json

Replace the controller and search base with your authorized values. This read-only export uses the current Windows identity and covers users in the selected search base; it does not include all forests, computers, groups or managed service accounts. Review permissions, export errors and scope before declaring completeness. The script does not add a network-query feature to AdPentest. Microsoft references: Get-ADUser and ConvertTo-Json.

Compatibility and troubleshooting

Existing standalone diagnostic and legacy AD commands retain their behavior. The adpentest[smb] installation extra remains a compatibility alias; Impacket is already a required dependency. Existing entrypoint report fields and the original bounded planned_requests list remain available; full coverage and combined diagnostic results are additive fields. Existing report consumers should tolerate additional keys.

Existing integration Compatibility in this release
.12 CLI scripts Runtime arguments and defaults are unchanged; .13 updates documentation and release metadata.
.11 entrypoint inventory with --ALL-PORTS alone Retains inventory-only behavior. Diagnostic port mapping requires an explicit diagnostic selection such as --port-map.
Existing --db-path SQLite history Older rows/tables remain intact; new ORM tables are additive. Historical findings are not reclassified by upgrading.
Existing entrypoint JSON consumers Schema version 1 and original root fields remain; new evidence fields are additive, and combined diagnostics retain their own schema version 2.
Existing report-generator imports generate_html_report and export_html_report remain exported from adpentest.
Older Kerberos metadata workflows --ticket-inventory and offline --ldap-spn-data remain separate routes with their existing options, rather than being folded into website scans.
Existing adpentest[smb] install commands Remain accepted; Impacket is a mandatory dependency.

To upgrade an existing installation, first back up its history database while no scan is writing to it, then install the pinned version above. Keep your existing command arguments and validate the selected profile in dry-run with new report filenames before the next active run. Compare scope, planned work and persistence receipts. Do not add website-profile options to legacy or offline scripts merely because the new guide shows them in other examples. This documentation release does not retroactively change old findings or guarantee compatibility of independently installed external executable versions.

Symptom Action
Unrecognized -vpn-access-check Use the double-hyphen --vpn-access-check and the --entrypoint-check profile.
No port map with gateway inventory Add --port-map alongside --ALL-PORTS.
Wrong host selected for VPN review Supply --vpn-access-host explicitly; the default is the exact website host.
Missing Nmap or another diagnostic executable Install the selected tool separately and verify PATH; review the recorded missing-tool result.
Existing JSON/HTML path rejected Choose a new filename and ensure its parent directory exists.
Website host blocked by DNS scope Inspect the recorded addresses and scope; this public profile rejects private/mixed answers.
Offline account count is unexpected Inspect coverage.entry_count, export scope and errors; the analyzer cannot discover omitted users.
Options from different profiles rejected Read the selected route's help, e.g. --entrypoint-check --help or --ldap-spn-data ad-users.json --help.

Do not mix --active-search or --pentest-technique into the entrypoint or offline account commands. The legacy broad scanner is not a users-only inventory. See release notes for this documentation release.

Other supported profiles

Local Kerberos ticket metadata for the current user's existing cache:

python -m adpentest --ticket-inventory --mode active --db-path ./ticket-history.sqlite

This independent route lists principals, TGT/service type, encryption, flags and validity timestamps, and saves sanitized metadata through the existing ORM. It does not start a target scan or export ticket/key material. The default mode is a dry run. See ticket inventory and CVE evidence handling.

DNS metadata checks for one host with an explicit resolver:

python -m adpentest --dns-check --target files.lab.example --dns-server 192.0.2.53 --mode active --scope-confirmed --db-path ./dns-history.sqlite

This route records A/AAAA/CNAME/PTR evidence, TTLs, lookup errors and a bounded forward/reverse check in the ORM. It requires no Nmap executable. See DNS host diagnostics for resolver selection, limits and the existing hostname-based service configuration checks.

The PyPI 2.14.213.78.21.6 files published on 2026-10-06 are the cb4ce2426765704ddb53d14276e5aacb2cf238fa snapshot. The features introduced in .7 and retained in .10 are absent from those published .6 files. See the verified artifact provenance.

SMBv1 host, user and UNC inventory from existing exports (2.14.213.78.21.10):

python -m adpentest --smbv1-data existing-report.json
python -m adpentest --smbv1-data existing-report.json --smbv1-only --smbv1-host fileserver --smbv1-user alice --smbv1-unc Team
python -m adpentest --smbv1-data existing-nmap.xml --smbv1-db ./scan_history.db

This local-file route reports enabled, disabled, unknown or conflicting SMBv1 evidence, exported usernames and UNC paths with source references. Search filters select whole host records and combine with AND. Share roots built from an exported host and share name are marked as constructed; usernames and paths do not establish account validity or share access. Try the synthetic inventory. See SMBv1 export analysis for formats and API use.

SMBv1ExportParser provides parse_json, parse_xml, parse_text, parse_data and parse_file. Its reports can be saved to SQLAlchemy import, host, user and UNC tables, with source evidence and relationships:

from adpentest.smbv1_data import SMBv1ExportParser

parser = SMBv1ExportParser()
report = parser.parse_file("existing-nmap.xml")  # JSON files work too.
receipt = parser.save_to_orm(report, "scan_history.db")

See class and ORM examples.

Single-host TCP and VPN UDP port inventory is explicitly selected with --ALL-PORTS (or --all-ports), including targets without an AD controller:

python -m adpentest --ALL-PORTS --target vpn.example --mode dry-run --db-path ./vpn-history.sqlite

This selects TCP 1-65535 and UDP 500, 1194, 1701, 4500 and 51820 with Nmap. PPTP control port 1723 is included; its GRE prerequisite is reported as untested. Results are port states and candidate labels, without service or vulnerability verification. See VPN port prerequisites and output.

For a PPTP control check on one endpoint:

python -m adpentest --pptp-check --target vpn.example --mode dry-run --domain lab.example --info-report ./pptp-review.json --db-path ./pptp-history.sqlite

Choose --mode active --scope-confirmed for an authorized control exchange. It uses Python's standard library on TCP/1723, validates the bounded reply, records the server's result code and metadata, and closes its connection. Domain-linked ORM history includes failures and dry runs. Authentication, GRE and VPN tunnel connectivity are reported as untested. See PPTP checks.

For fixed TLS certificate, SMB and SSH metadata checks with a configuration review report:

python -m adpentest --info-checks --target vpn.example --mode dry-run --info-report ./information-review.json --db-path ./information-history.sqlite

Active collection requires --mode active --scope-confirmed. The report retains evidence, unknown checks and review guidance; it does not confirm CVEs or run exploit probes. See information checks and reporting.

Single-host diagnostics accept an exclusive DNS server list:

python -m adpentest --target fileserver.lab.example --smbv1-check --dns-server="192.0.2.53,2001:db8::53" --dns-timeout 3 --db-path ./scan_history.db --mode dry-run

Active diagnostics pin one resolved address. Public IP inputs use a forward-confirmed PTR FQDN in host and target, retaining input_host, input_target and resolved_address. A public IP without a verified FQDN is recorded as dns-name-unavailable and is not probed. Targets in 172.16.199.0/24, including hostname answers, are recorded as ignored. Dry runs perform no DNS queries. Completed, untruncated single-host Nmap XML is automatically parsed through SMBv1ExportParser into linked ORM inventory rows in the selected database. See DNS and XML persistence.

To check protocol negotiation on one authorized host, with Nmap installed:

python -m adpentest --diagnostic-tools nmap_smbv1 --target 192.0.2.10 --mode active --scope-confirmed

This opt-in profile checks TCP 445 and saves raw output and a structured SMBv1 observation through the diagnostic ORM. Nmap commands always include -vv for increased verbosity; diagnostic captures retain the existing 65,536-byte limit per stream and flag truncated output. See diagnostic profiles. The Python SMB client (impacket>=0.13,<0.14) is a required package dependency:

python -m pip install --upgrade --no-cache-dir --index-url https://pypi.org/simple "adpentest==2.14.213.78.21.13"

With Nmap on PATH, run the combined built-in diagnostics on one host you administer:

python -m adpentest --target 192.0.2.10 --port-map --ports 1-65535 --port-map-timeout 600 --smbv1-check --smbv1-access --smb-share SHARE --smb-user alice --smb-domain LAB --mode active --scope-confirmed

The SMB password is prompted without echo. The access profile negotiates SMBv1, authenticates once using the supplied existing account, and returns a root directory listing for the specified share. It rejects guest sessions. Results are stored in diagnostic ORM history; passwords are passed to the worker over a private pipe. Omit --mode active --scope-confirmed to preview all three operations without network traffic or a password prompt. See port mapping and SMB access for prerequisites, result fields and timeouts.

GitHub stars GitHub issues License: MIT Python 3.10+ PyPI

Active Directory penetration testing framework with automatic Domain Controller detection, multi-threaded tool execution, WAF bypass engine, CVE scanning, and SQLite scan history.

For authorized penetration testing only. Always get explicit written permission before testing any systems.


Table of Contents


Quick Start

This section describes the existing broad legacy scanner. For website gateways and exported user inventories, use the explicit profiles in the user guide above. Its active workflows have a wider scope than the entrypoint profile.

pip install adpentest

# Dry-run — preview what would execute, no actual tool runs
adpentest --target 10.0.0.1 --mode dry-run --scope-confirmed

# Active scan with auto DC detection
adpentest --target corp.local --mode active --scope-confirmed

# View scan history
adpentest --history

# View all vulnerable CVE findings
adpentest --cve-report

Features

Core Capabilities

  • Auto DC Detection — discovers Domain Controllers via DNS SRV records, LDAP RootDSE probes, port fingerprinting, and subnet sweep
  • Multi-threaded execution — 16 parallel workers for tool execution, 32 workers for port/DNS/credential tasks (10-15x speedup)
  • 35+ AD/SMB/Kerberos/ADCS/Email tools — cross-platform binary tools + pure Python implementations
  • 7 CVE scanners — automated detection of critical AD vulnerabilities (CVSS 7.5-9.4)
  • WAF detection & bypass — identifies WAF/CDN vendors and attempts bypass via HTTP spoofing, raw LDAP/Kerberos, TCP fragmentation
  • SQLite scan history — persistent storage of all scan runs, tool results, and CVE findings
  • Auto-install — missing tools installed automatically via apt/pip/git
  • Safety — dry-run is the default mode; --scope-confirmed required for authorization

Attack Vectors

Category Tools Description
Reconnaissance nmap, masscan, enum4linux-ng, rpcdump, bloodhound-python, ldapdomaindump Network & AD enumeration
SMB smbclient, smbmap, crackmapexec, impacket Null sessions, share enum, signing detection, credential testing
Kerberos GetUserSPNs, AS-REP roast, Kerberoast, kerbrute SPN enum, ticket extraction, user enumeration
ADCS certipy (find, shadow, ESC1, ESC3, ESC9) Certificate template analysis & exploitation
Email SMTP/POP3/IMAP enum & auth testing User discovery, credential testing, Exchange detection
Privilege Escalation ACL scanner, GPO abuse, delegation chain, auto privesc Permission analysis & escalation paths
Persistence Golden/silver ticket, DCshadow, skeleton key, DSRM, SID history Domain persistence techniques
Coercion & Relay PetitPotam, PrinterBug, NTLM relay Authentication coercion attacks
CVE Scanning 7 dedicated scanners Certighost, ResetNightmare, NTLM bypass, RC4, RPC RCE

Installation

From PyPI

pip install adpentest

From Source

git clone https://github.com/netanelcyber/AdPentestAI-Python.git
cd AdPentestAI-Python
pip install -e .

Dependencies

Package Version Purpose
httpx >= 0.27 HTTP client for EWS/web enumeration
dnspython >= 2.4 DNS resolution with SRV record support
ldap3 >= 2.9 LDAP operations (RootDSE, anonymous bind)
impacket >= 0.13, < 0.14 Required Python SMB backend

Standard library modules used: smtplib, poplib, imaplib, socket, concurrent.futures, subprocess, sqlite3, json.


Usage

Basic Scans

# Dry-run (check tools, detect DCs, preview commands — no actual execution)
adpentest --target 10.0.0.1 --mode dry-run --scope-confirmed

# Active scan with auto DC detection
adpentest --target corp.local --mode active --scope-confirmed

# Custom timeout and no auto-install of missing tools
adpentest --target 192.168.1.10 --mode active --scope-confirmed --timeout 600 --no-auto-install

# Custom DNS servers
adpentest --target corp.local --mode active --scope-confirmed --dns-server 1.1.1.1,8.8.8.8

# Connect via VPN before scanning
adpentest --target 10.10.10.1 --mode active --scope-confirmed --vpn lab.ovpn

Scan History & Reports

# Show all past scan runs
adpentest --history

# Show last 5 runs
adpentest --history --history-limit 5

# Show all vulnerable CVE findings across all runs
adpentest --cve-report

# Show details for a specific run
adpentest --run-details run-8824073e5124-20260904055457

# Use custom database path
adpentest --history --db-path /path/to/custom.db

HTML Pentest Report Generation

Generate an executive-ready, standalone, and interactive HTML penetration test report (<100KB):

# Generate report during active scan
adpentest --target corp.local --mode active --scope-confirmed --html-report report.html

# Generate report from an existing JSON output file
python -m adpentest.report_generator scan_results.json report.html
  • 0.0 - 10.0 Executive Risk Score with CVSS & severity metrics gauge
  • Interactive Dark / Light mode toggle & print-optimized layout
  • Target architecture & Domain Controller detection breakdown
  • Categorized security findings with remediation advice
  • Collapsible tool execution logs with timing and duration metrics

Lab Setup

# Interactive lab setup orchestrator
adpentest --setup-labs

Output Format

All scan output is JSON:

{
  "status": "completed",
  "run_id": "run-abc123-20260901120000",
  "db_path": "~/.adpentest/scan_history.db",
  "dc_detection": {
    "dc_count": 2,
    "detected_domain": "corp.local",
    "domain_controllers": [...]
  },
  "execution": {
    "result_count": 35,
    "completed": 28,
    "failed": 7
  }
}

See examples/sample-dry-run-output.json for a complete example.


CVE Scanners

The framework includes 7 built-in CVE scanners that run as part of every scan. All scanners are safe and read-only — they use port probes, anonymous LDAP queries, and raw protocol checks only.

CVE Name CVSS Description
CVE-2026-59270 Spring LDAP 9.4 Hardcoded credentials in Spring Security embedded LDAP (UnboundIdContainer)
CVE-2026-54121 Certighost 8.8 AD CS enrollment bypass — certificate enrollment for arbitrary computer accounts
CVE-2025-54918 NTLM LDAP Bypass 8.1 NTLM authentication bypass on DC LDAP — privilege escalation to SYSTEM
CVE-2026-33826 AD RPC RCE 8.0 Windows AD RPC remote code execution via improper input validation
CVE-2026-27912 ResetNightmare 8.0 Kerberos kpasswd password reset bypass via UPN collision — full domain takeover
CVE-2026-24294 NTLM Reflection 7.8 NTLM reflection via SMB port multiplexing (Server 2025 / Win 11 24H2)
CVE-2026-20833 Kerberos RC4 7.5 KDC accepts RC4-HMAC encryption — enables Kerberoasting attacks

What Each Scanner Checks

CVE-2026-59270 — Attempts LDAP bind with known hardcoded credentials (uid=admin,ou=system / secret) on ports 389, 636, 53389, 33389, 10389, 8389. Reports exposed entry count.

CVE-2026-54121 — Queries AD CS Enrollment Services and certificate templates via LDAP. Identifies templates with ENROLLEE_SUPPLIES_SUBJECT flag or risky enrollment configurations.

CVE-2025-54918 — Checks if LDAP accepts NTLM/GSS-SPNEGO authentication without enforced signing. Extracts DC functional level and domain context.

CVE-2026-33826 — Probes RPC endpoint mapper (port 135), confirms AD DC via LDAP, checks for exposed RPC-related ports (135, 593, 445, 139).

CVE-2026-27912 — Checks if kpasswd (port 464) and Kerberos (port 88) are open. Queries ms-DS-MachineAccountQuota to assess exploitation feasibility.

CVE-2026-24294 — Sends SMB2 Negotiate to detect protocol version and signing mode. Checks for alternative SMB ports (8445, 9445, etc.) indicating port multiplexing.

CVE-2026-20833 — Sends raw Kerberos AS-REQ with RC4 (etype 23), AES256 (etype 18), and AES128 (etype 17) to detect which encryption types the KDC accepts.


WAF Detection & Bypass

When scanning targets behind WAF/CDN services, the framework automatically:

  1. Detects WAF vendor — checks HTTP headers and body content for signatures of 17+ WAF vendors (Incapsula/Imperva, Cloudflare, Akamai, AWS WAF, Azure Front Door, Sucuri, etc.)
  2. Attempts bypass via 5 technique layers:
    • HTTP bypass — header spoofing (X-Forwarded-For, X-Real-IP, CF-Connecting-IP), User-Agent rotation, path obfuscation, verb tampering
    • Raw LDAP — BER-encoded LDAPv3 anonymous bind directly to port 389
    • Raw Kerberos — AS-REQ with TCP framing to port 88
    • TCP fragmentation — 1 byte per TCP segment with TCP_NODELAY
    • Email/HTTP — OWA, EWS NTLM handshake, Autodiscover, ActiveSync, MAPI probing

If raw LDAP or Kerberos bypasses the WAF, the framework extracts domain info and adjusts DC detection confidence accordingly.


Scan History Database

All scan data is automatically stored in SQLite at ~/.adpentest/scan_history.db.

Database Schema

scan_runs — One row per scan execution:

  • run_id, target, mode, started_at, finished_at, status
  • dc_count, live_hosts, tools_executed, tools_succeeded, tools_failed
  • cves_checked, cves_vulnerable

tool_results — One row per tool execution:

  • tool, host, is_dc, fqdn, status, duration_sec, output, error

cve_findings — One row per CVE check:

  • cve_id, target, cvss, severity, vulnerable, impact, details_json

Querying Directly

# Open the database
sqlite3 ~/.adpentest/scan_history.db

# All vulnerable findings
SELECT cve_id, target, cvss, severity, impact FROM cve_findings WHERE vulnerable=1 ORDER BY cvss DESC;

# Scan history summary
SELECT run_id, target, mode, status, tools_executed, cves_vulnerable, started_at FROM scan_runs ORDER BY started_at DESC;

# Tool success rate
SELECT tool, COUNT(*) as runs, SUM(CASE WHEN status='completed' THEN 1 ELSE 0 END) as ok FROM tool_results GROUP BY tool ORDER BY runs DESC;

DC Detection Strategies

The framework uses a multi-strategy pipeline to discover Domain Controllers:

Strategy Method Confidence
DNS SRV Queries _ldap._tcp.dc._msdcs.<domain> High (0.9)
LDAP RootDSE Anonymous bind to extract domain/forest info High (0.9)
Port fingerprint Checks Kerberos (88), LDAP (389/636), GC (3268/3269) Medium (0.7)
Subnet sweep Kerberos port 88 scan on /24 → /23 → /22 Medium (0.6)

When WAF is detected blocking ports, the bypass engine runs automatically. If raw LDAP/Kerberos bypasses succeed, confidence is adjusted to 0.7 ("waf-bypassed"); otherwise 0.1 ("waf-blocked").


Tool Registry

Available Tools (35+)

Binary tools: nmap, masscan, enum4linux-ng, rpcdump, smbclient, bloodhound-python, certipy, ldapdomaindump, kerbrute, crackmapexec, smbmap, impacket (secretsdump, psexec)

Windows-native: powershell_ldap_enum, powershell_smb_enum, powershell_ad_recon

Kerberos: GetUserSPNs, AS_REP_roast, kerberoast

ADCS: certipy_shadow, certipy_esc1, certipy_esc3, certipy_esc9

Email: smtp_enum, smtp_auth_test, pop3_auth_test, imap_auth_test, email_server_discovery

Exploitation: ntlm_null_session, auto_privesc, golden_ticket, silver_ticket, delegation_abuse, trust_enumeration, trust_abuse, petitpotam, printerbug, ntlm_relay, acl_scanner, acl_exploit, gpo_abuse, delegation_chain, sid_history, dsrm_backdoor, dcshadow, golden_gmsa, skeleton_key

CVE scanners: cve_2026_59270, cve_2026_54121, cve_2025_54918, cve_2026_33826, cve_2026_27912, cve_2026_24294, cve_2026_20833


Email Protocol Enumeration

Pure Python email enumeration using standard library (no external dependencies):

  • SMTP VRFY — discover valid usernames via VRFY command
  • SMTP RCPT TO — validate recipients via RCPT TO
  • Credential testing — automatic fallback chain: SMTP → POP3 → IMAP
  • Exchange detection — OWA, EWS NTLM handshake (extracts domain/DC/forest from NTLM challenge), Autodiscover, ActiveSync, MAPI
  • Parallel testing — 32 concurrent workers for credential testing

Ports scanned: 25, 465, 587 (SMTP), 110, 995 (POP3), 143, 993 (IMAP).


DNS Configuration

Priority Order

  1. CLI arguments (--dns-server, --dns-timeout) — highest priority
  2. Environment variables (DNS_SERVERS, DNS_TIMEOUT)
  3. System default DNS — auto-detected
  4. Public DNS fallback — Google (8.8.8.8, 8.8.4.4), Cloudflare (1.1.1.1, 1.0.0.1)

An explicit CLI or environment server list replaces system/public resolvers; errors do not fall back to another resolver. The single-host diagnostic route uses --dns-server="IP1,IP2" (also repeatable) or system DNS when omitted, without public fallback. Its --dns-timeout bounds the entire target lookup.

# CLI
adpentest --target corp.local --mode active --scope-confirmed --dns-server 192.168.1.1,8.8.8.8 --dns-timeout 5.0

# Environment
export DNS_SERVERS=192.168.1.1,1.1.1.1
export DNS_TIMEOUT=5.0
adpentest --target corp.local --mode active --scope-confirmed

Architecture

Single-File Design

All framework logic is in adpentest/core.py. This monolithic approach provides clear dependency flow, centralized tool registry, unified error handling, and easy deployment.

Execution Pipeline

Input: --target 10.0.0.1 --mode active --scope-confirmed
  │
  ├── Scope validation (dry-run vs active)
  ├── Tool discovery (scan $PATH)
  ├── SQLite run initialization
  │
  ├── DC Detection (multi-strategy)
  │   ├── DNS SRV queries
  │   ├── LDAP RootDSE probe
  │   ├── Port fingerprint (+ WAF detect/bypass)
  │   └── Subnet sweep (/24 → /23 → /22)
  │
  ├── Domain discovery + FQDN resolution
  ├── Email server discovery (MX + port scan)
  │
  ├── Parallel Tool Execution (ThreadPoolExecutor, 16 workers)
  │   ├── AD tools against DCs (prioritized)
  │   ├── CVE scanners against all targets
  │   └── Results → SQLite (tool_results + cve_findings)
  │
  └── Output: JSON + SQLite database

Threading Model

Pool Workers Purpose
Tool execution 16 AD diagnostic tools in parallel
Port scanning 32 Concurrent TCP port checks
DNS resolution 32 Concurrent DNS queries
Credential testing 32 SMTP/POP3/IMAP auth testing

Contributing

Contributions are welcome! See CONTRIBUTING.md for setup instructions and CODE_OF_CONDUCT.md for community guidelines.

Check the open issues for tasks labeled good-first-issue or help-wanted.

Adding a New CVE Scanner

  1. Add scanner function scan_cve_YYYY_NNNNN(target, timeout) returning a dict with cve, cvss, severity, vulnerable, impact, remediation
  2. Add tool name cve_YYYY_NNNNN_short_name to AD_TOOLS set
  3. Add to PIP_PACKAGES (empty list for pure Python)
  4. Add to EXECUTABLES (python3/python/python.exe)
  5. Add build_ad_command handler

Adding a New Tool

  1. Add tool name to AD_TOOLS set
  2. Add package mapping to PIP_PACKAGES/APT_PACKAGES/WINGET_PACKAGES
  3. Add executable names to EXECUTABLES dict
  4. Implement command building in build_ad_command()

License

MIT


Disclaimer: This tool is designed for authorized penetration testing and security research only. Users are responsible for obtaining proper authorization before testing any systems. The authors assume no liability for misuse.

Metadata

Release files for adpentest 2.14.213.78.21.13

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for adpentest 2.14.213.78.21.13
File Size Uploaded
adpentest-2.14.213.78.21.13.tar.gz 389.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for adpentest 2.14.213.78.21.13
File Interpreter ABI Platform
adpentest-2.14.213.78.21.13-py3-none-any.whl Python 3 none any Details

Total release size: 602.2 kB

Release files / adpentest-2.14.213.78.21.13.tar.gz

Download URL adpentest-2.14.213.78.21.13.tar.gz
Size 389.9 kB
Tags Source
SHA-256 checksum
How to use checksums
04619b0c9633bb397f8bf62c12a7aa1c9194205fcc2a1e3da6d846191a965c2e
BLAKE2b-256 checksum
How to use checksums
e2cac600814ab4efa19272507bd9e3b6cacc28a3c3a2e0fe89da81ec9eda44d6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / adpentest-2.14.213.78.21.13-py3-none-any.whl

Download URL adpentest-2.14.213.78.21.13-py3-none-any.whl
Size 212.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
19be95ba8a721d69ff90b3829eac95e5eecc3c823a7f1b6ba88eaf24da12b020
BLAKE2b-256 checksum
How to use checksums
3380c57eaec0669810cc6a541d9e02e94c9d2b3dbe9a12907e4619a97fec895d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

3.0.0

2 release files

2.26

2 release files

2.25

2 release files

2.23.0

2 release files

2.22

2 release files

2.20

2 release files

2.15.1

2 release files

2.15.0

2 release files

This release

2.14.213.78.21.13 This release

2 release files

2.14

2 release files

2.0.4

2 release files

2.0.3

2 release files

2.0.1

2 release files

1.7.1

2 release files

1.6.2

2 release files

1.6.1

2 release files

1.6.0

2 release files

1.5.0

2 release files

1.4.1

2 release files

1.4.0

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.2.4

2 release files

1.2.3

2 release files

1.2.2

2 release files

1.2.1

2 release files

1.2.0

2 release files

1.1.5

2 release files

1.1.3

2 release files

1.1.2

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page