Impacket Deep Dive Part 1: Why Real Red Teams Skip the Metasploit Tutorials

Every “getting started in penetration testing” post runs the same three tools: Nmap to find things, Hydra to brute-force a login, Metasploit to pop a shell. It’s not wrong, exactly — it’s just not what happens once the target stops being a single unpatched box and becomes a modern Windows Active Directory domain. Nobody doing that work for real is brute-forcing RDP logins. They’re not waiting on a Metasploit module for a CVE that was patched in 2019. They’re using Impacket — a Python library, originally from CORE Security and now maintained by Fortra, for constructing and parsing network protocols at a level most tooling doesn’t expose at all.

This is the first of a ten-part series that takes Impacket apart script by script: what each one actually does on the wire, why it works against protocols that have existed since Windows 2000, and — because half of this site is written for the people who have to defend these networks, not just attack them — how to detect and close each technique. No stone unturned, in the words of the brief that kicked this off.

What Impacket actually is

Impacket isn’t a scanner and it isn’t an exploit framework in the Metasploit sense. It’s a set of Python classes that implement Microsoft’s network protocols — SMB, MSRPC, Kerberos, LDAP, NTLM — faithfully enough that you can speak them programmatically instead of shelling out to a Windows binary. The examples/ directory ships several dozen ready-to-run scripts built on those classes, and those scripts are what most people mean when they say “Impacket.”

That distinction matters. wmiexec.py isn’t malware in the classic sense — there’s no payload, no dropped executable, no shellcode. It’s a working, protocol-correct implementation of “connect to WMI and ask it to run a command,” using exactly the same DCOM/WMI machinery any legitimate systems management tool uses. The entire toolkit is living off the land in the truest sense: every technique below abuses a feature, not a bug.

I confirmed the current toolkit directly rather than trusting a five-year-old blog post about it — installed the latest release in a sandbox and asked it what it is:

$ pip install impacket
$ python3 -c "from impacket import version; print(version.BANNER)"
Impacket v0.13.1 - Copyright Fortra, LLC and its affiliated companies

And the actual script inventory that ships with that version — the ones this series covers, plus the recon tools most tutorials skip past:

$ ls impacket/examples/ | grep -E '\.py$' | sort
...
GetADUsers.py       — LDAP enumeration of domain users
GetNPUsers.py       — AS-REP roasting (Part 3)
GetUserSPNs.py      — Kerberoasting (Part 4)
atexec.py           — remote exec via Task Scheduler (Part 6)
dcomexec.py         — remote exec via DCOM (Part 6)
lookupsid.py        — SID brute-forcing over SAMR (Part 2)
ntlmrelayx.py        — NTLM relay engine (Part 5)
psexec.py           — classic service-based exec (for comparison, Part 6)
rpcdump.py          — enumerate exposed RPC interfaces (Part 2)
samrdump.py         — SAM enumeration over SAMR (Part 2)
secretsdump.py      — SAM/LSA/NTDS.dit/DCSync (Part 7)
smbexec.py          — remote exec via a semi-interactive shell service (Part 6)
ticketer.py         — golden/silver ticket forging (Part 8)
wmiexec.py          — remote exec via WMI (Part 6)
...

Every command shown across this series is the actual -h output from this exact v0.13.1 install, not copied from a five-year-old cheat sheet. Where syntax has changed release to release — and it has, more than once, particularly around GetUserSPNs.py’s flag names — I’m working from what the tool says today.

Why this beats the Metasploit-tutorial approach

Three reasons, and they compound:

It’s protocol-native, not payload-based. A Metasploit module usually ships a payload — something that gets planted and executed. Impacket’s exec scripts don’t plant anything persistent; wmiexec.py runs your command through WMI’s existing Win32_Process.Create method and reads output back over the file share that already exists on every Windows box, ADMIN$. There’s no new binary for an AV signature to catch, because there’s no new binary.

It targets the trust model, not a vulnerability. Everything in this series — NTLM relay, Kerberoasting, DCSync — is a design property of Windows authentication being used the way it was designed to be used, just by someone who isn’t supposed to have the credentials they’re presenting. There’s no patch for “Kerberos service tickets are encrypted with the service account’s password hash and any authenticated user can request one.” That’s the protocol working correctly.

It’s what’s actually in incident response reports. Red Canary, Microsoft, CrowdStrike, and Splunk all publish detection content specifically for Impacket because it shows up constantly in real intrusions — ransomware crews doing lateral movement with wmiexec.py, not a custom RAT. If you’re defending a domain, the thing you need to understand is this toolkit, not a decade-old remote code execution module.

The lab this series runs against

I run FortiGates and Cisco kit on real hardware and in Proxmox for the SD-WAN and NSE content on this site, but I’m not standing up a second Active Directory domain purely for this series — no stone unturned doesn’t mean no sense of proportion. Instead, every example below is written against a documented, consistent lab topology, with command syntax and tool behavior verified against the real v0.13.1 install shown above. Treat the topology as the mental model the rest of the series assumes:

Domain: CONTOSO.LOCAL   (functional level: 2016)

DC01      10.10.30.10   Windows Server 2022, Domain Controller, holds all FSMO roles
FS01      10.10.30.20   Windows Server 2019, member server — file share + a legacy
                         service account (svc-backup) with an SPN and a weak password
WKS01     10.10.30.55   Windows 11, domain-joined workstation — the initial foothold,
                         reached the way most real intrusions start: a phished user,
                         not an exploited service

Foothold account: CONTOSO\j.reyes   — standard domain user, local admin on WKS01 only
Target account:   CONTOSO\svc-backup — has an SPN (MSSQLSvc/FS01.CONTOSO.LOCAL:1433),
                                        "Do not require Kerberos preauthentication" is
                                        unset on it but set on a second, older account,
                                        CONTOSO\svc-legacy-scan
Krbtgt:           rotated once at domain creation, never since — exactly the kind of
                   AD hygiene gap this series exists to talk about

That’s a small, realistic estate: one DC, one line-of-business server, one workstation, one phished user, and the kind of forgotten service accounts every real domain of any age accumulates. Every worked example in Parts 2 through 9 assumes this topology and refers back to it, so a technique in Part 7 makes sense in the context of what Part 3 already got out of the domain.

Where the series is going

  1. Recon without a single exploitGetADUsers.py, lookupsid.py, rpcdump.py, samrdump.py: everything you can learn from a domain before you’ve authenticated as anyone interesting.
  2. AS-REP RoastingGetNPUsers.py and the accounts that never ask “prove it” before handing out a crackable ticket.
  3. KerberoastingGetUserSPNs.py, service accounts, and why “the password doesn’t need to be weak, just weak enough to crack offline” is the whole game.
  4. NTLM relayntlmrelayx.py, the technique in the original brief for this series, and the single most consequential thing SMB signing does or doesn’t stop.
  5. The ghost shellswmiexec.py, smbexec.py, atexec.py, dcomexec.py, and exactly why one of them barely shows up in EDR telemetry and the others do.
  6. secretsdump.py — SAM, LSA secrets, NTDS.dit, and DCSync: how you go from “a foothold” to “the entire domain’s password material.”
  7. Forging ticketsticketer.py, Golden and Silver tickets, and why krbtgt is the single most under-rotated secret in most domains.
  8. The full chain — every technique above, run in the order a real intrusion actually uses them, from a phished laptop to Domain Admin.
  9. Defense in depth — the detection and hardening side of all eight prior parts, consolidated into one reference.

The brief that started this series called out ntlmrelayx.py, wmiexec.py, and GetNPUsers.py by name as the three most under-covered scripts worth writing about. They get Parts 5, 6, and 3 respectively, in the order the actual attack chain uses them rather than the order they were pitched — recon always comes before you know which of the fancier techniques is even worth running.

One last note before Part 2: every technique in this series is legal and useful in exactly one context — testing systems you own or are explicitly authorized to test, under a signed scope. The defensive halves of these posts aren’t an afterthought bolted on to justify the offensive content; they’re the actual point. Understanding how ntlmrelayx.py works is what tells you SMB signing isn’t optional, not a footnote you skip to get to the fun part.

Next up: Part 2, where CONTOSO.LOCAL gives up its entire user list, computer list, and RID space to an attacker who hasn’t authenticated as anyone yet.