Blackbird: Defeating PatchGuard, One Layer Deeper.
How do you maintain observability without sacrificing system stability? Diving into the depths of virtualization and extended page tables.
Read articleA long Windows Active Directory chain from LDAP injection and NTLM coercion through delegated ACL abuse, AD CS ESC3, protected-object inheritance repair, and S4U2Self U2U with RBCD.
How do you maintain observability without sacrificing system stability? Diving into the depths of virtualization and extended page tables.
Read articleA long Windows Active Directory chain from LDAP injection and NTLM coercion through delegated ACL abuse, AD CS ESC3, protected-object inheritance repair, and S4U2Self U2U with RBCD.
Read articleWhat happens when an EDR trusts filenames, unauthenticated localhost traffic and world-writable kernel objects? Five vulnerabilities, two SYSTEM LPE's and an RCE, a driver load and a lot of assumptions that should never have crossed a security boundary.
Read articleA complete Windows attack chain through OAuth account-linking abuse, stored browser navigation, SQLite extension loading, DPAPI credential recovery, and a writable SYSTEM service binary.
Read articleSysWhispers, HellsGate, HeavensGate, SidewaysGate, SpoofGate, TFGate, DoomGate, whatever gate your tool is being detected before the initial handle fully opens. How do EDR's detect & deny direct and indirect syscalls?
Read articleHow does Blackbird make Windows lie to malware's faces? Most anti-analysis checks trust the kernel because they have no choice. Blackbird weaponizes this by modifying syscall, timing & registry return data, erasing VM-identifiers and much, much more.
Read articleThere's a reason security products avoid kernel hooking. They are fragile, build-sensitive, and BSOD prone. Advanced malware analysis demands the visibility they provide. This post delves into the hook engine behind Blackbird and the struggle developing it.
Read articleModern defensive tooling doesn’t need to see payloads to stop you, it only needs to see the call path. This post breaks down how Windows system calls are intercepted, how syscall stubs became signatures, and why ActiveBreach takes a fundamentally different approach.
Read articleHercules was a long Windows Active Directory chain that rewarded careful mapping of delegated permissions rather than a single dominant vulnerability.
The route to domain compromise was:
The exposed IIS application built LDAP filters without safely escaping user-controlled input. The injection disclosed enough application material to reproduce the ASP.NET Forms Authentication state and create a valid privileged session.
With the forged session, I reached document-generation functionality that could be used for a BadODT-style file and credential-coercion attack. The resulting NTLM response belonged to Natalie and was crackable offline.
The recovered domain identity was:
HERCULES\natalie.a : <redacted>
This first stage crossed three boundaries in sequence: LDAP injection exposed application secrets, those secrets enabled session forgery, and the authenticated document workflow provided an NTLM coercion primitive.
BloodHound and direct ACL inspection showed that Natalie had GenericWrite over Bob. Rather than making a permanent password or group change, I used Certipy's reversible shadow-credentials workflow:
certipy shadow auto -k -no-pass \
-account bob.w \
-target dc.hercules.htb \
-dc-ip <redacted-dc-ip>
The operation temporarily added attacker-controlled key credential material, authenticated as Bob, and restored the original msDS-KeyCredentialLink state automatically. This produced a usable Kerberos context for Bob without leaving the injected key credential behind.
bob.w : <redacted-nt-hash>
Bob was a Recruitment Manager and controlled the Security Department path containing Auditor. That delegated control was enough to take over Auditor, enable the account, reset its password, and obtain a TGT.
Auditor belonged to Forest Management, which controlled the Forest Migration OU. I changed the OU owner to Auditor and granted it full control, creating a stable point from which to manage delegated ACEs beneath that OU.
This section of the chain was a reminder that Active Directory privilege is often encoded in object ownership and inheritance rather than obvious group membership. None of these accounts was a domain administrator, but each controlled the next security boundary.
Fernando was reachable through the Forest Migration ACL. His Smartcard Operators-related enrollment rights allowed access to the EnrollmentAgent certificate template:
certipy req -k -no-pass \
-dc-ip <redacted-dc-ip> \
-dc-host dc.hercules.htb \
-target dc.hercules.htb \
-target-ip <redacted-dc-ip> \
-ca CA-HERCULES \
-template EnrollmentAgent \
-out fernando-agent.pfx \
-dcom -dynamic-endpoint
The CA restricted enrollment-agent use to members of Domain Employees. A direct request for Administrator was therefore denied, but Ashley satisfied the policy. I used Fernando's enrollment-agent certificate to request a Smartcard Logon certificate on Ashley's behalf:
certipy req -k -no-pass \
-dc-ip <redacted-dc-ip> \
-dc-host dc.hercules.htb \
-target dc.hercules.htb \
-target-ip <redacted-dc-ip> \
-ca CA-HERCULES \
-template SmartcardLogon \
-on-behalf-of 'HERCULES\ashley.b' \
-pfx fernando-agent.pfx \
-out ashley.pfx \
-dcom -dynamic-endpoint
Authenticating with that certificate returned Ashley's TGT and account hash:
ashley.b : <redacted-nt-hash>
The important ESC3 condition was not simply the presence of an enrollment-agent template. The path required control of an eligible enrollment principal, permission to use the agent template, a target user accepted by the CA's restrictions, and a second template that allowed enrollment on behalf of that user.
Ashley belonged to IT Support and Remote Management Users. The IT share contained cleanup.lnk, which referenced:
C:\Users\ashley.b\Desktop\aCleanup.ps1
The script appeared absent over the Users SMB share because access-based enumeration hid it. From Ashley's Kerberos-authenticated WinRM session, however, the file was visible and contained only:
Start-ScheduledTask -TaskName "Password Cleanup"
The scheduled task ran as SYSTEM and wrote its log beneath Ashley's profile. Mail in the profile explained its purpose: formerly privileged users retained protected DACLs, preventing departmental password-reset delegation from applying. The cleanup task repaired inheritance, but only in OUs containing a delegated password-reset ACE.
IIS_Administrator lived inside Forest Migration with adminCount=1 and a protected DACL. I added an inherited Reset Password delegation for IT Support to the controlled OU:
dacledit.py -k -no-pass \
-dc-ip <redacted-dc-ip> \
-dc-host dc.hercules.htb \
-action write \
-rights ResetPassword \
-inheritance \
-principal 'IT Support' \
-target-dn 'OU=Forest Migration,OU=DCHERCULES,DC=hercules,DC=htb' \
'hercules.htb/auditor'
After starting Password Cleanup again, its log included IIS_Administrator. The task removed the account's adminCount, disabled DACL protection, and restored inherited permissions.
I could then add inherited control for Auditor, clear ACCOUNTDISABLE, and reset the account password through Kerberos-authenticated SAMR as Ashley:
changepasswd.py -k -no-pass -reset \
-altuser 'hercules.htb/ashley.b' \
-newpass '<redacted>' \
-protocol smb-samr \
-dc-ip <redacted-dc-ip> \
'hercules.htb/iis_administrator@dc.hercules.htb'
The escalation depended on understanding the cleanup task's selection logic. Triggering it alone was insufficient; the controlled OU first needed the delegated password-reset ACE that made the protected account eligible for repair.
IIS_Administrator belonged to Service Operators. That group had Force Change Password over the iis_webserver$ service account.
The domain controller's resource-based constrained delegation descriptor trusted the service account SID. The service account did not have an SPN, so the ordinary S4U2Self path was unavailable. I used the user-to-user Kerberos variant instead:
iis_webserver$ to controlled key material;The core request was:
KRB5CCNAME='iis_webserver$.ccache' getST.py \
-k -no-pass \
-dc-ip <redacted-dc-ip> \
-u2u \
-impersonate Administrator \
-spn cifs/dc.hercules.htb \
'hercules.htb/iis_webserver$'
This produced an Administrator service ticket for CIFS without requiring the controlled account to advertise its own SPN. I repeated the request for HTTP/dc.hercules.htb and used the resulting ticket for an Administrator WinRM session.
hercules\administrator
Hercules combined several independent trust failures:
GenericWrite, ownership, and inherited ACE control connected otherwise unprivileged identities.GenericWrite, password-reset, and inherited-control paths in Active Directory;adminCount removal and DACL-protection changes;Hercules was less about one exotic exploit than about maintaining a correct model of identity, ownership, inheritance, certificate issuance, and Kerberos delegation across a long chain. Each stage became possible because the previous principal controlled exactly one more trust decision than it should have.