Impacket Deep Dive Part 10: Defense in Depth and Detection

This series opened with a promise: every offensive post would carry its own defensive notes, not as an afterthought but as the actual point. This closing post collects all of it into one reference, adds the pieces that only make sense at the whole-series level, and closes the loop with the network-layer controls — Fortinet’s Security Fabric, segmentation, and ZTNA — that matter once the assumption “the domain itself might already be compromised” is taken seriously, which after Part 9’s full chain, it should be.

The consolidated hardening checklist

Authentication protocol hardening. Enforce SMB signing domain-wide via GPO (Microsoft network server: Digitally sign communications (always)) rather than waiting on the Windows 11 24H2 / Server 2025 default rollout — Part 5. Enable LDAP signing (Require signing) and, separately, LDAP channel binding (Always) — the two settings are independent and both matter, per Microsoft’s ADV190023 — Part 5. Enable Extended Protection for Authentication on any ADCS web enrollment endpoint — Part 5.

Kerberos hygiene. Confirm zero accounts carry DONT_REQ_PREAUTH outside a specific, documented, reviewed exception list — Part 3. Migrate every service account with a registered SPN to a Group Managed Service Account — Part 4, and this series’ single highest-leverage fix per Part 9. Force AES-only Kerberos encryption domain-wide, retiring RC4 — Part 4. Rotate krbtgt’s password twice, several hours apart, on a recurring schedule and immediately after any suspected compromise — Part 8.

Privilege and permission audits. Review DCSync rights (Replicating Directory Changes / Replicating Directory Changes All) against a strict allowlist of Domain Admins, Enterprise Admins, and domain controllers, on a recurring schedule, not just at domain creation — Part 7. Treat Backup Operators membership changes with Domain Admin-equivalent change control — Part 7 and Part 9. Restrict null-session/anonymous SAMR access via RestrictAnonymous, understanding it only closes the unauthenticated half of the recon surface — Part 2.

Coercion and lateral movement. Disable the Print Spooler service on every domain controller. Restrict EFSRPC reachability from standard workstations. Enforce network segmentation and a tiered administration model that blocks workstation-to-workstation and workstation-to-server lateral movement paths with no legitimate business justification — Part 5 and Part 6.

The event ID reference

Event IDLogSignal
4625SecurityFailed logon — largely irrelevant to Parts 2–3’s recon since neither generates one, worth knowing for what it won’t show
4662Security (DS Access)Broad object-level LDAP reads (Part 2, tuned); DCSync signature via replication GUIDs (Part 7)
4768SecurityTGT requested — pre-auth type and result code distinguish normal logons from AS-REP roasting attempts (Part 3)
4769SecurityService ticket requested — high fan-out of distinct SPNs from one principal is the Kerberoasting signature (Part 4)
4771SecurityKerberos pre-authentication failure — pairs with 4768 for roasting detection (Part 3)
4624 (type 3)SecurityNetwork logon — cross-host session correlation is the NTLM relay signature (Part 5)
7045 / 7036SystemService installed / entered running state — psexec.py (persistent, obvious) and smbexec.py (paired burst, self-deleting) both fire this (Part 6)
4698SecurityScheduled task created — atexec.py’s signature, short random task names (Part 6)
WMI-Activity/OperationalApplications and Services LogsNot collected by default in most estates — the actual lever against wmiexec.py specifically (Part 6)

None of these are individually sufficient. The through-line across every “defensive notes” section in this series has been the same: detect the pattern, not the primitive. A single 4769 is nothing. A hundred of them in ninety seconds, against every SPN in the domain, from one account that’s never done this before, is Kerberoasting. A single 4698 is routine task-scheduler noise. One with a six-character random name, created and deleted inside three seconds, from a source that isn’t a management server, is atexec.py. The tools in this series are all living-off-the-land by design — they use real protocols, real APIs, real management interfaces — so the actual detection surface was never going to be “block this bad executable.” It’s behavioral, every time.

Where network-layer controls fit when the domain itself might already be compromised

Everything above assumes AD-native controls: GPO settings, permission audits, Windows event logs. It’s worth being honest about their limit — every one of them depends on the domain controller itself being trustworthy, and Part 9’s full chain ends with an attacker holding krbtgt’s key, at which point that assumption is exactly what’s been broken. This is where this series connects back to the rest of what this site actually covers day to day: SD-WAN and firewall architecture.

The Zero Trust / SD-WAN convergence post makes the case that used to sound theoretical and increasingly doesn’t: identity-based, per-application access control, verified continuously rather than granted once at the network perimeter, means that even a forged Golden Ticket only gets an attacker as far as the specific applications that identity’s ZTNA policy allows — not blanket network reachability. A segmented estate, with FortiGate security fabric policies actually enforcing east-west restrictions between the workstation, server, and DC segments this series’ lab implies, turns Part 9’s Stage 4 lateral-movement step from “one wmiexec.py call away” into “blocked at the firewall, logged, and alertable” regardless of whether the Windows-side detection in this post ever fires. And FortiAnalyzer-driven SLA and log observability, while built for a completely different operational purpose, is the same underlying idea as the WMI-Activity log recommendation above: the data needed to catch this exists only if something is actually collecting and correlating it, and neither a firewall nor a domain controller does that automatically just by being present on the network.

None of that makes AD-native hardening optional — a firewall policy is not a substitute for rotating krbtgt — but it’s the layer that still matters on the day AD-native hardening has already failed somewhere, which, per the Red Canary and CrowdStrike research cited across this series, it demonstrably does, constantly, in real environments.

Where this leaves the “LLM with these tools” question

This series never wired an agent into any of these scripts the way AI Part 7 and Part 8 did with Nmap and Metasploit — deliberately, since the point here was the protocols and the Windows trust model, not agentic tool-calling. But it’s worth closing on the honest connection between the two series: everything in Parts 2 through 8 above is a well-documented Python script with a stable CLI, exactly the shape of thing that’s trivial to wrap as a callable tool for an LLM. The same finding AI Part 7 landed on — that a model is not a trustworthy narrator of its own actions, and that only server-side verification against ground truth caught a smaller model fabricating a successful exploit outright — applies without modification to a hypothetical “Impacket MCP server.” An agent that can run secretsdump.py -just-dc and report back what it found needs exactly the same discipline this site applied to Metasploit: check the domain controller’s actual state, not the model’s summary of it, before trusting a single claimed result.

That’s also this series’ actual thesis, restated: every technique here targets the same thing — a trust boundary between “presents valid-looking credentials” and “is who they claim to be” — whether that boundary is Kerberos pre-authentication, an NTLM challenge-response, a DRSUAPI permission check, or an AI agent’s account of what it just did. Verify the claim against the system, not the story being told about the system, and most of what this series covers stops working.