🧠 Hardening Detection
How ADscan automatically detects defensive controls (NTLM disabled, AES-only Kerberos, LDAP signing, channel binding, SMB signing, LDAPS) and adapts in real time
ADscan's Hardening Detection is a posture-aware authentication layer that learns the defensive controls of every domain it touches and adapts on the fly. Instead of speculatively retrying every credential and transport combination on every operation, ADscan observes the first signal a Domain Controller emits, persists the conclusion in the workspace, and skips impossible attempts for the rest of the engagement.
The result: fewer retries, faster scans, cleaner output, and a tangible artefact for the client showing exactly which hardening controls their environment enforces.
Why this matters
Most AD pentest tooling hardcodes a "just keep trying" retry chain: NTLM first, fall back to Kerberos; LDAPS first, fall back to LDAP; password first, fall back to hash. Against a hardened environment that doesn't allow any of those, you get long timeouts, ambiguous error messages (SEC_E_LOGON_DENIED, invalidCredentials), and a scan that takes 4× longer than it should.
ADscan does the opposite. It treats the environment's behavior as evidence to be remembered, not noise to be retried through.
Controls ADscan detects
| Control | Detection signal | What ADscan changes |
|---|---|---|
| NTLM authentication disabled | DC rejects an NTLM bind with SEC_E_LOGON_DENIED after a valid Kerberos TGT, refuses the bind with SEC_E_UNSUPPORTED_FUNCTION / 0x80090302 / STATUS_NOT_SUPPORTED / STATUS_NTLM_BLOCKED, or SMB returns STATUS_LOGON_FAILURE with NTLM markers | All subsequent operations skip NTLM bind attempts |
| AES-only Kerberos / RC4 disabled | KDC returns KDC_ERR_ETYPE_NOTSUPP for RC4 | NT-hash-as-Kerberos-key paths are pruned |
| Non-default Kerberos salt | ETYPE-INFO2 advertises a non-standard AES salt | Etype probe applied automatically before every TGT request |
| LDAPS available | LDAPS bind on port 636 succeeds | LDAPS becomes the preferred transport for that domain |
| LDAPS unavailable | TLS handshake or transport failure on port 636 | LDAP plain (with signing where required) is used directly — no LDAPS attempts |
| LDAP signing required | DC returns LDAP_STRONG_AUTH_REQUIRED / strongerAuthRequired | Plain-LDAP binds force sign=true |
| LDAP channel binding required | LDAPS bind without CBT rejected | LDAPS binds enable CBT automatically |
| SMB signing required | Negotiate response advertises signing required, or bind raises a signing exception | Relay vectors flagged as not viable in the report |
Each detection has an associated confidence level (low / medium / high). Only high-confidence evidence is allowed to prune retries — low-confidence signals enrich the audit trail without changing behavior.
What you see when ADscan detects hardening
The first time a control is detected during a scan, the Intelligence Update panel appears once per (domain, control) pair:
╭─────────────────── 🧠 ADscan Intelligence Update ───────────────────╮
│ │
│ Detected security hardening on garfield.htb │
│ │
│ Constraint NTLM authentication disabled │
│ Evidence DC rejected NTLM bind with SEC_E_LOGON_DENIED while │
│ a Kerberos TGT was valid │
│ Source ldap_transport · garfield.htb │
│ Action ⚡ Switching to Kerberos-only auth for this domain │
│ │
│ This is good defensive posture — your client has hardened their │
│ domain against legacy authentication. │
│ │
│ 📌 Learned posture saved · no further retries this scan │
│ 📊 Report will appear in "Detected Defensive Posture" │
│ │
╰──────────────────────────────────────────────────────────────────────╯Three things happen at that moment:
-
The decision is persisted in the workspace at
~/.adscan/workspaces/<workspace>/domains/<domain>/<workspace_data>.jsonunderauth_posture.constraints.<category>. Any subsequent operation in the same scan reads this and skips impossible attempts. -
The scan adapts. A trust enumeration that was about to attempt LDAPS+NTLM (and would have returned
SEC_E_LOGON_DENIEDafter a 30-second timeout) now goes straight to LDAP+Kerberos. Same for the LDAP collector, the SMB share enumeration, and every other LDAP-touching operation. -
The discovery is logged for the report. When the engagement finishes, the PDF report includes a
Detected Defensive Posturesection before the findings, listing every control ADscan validated empirically against the live DC.
In the customer report
Just before the findings, the report shows:
Detected Defensive Posture
corp.local
This domain demonstrates the following defensive posture, validated empirically by ADscan during the engagement (not from configuration review):
Hardening control Status NTLM authentication ✓ Disabled Kerberos RC4 encryption ✓ Disabled LDAP channel binding ✓ Required SMB signing ✓ Required This is good defensive posture. The findings in the following sections were obtained despite this hardening, which means they represent residual risk that policy alone does not mitigate.
Detection method
ADscan validated each control empirically during the engagement. The evidence trail below is auditable — your blue/red team can replay each observation against the same DC.
- NTLM authentication: DC rejected NTLM bind with SEC_E_LOGON_DENIED while a Kerberos TGT was valid. Source: ldap_transport. Signal: NTLM_REJECTED_VIA_LDAP.
- Kerberos RC4 encryption: KDC rejected requested encryption type — domain enforces AES-only Kerberos. Source: kerberos_transport. Signal: KDC_ERR_ETYPE_NOTSUPP.
- …
This section is omitted entirely when no high-confidence hardening was detected — ADscan never fills the report with "Unknown" placeholders.
How the planner adapts
When the workspace already has high-confidence posture for a domain (from earlier in the same scan or a previous run against the same target), ADscan's LDAP authentication planner consults it and emits an ordered list of attempts to try, pruning impossible combinations.
Example: a domain with LDAPS_AVAILABLE = DISABLED (high) and NTLM_AUTHENTICATION = DISABLED (high). The conservative chain (4 attempts) is reduced to 1:
Conservative chain (no posture):
1. LDAPS + Kerberos
2. LDAPS + password (NTLM)
3. LDAP + Kerberos
4. LDAP + password (NTLM)
Posture-driven plan:
1. LDAP + KerberosWhen all viable attempts are pruned (e.g. NT hash credential against an NTLM-disabled, AES-only domain), ADscan surfaces a clear NoViableLDAPAuthError instead of running a futile bind.
Behavior in non-restrictive environments
In labs and permissive environments (NTLM enabled, RC4 allowed, no signing, no CBT), ADscan does not fabricate posture data. The workspace simply has no auth_posture.constraints block, the planner uses the conservative chain, and the report omits the Detected Defensive Posture section.
The same code path runs in GOAD, hardened customer DCs, and HTB boxes — the difference is in what the workspace remembers, not in how ADscan operates.
Re-running ADscan against the same target
The posture persists in the workspace JSON. Re-running ADscan picks up where the last scan left off:
- If the customer's GPO changed between runs (e.g. NTLM was re-enabled), the next high-confidence signal from the new run upgrades the posture; ADscan re-evaluates the planner with the updated state.
- To force a fresh probe (e.g. after a policy change you know happened), delete the
auth_postureblock from the workspace JSON or start a new workspace.
What's persisted, what's not
Persisted across scans:
auth_posture.constraints.<category>.state(likely_enabled / likely_disabled / likely_required / unknown)auth_posture.constraints.<category>.confidence(low / medium / high)auth_posture.constraints.<category>.evidence[]— the audit trail (capped at the last 20 observations per control)auth_posture.constraints.<category>.updated_at
Ephemeral (in-memory, per-scan only):
- Clock skew with the DC
- Per-credential auth retries (e.g. TGT staleness refresh)
- Network-level timeouts and reachability
See also
- Best Practices — engagement preparation, including credential and scope verification
- Troubleshooting — common authentication errors and how to interpret them
- Pro Report Outputs — full report structure including the Detected Defensive Posture section