Skip to content
ADscan Docs

🔍 Scanning Commands

Unauthenticated and authenticated Active Directory scanning commands

Authorization Required

Only scan systems you have explicit written authorization to test. Unauthorized network scanning and access is illegal and may result in criminal prosecution.

ADscan provides scanning commands for both unauthenticated and authenticated Active Directory enumeration.

Configuration Commands

Before starting a scan, configure these essential parameters:

set iface

Set the network interface for scanning.

Syntax:

set iface <interface_name>

Examples:

# Ethernet
(ADscan:workspace) > set iface eth0

# VPN (common for CTFs)
(ADscan:workspace) > set iface tun0

# WiFi
(ADscan:workspace) > set iface wlan0

Finding your interface:

ip addr show

set hosts

Set target IP range for unauthenticated scans (discovery mode).

Syntax:

set hosts <cidr_range|ip_address>

Examples:

# Single host
(ADscan:workspace) > set hosts 10.10.10.161

# CIDR range
(ADscan:workspace) > set hosts 192.168.1.0/24

# Large subnet
(ADscan:workspace) > set hosts 10.0.0.0/16

set auto

Configure automation level.

Syntax:

set auto <True|False>

Examples:

# Semi-automatic mode (recommended for production)
(ADscan:workspace) > set auto False

# Automatic mode (faster for labs/CTFs)
(ADscan:workspace) > set auto True

Modes:

  • auto=False: Prompts before each potentially noisy or disruptive action (maximum operator control)
  • auto=True: Automatically runs low‑risk steps while still prompting before noisy, disruptive, or high‑impact actions

Production Warning

Use auto=False in production or client environments. Automatic mode (auto=True) is designed for labs/CTFs: it accelerates safe enumeration, but high‑impact operations still require explicit confirmation. Semi‑automatic mode keeps you in the loop for more decision points, which better matches strict rules of engagement.

set telemetry

Enable or disable telemetry reporting.

Syntax:

set telemetry <on|off>

Examples:

# Enable telemetry (helps improve ADscan)
(ADscan:workspace) > set telemetry on

# Disable telemetry
(ADscan:workspace) > set telemetry off

Note: Telemetry does not include sensitive data (credentials, domain names, etc.). Only anonymized error data and feature usage.

Unauthenticated Scanning

start_unauth

Start unauthenticated Active Directory enumeration.

Syntax:

start_unauth
start_unauth [domain|dc_ip] [dc_ip]

Prerequisites:

  • Network interface configured (set iface)
  • Either:
    • Target hosts configured (set hosts) for discovery-by-range, or
    • Provide domain/DC context interactively (guided prompts), or
    • Provide domain/DC context via arguments (see examples below)

Example (HTB Forest):

Unauthenticated scan
  (ADscan:forest ~/.adscan/workspaces/forest) > set iface tun0
  (ADscan:forest ~/.adscan/workspaces/forest) > set hosts 10.129.2.124
  (ADscan:forest ~/.adscan/workspaces/forest) > start_unauth
Output - Unauthenticated Scan (Forest)
    Starting host detection on 10.129.2.124...
    Starting smb scan
   New domain found: htb.local
    Updating DNS
   DNS resolution configured correctly for htb.local
   smb scan finished.
    Checking for null sessions on SMB on the domain htb.local
   null session accepted successfully for domain htb.local.
    Creating a SMB user list
   19 Users found.
    Searching for AS-REP roastable users in domain htb.local
  ╭────────────────────────────────────────────────────────────╮
  │         Asreproastable Users in htb.local (Guest)          │
  │ ╭────────────────────────────────────────────────────────╮ │
  │ │ svc-alfresco                                           │ │
  │ ╰────────────────────────────────────────────────────────╯ │
  ╰────────────────────────────────────────────────────────────╯
    Using rockyou as the default wordlist.
   Cracking asreproast hashes. Please be patient (this may take a while)
   Kerberos TGT created successfully
    Kerberos ticket generated for [email protected]

What it does:

  1. Helps you choose the correct scan type (unauthenticated vs authenticated)
  2. Discovers Active Directory domain and domain controllers (or uses your known domain/DC)
  3. Validates the provided DC/PDC target and may suggest a better DC/PDC IP
  4. Enumerates what is accessible without credentials (SMB/LDAP/Kerberos depending on exposure)
  5. If credentials are available, recommends switching to start_auth for full coverage

Recommended usage patterns:

# If you have credentials: prefer authenticated scanning (covers unauth too)
(ADscan:workspace) > start_auth

# If you know the domain + a DC IP: skip host-range discovery and go straight to enumeration
(ADscan:workspace) > start_unauth corp.local 10.10.10.1

# If you know only the domain (and DNS is already working): ADscan can try SRV discovery
(ADscan:workspace) > start_unauth corp.local

# If you know only a DC IP: ADscan can try PTR first, then SMB fingerprinting as fallback
(ADscan:workspace) > start_unauth 10.10.10.1

Re-running only Kerberos user enumeration:

If you want to keep iterating on username discovery after start_unauth, you do not need to rerun the full unauthenticated scan.

Use:

kerberos_enum_users <domain>

ADscan now supports three focused Kerberos username-enumeration paths:

  • Focused corporate wordlists: choose a known username format and generate candidates from statistically-likely corp patterns, known names, and in audit workspaces optionally LinkedIn employee discovery.
  • General common username wordlist: a built-in fallback when the username format is unknown.
  • Custom username wordlist: import a wordlist from your host and retry paths interactively if the file path is wrong.

Success criteria:

  • Domain discovered
  • User accounts enumerated
  • Potential attack paths identified

Authenticated Scanning

start_auth

Start authenticated Active Directory enumeration with credentials.

Syntax:

start_auth
start_auth <domain> <dc_ip> <username> <password|hash>

Guided mode (recommended):

  • Run start_auth with no arguments to follow an interactive wizard:
    • Enter credentials (username + password/hash)
    • Credential input is visible so you can verify what you typed before confirming
    • Provide whatever target context you know (domain, DC IP, or DC hostname)
    • ADscan validates the DC/PDC target and may suggest switching to the discovered PDC

Parameters:

  • domain: Domain name (e.g., corp.local, htb.local)
  • dc_ip: Primary Domain Controller IP address
  • username: Domain username (without DOMAIN\ prefix)
  • password: Cleartext password or NTLM hash

Examples:

Guided mode:

(ADscan:workspace) > start_auth

With password:

(ADscan:workspace) > start_auth corp.local 10.10.10.1 jdoe MyP@ssw0rd!

With NTLM hash (pass-the-hash):

(ADscan:workspace) > start_auth corp.local 10.10.10.1 administrator aad3b435b51404eeaad3b435b51404ee:8846f7eaee8fb117ad06bdd830b7586c

What it does:

  1. Verifies credentials against domain controller
  2. Enumerates all domain users, groups, and computers
  3. Collects BloodHound data automatically
  4. Detects escalation opportunities and records them as attack steps
  5. Computes attack paths from your current/owned users to high‑value targets
  6. Maps SMB share exposure: captures NTLMv2 hashes on writable shares (drops SCF/LNK bait for a privileged user to browse) and hunts readable shares for embedded credentials
  7. Prompts you to review and (optionally) execute supported attack paths

To revisit paths later (or after adding new credentials), use:

attack_steps <domain>
attack_paths <domain> owned

Example output (Forest, after AS-REP roasting):

Output - Authenticated Enumeration (Forest)
  Do you want to enumerate privileges for user svc-alfresco? [y/n] (y): y
  Do you want to enumerate privileges for user svc-alfresco on various services on hosts?
  (⚠ WARNING: This will saturate the network if the number of hosts in domain htb.local is very high) [y/n]: y
    Starting smb privilege enumeration for user svc-alfresco
   smb enumeration completed for user svc-alfresco. No hosts with privileges found.
    Starting winrm privilege enumeration for user svc-alfresco
   User svc-alfresco has winrm privileges on host 10.129.95.210
  Do you want to enumerate host 10.129.95.210 via WinRM as user svc-alfresco? [y/n]: y
    Searching for Firefox files for user svc-alfresco
   No Firefox credential files found for user svc-alfresco
    Obtaining PowerShell history for user svc-alfresco
   No PowerShell history found for the user.
    Obtaining autologon credentials
   No autologon credentials found in the output.

Domain Collection (Phase 2)

After authentication succeeds, start_auth runs Domain Collection — the phase that builds the attack graph. It collects two distinct layers:

  • The LDAP layer (always): the directory graph, ACLs, group memberships, and ADCS/PKI objects. This is the mandatory base — it produces the graph and the list of computers everything else builds on.
  • The SMB layer (optional): per-host data that requires touching each computer over the network — logged-on sessions and local administrators, plus accessible shares and their permissions.

Choosing what to collect

At the start of Domain Collection, ADscan asks which sub-collections to run:

? Domain Collection — select sub-collections for corp.local
  [x] LDAP graph, ACLs, memberships & ADCS/PKI
  [x] SMB: sessions & local admins (SAMR)
  [x] SMB: shares & share ACLs (SRVSVC)
  • The LDAP item is always collected (it is the base graph) and is shown checked for visibility.
  • The two SMB items are independent — keep both, keep one, or deselect both.
  • Deselecting both SMB items turns Domain Collection into a fast, quiet LDAP-only pass: ADscan skips the per-host network phase entirely. This is ideal for a first, low-noise look at a large estate, or when you only need the graph/ACL/ADCS view.
  • The default is everything selected, so leaving the prompt untouched (or running non-interactively, e.g. in CI) collects all three layers — no change from previous behavior.

Why a fast LDAP-only pass

On very large or tightly segmented networks, the SMB layer is the slow part — it has to reach every computer. Running LDAP-only first gives you the full graph, ACLs, and certificate-services view in seconds, then you can re-run later with the SMB layers enabled once you have narrowed the scope.

Reachability gate on the SMB layer

When the SMB layer is enabled, ADscan does not blindly try to reach every computer in the directory. Before the expensive per-host collection, it runs a fast reachability probe and only collects from hosts that actually answer on the SMB port:

  • Unreachable hosts are skipped, not retried until timeout. On large estates (thousands of computers, restricted subnets, stale machine accounts) this is the difference between finishing in minutes and stalling for an hour on hosts that will never respond. Skipped hosts stay in the graph — they simply get no SMB data.
  • Disabled computer accounts are excluded from the SMB layer entirely (a disabled account cannot authenticate, so probing it is pure waste).

You will see a short reachability summary (how many hosts answered) before the per-host phase begins. The gate fails open: if the probe itself errors, ADscan falls back to collecting all hosts so coverage is never silently reduced.

Tuning (optional — defaults are sensible for most networks):

# How many hosts to probe in parallel (default 256)
export ADSCAN_COLLECTOR_GATE_CONCURRENCY=256

# Per-host connect-probe budget in seconds (default 5.0; raise for high-latency VPNs)
export ADSCAN_COLLECTOR_GATE_TIMEOUT=5.0

Active host cap (time-bound scanning on large estates)

On a large estate (a few thousand computers), the reachability and port scan still run on every host — that part is cheap and gives you a complete reachability and open-port inventory for the report. What you can bound is the active layer that follows: the per-host SMB collection and the SMB / WinRM / MSSQL privilege sweeps.

The host_cap scan-config field limits that active set to a fixed number of hosts, chosen highest-value first (Tier 0 — domain controllers and certificate authorities — then member servers, then workstations). The cap is a single union, so the total active footprint is host_cap hosts across all services, not per service. The directory graph is never capped, and you always see a clear message when the cap applies — it is never silent.

  • Default 150 — roughly one /24 worth of the most important hosts, enough for a representative pilot on a multi-thousand-host network.
  • 0 = unlimited — every reachable host is collected and swept (the full sweep).

Set it in the scan config (adscan ci and the Enterprise scan form expose a "Host cap (0 = unlimited)" field), or override per run:

# Cap the active sweep to the top 150 hosts (representative-first)
export ADSCAN_COLLECTOR_HOST_CAP=150

# Full sweep — collect and sweep every reachable host
export ADSCAN_COLLECTOR_HOST_CAP=0

NTLMv1 / NTLMv2 detection per host

During Domain Collection, ADscan classifies how each reachable host negotiates NTLM authentication and flags NTLMv1 — a downgrade misconfiguration whose captured responses can be cracked to the account's NT hash via rainbow tables. Previously this signal was only observed on the domain controller; it is now evaluated per host.

The scope is gated by engagement type to respect rules of engagement:

  • CTF workspaces: ADscan sweeps all reachable hosts automatically.
  • Audit workspaces: ADscan stays DC-only by default (the quiet, low-footprint choice). You can opt in to a full per-host sweep when prompted — ADscan shows an OPSEC heads-up first, because coercing each host to authenticate back can be flagged by Defender for Identity, MDI, or SOC network detection.

OPSEC — full NTLM sweep in audit mode

The DC-only NTLMv1 check is always safe to run and is reportable on its own. The opt-in full sweep generates additional authentication traffic from every host and is more likely to be noticed. Only enable it when your rules of engagement allow it.

Tuning (optional):

# Concurrent hosts in the full per-host sweep (default 8 — kept low for OPSEC)
export ADSCAN_NTLM_SWEEP_CONCURRENCY=8

# Overall wall-clock budget for the whole sweep, in seconds (default 1800)
export ADSCAN_NTLM_SWEEP_BUDGET_SECONDS=1800

Long-Running Operations — Live Progress & Patience Notices

Several scan steps can take a while on real networks — per-host SMB collection, Kerberos user enumeration, password spraying, the port scan, and the share credential hunt. ADscan makes long operations legible so you never wonder whether the tool has hung:

  • Upfront patience notice. Before a large run starts, ADscan tells you roughly how long to expect (scaled to the number of hosts/users involved — from "a few seconds" up to "ten minutes or more — grab a coffee"). Small runs stay silent, so the output stays clean.
  • Live progress surface. While the operation runs, a live dashboard shows progress — a count with throughput and ETA where the total is known, or a working spinner where it is not — so you can see it is actively making progress.

The patience-notice threshold is per operation and can be overridden (the value is the item count above which the upfront notice appears):

export ADSCAN_PATIENCE_THRESHOLD_SMB_COLLECTION=...   # per-host SMB collection
export ADSCAN_PATIENCE_THRESHOLD_USERENUM=...         # Kerberos user enumeration
export ADSCAN_PATIENCE_THRESHOLD_SPRAY=...            # password spraying
export ADSCAN_PATIENCE_THRESHOLD_IMPORTANT_PORT_SCAN=... # port scan

In non-interactive / CI runs the notice is collapsed to a single log line and never blocks.

Password Spraying — Lockout-Aware Coverage

The spraying phase runs in two steps and is designed to test every safe spray angle while guaranteeing no account is ever locked out. Throughout, ADscan reads the domain's lockout policy (threshold + observation window) and each account's current badPwdCount, and keeps a 2-attempt safety margin below the threshold: any account too close to the limit is held back, never sprayed. Combinations already tried in a previous run are skipped automatically (tracked per (user, password)), so re-running a scan never re-sprays covered ground or burns badPwdCount.

Who is sprayed — eligibility & exclusions

Before each spray, ADscan shows a Spray Eligibility panel with two tables — Eligible accounts (who will be sprayed, with their BadPwdCount, remaining attempts, and the lockout policy that applies) and Excluded accounts (who is held back, with the reason). Accounts are excluded for four reasons, so spraying is both safe and free of noise:

  • Already owned — any account ADscan already holds a credential for (password or hash) is dropped silently. Spraying an account you control is pointless and only adds badPwdCount. Machine accounts you already cracked are likewise dropped from the pre2k step.
  • Currently locked out — read live from the DC's msDS-User-Account-Control-Computed (the authoritative UF_LOCKOUT flag, already PSO- and auto-unlock-aware). A locked account resets its badPwdCount to 0, so it looks sprayable — ADscan excludes it (you cannot authenticate it, and spraying would extend the lockout). This is informational only: it never prompts you to confirm, and it is excluded from the coverage percentage (a locked account cannot be "covered").
  • Near the lockout threshold — within the 2-attempt margin; held back for safety and re-tried automatically once the lockout observation window resets.
  • Unreadable fine-grained policy (PSO) — when an account has a PSO assigned (msDS-ResultantPSO) but the spraying principal cannot read the Password Settings Container (the norm for low-privilege users, and exactly the privileged Tier-0 accounts you least want to lock), ADscan cannot know the PSO's real lockout threshold. Rather than assume the domain default (which a stricter PSO would over-estimate, risking a lockout), it applies a conservative threshold of 3 — with the 2-attempt margin this caps such users at a single attempt. The eligibility panel labels these clearly (e.g. PSO 'TIER0' unreadable · thr 3), and shows the real PSO name + threshold when the PSO object is readable.

Step 1 — pre2k computer-account spray

Pre-Windows-2000 computer accounts are frequently provisioned with their password equal to the hostname in lowercase. ADscan sprays that pattern across every enabled computer account. Because computer accounts are not subject to the user lockout policy, this can never lock out a domain user, so it runs first. An educational panel explains what it is, why it is safe, and what a hit means, then asks for confirmation (default yes; auto-yes in adscan ci).

Step 2 — coverage-aware spray selector

A selector then offers the user-account spray types, each with a live coverage percentage and the number of users currently eligible (within the lockout margin):

  • user-as-password — the user's own name as the password. A sub-menu picks the case mode (normal / lowercase / uppercase); one mode marks the type covered.
  • owned-credential reuse — appears once a cleartext credential has been recovered; sprays it across the domain to surface password reuse. A sub-menu selects which owned credential(s) to use.
  • blank password — accounts with an empty password.

Two interactive-only extras are also offered when relevant: custom password (spray a password you type) and retry passwords found in shares / SAM → domain reuse.

Interactive (adscan start). You pick a spray from the selector; it re-appears after each run so you stay in full control and can run as many as you like (or pick Done). When no users remain eligible (everyone locked, near lockout, or owned), ADscan finishes the phase automatically instead of re-prompting an empty selector. The "some accounts were held back — continue?" confirmation only appears for genuine safety hold-backs (near lockout), never for locked accounts.

Non-interactive (adscan ci). ADscan auto-selects intelligently: it walks the priority order (user-as-password → owned-credential reuse → blank), skips any type already fully covered or with zero eligible users, and finishes the phase once none remain. The case mode defaults to lowercase; owned-credential reuse sprays all held credentials. This is deterministic and cannot loop.

Manual commands

Inside the interactive shell you can run the same flow on demand:

# Coverage-aware spray selector for a domain (the Step-2 flow above).
(ADscan:workspace) > spraying <domain>

# The pre2k computer-account check on its own (Step 1).
(ADscan:workspace) > pre2k <domain>

Both default to the current domain. pre2k is deduped per workspace — once run, it is not silently repeated on a later re-entry.

Notes:

  • When the domain lockout threshold is 0 (lockout disabled), every account is sprayable and nothing is held back.
  • Coverage and eligibility are recomputed from live policy data on every selector pass, so a credential recovered mid-phase immediately unlocks owned-credential reuse, and a re-run after the observation window picks up previously-held users.

Scan Types

Network Discovery

Identify Active Directory infrastructure:

(ADscan:workspace) > set hosts 192.168.1.0/24
(ADscan:workspace) > start_unauth

Discovers:

  • Domain controllers
  • Domain DNS name
  • Domain functional level

User Enumeration

List all domain user accounts:

Unauthenticated:

start_unauth
# Uses anonymous RPC/LDAP if allowed

Authenticated:

start_auth domain.local 10.10.10.1 user pass
# Full user enumeration with attributes

Privilege Escalation

Identify paths to Domain Admin:

# Run authenticated scan
start_auth domain.local 10.10.10.1 lowpriv_user password

# ADscan automatically:
# - Checks for Kerberoasting opportunities
# - Identifies AS-REP roastable accounts (within domain)
# - Builds attack steps and analyzes BloodHound paths
# - Suggests attack paths for operator review

Best Practices

Reconnaissance

Start with unauthenticated scanning:

# 1. Discover the domain
set hosts 10.10.10.0/24
start_unauth

# 2. If credentials found, escalate
start_auth domain.local 10.10.10.1 found_user found_password

Production Environments

Use semi-automatic mode for control:

set auto False
# You'll be prompted before potentially noisy operations and most key decisions

Lab/CTF Environments

Use automatic mode for speed:

set auto True
# Faster enumeration with minimal prompts (still confirms high-impact actions)

Credential Management

ADscan automatically saves discovered credentials inside the workspace state:

# Workspace state (including credentials) is stored in:
~/.adscan/workspaces/<workspace>/variables.json

# Use discovered credentials in future scans
start_auth domain.local 10.10.10.1 stored_user stored_password

Scan Output

All scan results are saved in the workspace:

~/.adscan/workspaces/<workspace>/
├── users.txt              # All enumerated users
├── computers.txt          # All enumerated computers
├── groups.txt             # All groups
├── bloodhound/            # BloodHound JSON files
├── kerberoast/            # Kerberoastable hashes
├── asrep/                 # AS-REP roastable hashes
└── shares/                # Accessible SMB shares

Troubleshooting

"Network interface not found"

 Interface 'tun0' not found

Solution: Check available interfaces:

ip addr show

"Domain not found"

 No Active Directory domain found in range

Solutions:

  • Verify target IP range is correct
  • Ensure network connectivity to domain controllers
  • Check firewall rules (ports 88, 389, 445)

"Credentials invalid"

 Authentication failed for user 'jdoe'

Solutions:

  • Verify username and password are correct
  • Check if account is locked or disabled
  • Ensure domain name is correct
  • Try NTLM hash instead of password

"Permission denied"

 Insufficient privileges for operation

Solutions:

  • Use higher-privileged account
  • Check if operation requires Domain Admin rights
  • Review BloodHound for privilege escalation paths

Advanced Usage

Custom Wordlists

Use custom wordlist for password cracking:

# ADscan prompts for wordlist selection during cracking
? Select wordlist:
  > rockyou.txt (default)
    custom_ad_wordlist.txt
    company_passwords.txt

Targeted Scanning

Scan specific domain controller:

set hosts 10.10.10.1
start_unauth

Multi-Domain Environments

Scan multiple domains (requires separate workspaces):

# Domain 1
workspace create domain1
start_auth domain1.local 10.10.10.1 user pass

# Domain 2
workspace create domain2
start_auth domain2.local 10.20.10.1 user pass

Service-Access Sweep Backends

When ADscan probes which hosts a credential can reach over SMB, WinRM, RDP, and MSSQL, it now uses its native async stack by default instead of shelling out to an external scanner:

  • SMB — native ADMIN$/C$ connection check (confirms local administrator access, the same signal a Pwn3d! line used to convey). Honors NTLM, Kerberos, SMB signing, AES-only KDCs, and cross-domain credentials automatically.
  • MSSQL — native in-process SQL login. A successful login confirms access; if the login is sysadmin, that is surfaced and recorded as administrative access.
  • WinRM / RDP — already native (PSRP and the native RDP probe).

The native backends are posture-aware (they adapt to detected hardening such as NTLM-disabled or channel-binding-required) and run with bounded concurrency so they scale safely across large host sets.

Tuning and fallback:

# Concurrency (workers) per native sweep — clamped to 1-128, default 30
export ADSCAN_SMB_PROBE_WORKERS=30
export ADSCAN_MSSQL_PROBE_WORKERS=30

# Temporarily fall back to the legacy external-scanner backend for one
# service (kept one release behind for parity verification). Default is "native".
export ADSCAN_SMB_PRIVS_BACKEND=netexec
export ADSCAN_MSSQL_PRIVS_BACKEND=netexec

Leave the backend variables unset (or native) for the recommended path. The legacy backend will be removed in a future release.

Next Steps

After completing a scan:

  1. View discovered credentials with creds show
  2. Select credentials for further enumeration with creds select <domain>
  3. Review and execute attack paths with attack_paths <domain> owned
  4. Inspect detected steps with attack_steps <domain>
  5. Analyze BloodHound data through the BloodHound UI (optional)
Share with your team lead
Forward a clean demo link to a lead who can approve a free team demo.
Find this useful?
Pass it to the next pentester running an AD engagement
Running 2+ AD engagements/year?
Get PRO free — beta access·Free in exchange for feedback
Automated PDF reports. Save ≥1 day per engagement.

ADscan — AD pentest automation for security consultants

🔍 Scanning Commands | ADscan