In this sherlock, players will go through network traffic and uncover credential-stealing technique by abusing the LLMNR protocol feature in Windows. Players will learn how a victim made a typo navigating to a network share and how the attacker was using the Responder tool to steal hashes and pose as a legitimate device in the internal network. Players will also learn to crack NTLMV2 hashes by gathering information from SMB traffic.
A rogue host on Forela’s internal network ran Responder and answered LLMNR and NBNS name queries it had no right to answer. A user mistyped the name of the domain controller while opening a file share, DNS failed, and the client fell back to broadcast resolution, where the rogue host claimed the name. The client then authenticated to it over SMB, handing over an NTLMv2 challenge/response pair. The server challenge and the proof string from that exchange were enough to rebuild the hash and recover the password offline with a common wordlist. The capture also showed the share the user had actually meant to reach.
capture.pcap → tshark (Wireshark works too). Contains LLMNR, NBNS, DHCP, SMB2 and NTLMSSP trafficTimestamp note:
tsharkprints capture times in the capture’s local offset (+10:00). Q4 wants UTC, so subtract ten hours or add-t udand convert.
Truncation note:
tsharkwarns that the pcap is cut off at the end. The traffic that matters is intact, so the warning can be ignored.
Start with the name-resolution protocols Responder abuses. Filter on LLMNR and NBNS and look at who is sending the responses rather than the queries. Replies for DCC01 come back from one workstation address that is not a DNS server or domain controller, which is Responder answering for names it does not own.
tshark -r capture.pcap -Y 'llmnr || nbns' -T fields -e frame.number -e ip.src -e ip.dst -e dns.qry.name
From Q1 we have the rogue address, so pull the DHCP hostname option sent from it. It shows up twice with different values: an earlier lease (frame 1666) carries V17VT3M03 and a later one (frame 12714) carries a different name. The later lease is the most recent identity of the box, and it fits a Kali host running Responder, but nothing in the capture ties either name to the poisoner beyond the IP, so treat this one as an inference.
tshark -r capture.pcap -Y 'dhcp && ip.addr == 172.17.79.135' -T fields -e frame.number -e dhcp.option.hostname
Gotcha: Two DHCP leases from the same address give two hostnames. Check both frame numbers before settling on one.
The name the victim queried is the one Responder answered. Compare it to the real domain controller name seen in the SMB traffic: the client asked for a host with one extra letter. A name like that gets no DNS answer, so the client falls back to LLMNR and NBNS broadcasts, which is the opening the attacker used.
tshark -r capture.pcap -Y 'llmnr || nbns' -T fields -e dns.qry.name -e nbns.name | sort | uniq -c
Once the victim is steered to the rogue host, SMB session setup carries an NTLMSSP authenticate message (type 3). Extract the username field from every type 3 message sent toward the poisoner.
tshark -r capture.pcap -Y 'ntlmssp.messagetype == 0x00000003' -T fields -e frame.number -e ip.src -e ntlmssp.auth.domain -e ntlmssp.auth.username
The same user authenticates to the rogue host several times. Sort the type 3 messages from Q3 by time and take the earliest, frame 9292. tshark shows it as 21:18:30 +10:00, so convert to UTC for the answer.
tshark -r capture.pcap -Y 'ntlmssp.messagetype == 0x00000003' -T fields -e frame.number -e frame.time -e ntlmssp.auth.username
Gotcha: The displayed time is in the capture’s +10:00 offset. Submitting it as shown is ten hours off.
The challenge comes from the NTLMSSP challenge message (type 2) that the rogue server sends back just before the authenticate message from Q4. For the first exchange that is frame 9291, directly ahead of frame 9292. Match challenge to response by TCP stream, since later exchanges carry different challenges.
tshark -r capture.pcap -Y 'ntlmssp.messagetype == 0x00000002' -T fields -e frame.number -e tcp.stream -e ntlmssp.ntlmserverchallenge
Same exchange, other half. NTProofStr lives in the NTLMv2 response inside the type 3 message from frame 9292. It is the first 16 bytes of the response; the remainder of the blob is what hashcat needs as well.
tshark -r capture.pcap -Y 'frame.number == 9292' -T fields -e ntlmssp.ntlmv2_response.ntproofstr
Assemble the NetNTLMv2 line from Q3, Q6 and Q7: user::domain:challenge:NTProofStr:rest-of-blob, where the blob is the NTLMv2 response with the first 16 bytes removed. Run it through hashcat mode 5600 against rockyou.txt. It falls quickly, so the password was only as strong as a stock wordlist.
hashcat -m 5600 work/hash.txt /usr/share/dict/rockyou.txt
The victim’s intent shows up in SMB2 tree connect requests. Look for the connection to the real domain controller and read the tree path. It points at a confidential share on DC01, which is the correct spelling of the name from Q5.
tshark -r capture.pcap -Y 'smb2.cmd == 3' -T fields -e frame.number -e ip.src -e ip.dst -e smb2.tree
| Phase | Action |
|---|---|
| Credential Access | Rogue host at 172.17.79.135 listens for LLMNR and NBNS broadcasts with Responder |
| Credential Access | Victim mistypes the domain controller name; DNS fails and the client broadcasts a query for DCC01 |
| Credential Access | Rogue host answers, and the client authenticates to it over SMB |
| Credential Access | NTLMv2 challenge and response for john.deacon captured, first at frame 9292 |
| Credential Access | Hash cracked offline with hashcat mode 5600 and rockyou.txt |
| Type | Value |
|---|---|
| IP (rogue host) | 172.17.79[.]135 |
| Hostname (DHCP, unconfirmed) | V17VT3M03 / later lease name, see Q2 |
| Name queried (typo) | DCC01 |
| Account (hash captured) | john.deacon |
| NTLM server challenge | 601019d191f054f1 |
| NTProofStr | c0cc803a6d9fb5a9082253a04dbd4cd4 |
| Technique | ID | Description |
|---|---|---|
| Adversary-in-the-Middle: LLMNR/NBT-NS Poisoning and SMB Relay | T1557.001 | Responder answering LLMNR and NBNS queries for DCC01 |
| Network Sniffing | T1040 | NTLMv2 challenge and response captured from the SMB negotiation |
| Brute Force: Password Cracking | T1110.002 | Captured NTLMv2 response cracked offline with hashcat -m 5600 and rockyou.txt |
Turn off LLMNR and NBT-NS. The whole attack depends on clients falling back to broadcast name resolution after DNS fails. Group Policy disables LLMNR, and NetBIOS over TCP/IP can be turned off per adapter. With both off, a typo fails instead of leaking a hash.
Alert on name-resolution replies from hosts that are not name servers. A workstation answering LLMNR or NBNS queries for names it does not own is a strong, low-noise signal. It was visible in the first filter of this capture.
Require SMB signing. It does not stop this capture-and-crack path, but it blocks relaying the same authentication to other hosts, which is the other half of what Responder enables.
Watch DHCP hostnames on the corporate segment. The rogue box announced itself in two leases with different names, one of them a default Linux distro style. A new, unmanaged host asking for a lease is worth a ticket.
Use long, unique passwords. The captured NTLMv2 response fell to a stock wordlist. Anyone who can sniff one exchange can test guesses offline at their leisure, so the password’s strength is the only remaining control.
One mistyped server name was enough for a rogue host to collect a domain user’s NTLMv2 exchange and crack the password offline. The attack never touched the domain controller; closing off LLMNR and NBT-NS would have turned the typo into a harmless error.