For authorized penetration testing use only. Unauthorized use against systems you do not own or have permission to test may be illegal.
Turkish documentation: README.tr.md
adar/
├── core/
│ ├── engine.py # Main orchestration engine (ScanEngine)
│ ├── result_store.py # Async-safe user aggregation & dedup
│ └── noise_controller.py # Adaptive rate limiting & jitter
├── techniques/
│ ├── base.py # Abstract BaseTechnique
│ ├── dns_enum.py # [T1] DNS SRV record queries
│ ├── ldap_enum.py # [T1] LDAP anonymous bind + paged dump
│ ├── kerberos_enum.py # [T1] Kerberos AS-REQ user probing (wordlist or built-in)
│ ├── smb_enum.py # [T1] SMB null session probe
│ ├── samr_enum.py # [T2] MS-SAMR user enumeration
│ ├── rid_cycling.py # [T2] SID+RID brute-force (500-2000)
│ ├── oxid_resolver.py # [T2] OXID ServerAlive2 interface enum
│ ├── ldap_auth_enum.py # [T3] Authenticated LDAP full attribute dump
│ ├── asreproast_enum.py # [T3] AS-REP Roasting — hashcat hash dump
│ ├── kerberoast_enum.py # [T3] Kerberoasting SPN accounts
│ ├── sysvol_enum.py # [T3] SYSVOL/GPO script & Groups.xml parse
│ ├── adcs_enum.py # [T4] ADCS cert template enum + ESC1/2/3/4 vuln detection
│ ├── azure_enum.py # [T4] Azure AD GetCredentialType user enum
│ ├── smtp_enum.py # [T4] SMTP VRFY/EXPN user validation
│ ├── owa_timing.py # [T4] OWA/EWS HTTP timing side-channel
│ ├── printer_spooler.py # [T4] MS-RPRN job owner enum + PrinterBug detection
│ └── ldap_referral.py # [T2] Forest/trust referral chase
├── intelligence/
│ ├── dc_fingerprint.py # DC service & capability detection
│ └── technique_selector.py # Tier-aware technique pipeline builder
├── output/
│ └── reporter.py # Rich terminal + JSON + CSV + HTML
├── types_/
│ └── models.py # Pydantic v2 models & enums
└── adar.py # Click CLI entry point
From GitHub (recommended):
git clone https://github.com/cumakurt/adar.git
cd adar
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .
adar --helpFrom source (requirements only):
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python adar.py --helpRequires Python 3.10+. See requirements.txt for dependencies.
Domain is auto-discovered if omitted (LDAP/SMB/Kerberos/rDNS).
python adar.py -t 192.168.1.10
python adar.py -t 192.168.1.10 -d corp.localWithout credentials, all unauthenticated tactics run: Tier 1–2 and credential-free Tier 4 (DNS, LDAP anon, Kerberos AS-REQ, SMB null, LLMNR/passive listener, OXID, SAMR, RID cycling, DNS LDAP dump, Global Catalog, SCCM, MS-RPRN). With default --noise high, techniques run at maximum speed unless you explicitly lower the noise budget.
If no wordlist (-w) is given, Kerberos uses the embedded smart list (administrator, guest, krbtgt, etc.); Azure enum and OWA timing also use the embedded list when no wordlist is provided (see Tier 4 details below).
python adar.py -t 192.168.1.10 -d corp.local -w /path/to/users.txtpython adar.py -t dc01.corp.local -d corp.local \
-u admin -p 'Password1!' \
-f json -f html -o ./reports/Note: Tier 3 techniques (
ldap_auth,kerberoast, etc.) are required for full user discovery. They run only with--profile defaultor--profile full.--profile stealthuses only Tier 1–2; no user enum even when credentials are provided.
python adar.py -t 10.0.0.5 -d lab.test \
--noise very_low --timeout 15 -w users.txtpython adar.py -t 10.0.0.5 -d corp.local \
-u admin --hash aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0| Parameter | Short | Default | Description |
|---|---|---|---|
--target |
-t |
required | DC IP or hostname |
--domain |
-d |
— | AD domain (auto-discovered if omitted) |
--username |
-u |
— | Username |
--password |
-p |
— | Password |
--hash |
— | — | NTLM hash |
--wordlist |
-w |
— | User list for Kerberos, Azure AD, OWA timing, SMTP VRFY |
--profile |
— | default |
default (all tiers), stealth (T1–2 only), full, soc-full |
--noise |
— | high |
very_low / low / medium / high |
--timeout |
— | 10 |
Connection timeout (seconds) |
--output-dir |
-o |
. |
Report output directory |
--format |
-f |
terminal,json,html |
Output format (repeatable) |
--concurrent |
— | 3 |
Concurrent techniques per tier |
--listen-time |
— | 60 (stealth: 300) |
Passive listener duration (seconds) |
--verbose |
-v |
false |
Debug logging |
{
"username": "admin",
"confidence": "confirmed",
"found_by": ["kerberos_enum", "ldap_anon"],
"attributes": {
"email": "admin@corp.local",
"display_name": "Admin",
"groups": ["Domain Users", "IT Staff"],
"enabled": true
},
"timestamp": "2024-01-15T10:23:41Z"
}| Tier | Technique | Description |
|---|---|---|
| T1 | DNS enum | SRV records, zone transfer attempt |
| T1 | LDAP anon | Anonymous bind + user search |
| T1 | Kerberos enum | AS-REQ user existence check (wordlist or built-in) |
| T1 | SMB null | Null session, OS/domain info |
| T1 | LLMNR/NBT-NS listener | Passive; name queries and NTLM capture |
| T1 | Passive traffic | mDNS/NBNS passive listen |
| T2 | LDAP referral | Forest/trust referral chase |
| T2 | OXID resolver | RPC endpoint list |
| T2 | SAMR | MS-SAMR user list (null/auth) |
| T2 | RID cycling | SID+RID account name resolution |
| T2 | DNS LDAP dump | ADIDNSdump-style DNS record dump |
| T2 | Global Catalog | GC bind + user search |
| T2 | SCCM enum | SCCM/MDT MP and NAA discovery |
| T4 | Printer Spooler | MS-RPRN job owner enum, PrinterBug check |
Tier 3 (LDAP auth, AS-REP Roasting, Kerberoasting, SYSVOL, vulnerable accounts) requires credentials (-u/-p or --hash). ADCS in T4 requires credentials; Azure enum and OWA timing do not require credentials and use the embedded smart list when no wordlist is given (see “Azure and OWA details” below).
Each technique is described with method (how it works) and rationale (why it is used).
| Technique | Method | Rationale |
|---|---|---|
| dns_enum | Queries standard AD DNS SRV records (_kerberos._tcp, _ldap._tcp, _ldap._tcp.dc._msdcs, _gc._tcp, etc.) via the target as DNS server. Optionally probes TXT and zone transfer. |
Confirms DC presence and discovers additional DCs/forest members without any authentication. Purely passive from an AD auth perspective; only DNS traffic. |
| ldap_anon | Binds to LDAP (port 389) with anonymous authentication. Tries multiple strategies: (1) paged user search with full attributes, (2) minimal attributes (sAMAccountName) with alternate filters, (3) well-known accounts (Administrator, Guest, krbtgt) by DN, (4) CN=Users subtree. | Many misconfigured or legacy DCs allow anonymous LDAP bind; this yields a direct list of user objects when ACLs permit. Very low noise. |
| kerberos_enum | Sends Kerberos AS-REQ (Authentication Service Request) for each candidate username (wordlist or embedded smart list). Interprets KDC response: KDC_ERR_PREAUTH_REQUIRED (25) → user exists; KDC_ERR_C_PRINCIPAL_UNKNOWN (6) → user does not exist. |
The KDC reveals user existence without requiring a password. Industry-standard user enumeration method; wordlist-driven and throttleable. |
| smb_null | Establishes an unauthenticated (null) SMB session to port 445 (empty username/password). Retrieves NetBIOS domain name, DNS hostname, and OS version via SMB calls. | Confirms that null session is allowed, which is a prerequisite for SAMR/RID cycling on older DCs. Does not enumerate users itself but enriches DC fingerprint. |
| llmnr_listener | Passive only (no packet injection). Binds to LLMNR (UDP 5355, multicast 224.0.0.252), NBT-NS (UDP 137), and mDNS (UDP 5353). Captures hostname queries and, when present, NTLM Type-1/2/3 messages (usernames and optionally NTLMv2 hashes). | Equivalent to Responder “analysis” mode: observes what names hosts request and any NTLM traffic on the wire. Zero risk of poisoning; useful for user/hash discovery in shared segments. |
| passive_traffic | Fully passive — sends no packets. Sniffs mDNS (UDP 5353) and NBNS (UDP 137) on the local segment. Extracts machine names and infers computer accounts (HOSTNAME$) and possible usernames from naming conventions. | Complements LLMNR listener with multicast/broadcast-only capture. Reveals hostnames and naming patterns that often map to AD users; requires CAP_NET_RAW. |
| Technique | Method | Rationale |
|---|---|---|
| ldap_referral | Queries the domain’s trustedDomain objects via LDAP to list forest and external trusts. For INBOUND/BIDIRECTIONAL trusts, follows LDAP referrals to the trusted DC and attempts anonymous bind and base DN / user enumeration. | Trust map is essential for cross-domain and forest escalation. Referral chase can yield users in trusted domains when anonymous bind is allowed there. |
| oxid_resolver | Single RPC call to IObjectExporter::ServerAlive2 on port 135 (RPC Endpoint Mapper). Parses the response for network interface strings (IPs and hostnames). | Reveals alternate hostnames and IPs the DC exposes; used as recon for later techniques and for pivot targets. Very low noise (one call). |
| samr_enum | Uses MS-SAMR over the \pipe\samr SMB named pipe. Connects with null session or provided credentials, opens domain handle, and enumerates users via SamrEnumerateUsersInDomain (paged). |
SAMR is the canonical way to list domain users over the network. Null session works on legacy DCs; modern DCs require credentials. Results are CONFIRMED when authenticated. |
| rid_cycling | (1) Resolves domain SID via LSA or SAMR. (2) Builds SID+RID combinations for RIDs 500–2000 (configurable). (3) Uses MS-SAMR LookupRids in batches to resolve RID → account name. Filters out group RIDs (512–520), keeps users. | When SAMR enumeration is restricted, RID cycling still resolves known RIDs (e.g. 500=Administrator) and discovers additional accounts by brute-forcing RID space. |
| dns_ldap_dump | adidnsdump-style: queries LDAP partitions DC=DomainDnsZones and DC=ForestDnsZones for DNS nodes. Parses dnsRecord binary blobs, builds hostname→IP map, and derives service account candidates from naming (e.g. svc-, sql-, web-). |
AD-integrated DNS is stored in LDAP; dumping it reveals hostnames and hidden records. Service account names inferred from hostnames are high-value targets. Works anonymous when allowed; better with credentials. |
| global_catalog | Connects to Global Catalog (port 3268 or 3269 for LDAPS). Search base ""; queries for user objects across the entire forest. Uses paged search with user attributes. |
GC holds a partial replica of every domain in the forest; one connection can enumerate users from all child domains without knowing their DNs. Anonymous possible on some DCs; credentials improve coverage. |
| sccm_enum | (1) LDAP: finds SCCM Management Points and sites. (2) HTTP: probes MP endpoints for XML that may contain usernames. (3) SMB: checks MDT shares for Bootstrap.ini / CustomSettings.ini with NAA credentials. |
SCCM/MDT often store deployment and NAA credentials in plaintext. Discovering MPs and parsing config files yields service accounts and sometimes passwords. |
| Technique | Method | Rationale |
|---|---|---|
| ldap_auth | Binds to LDAP (389) or LDAPS (636) with provided credentials (Simple or NTLM). Performs paged search for all user objects with a full attribute set. | With valid credentials, LDAP is the highest-fidelity source of user and group data. Single technique for complete user dump and attributes. |
| asreproast | (1) LDAP (authenticated): finds users with DONT_REQUIRE_PREAUTH. (2) Sends AS-REQ for each such user (no preauth). (3) Extracts the encrypted AS-REP part and outputs hashcat format. | Accounts without preauth can be “roasted”: the KDC returns an encrypted ticket that can be cracked offline. |
| kerberoast | (1) LDAP (authenticated): queries users with servicePrincipalName set (and not disabled). (2) Uses provided credentials to get a TGT, then requests TGS for each SPN. (3) Extracts RC4-encrypted service ticket part in hashcat format. | Service accounts with SPNs get TGS tickets encrypted with their password-derived key; these hashes can be cracked offline. Standard Kerberoasting. |
| sysvol_enum | Connects via SMB with credentials to SYSVOL and NETLOGON. Recursively walks shares for GPO-related files. Parses Groups.xml and other GPO XML for cpassword (GPP encrypted password); decrypts with Microsoft’s published AES key. |
GPP often contained credentials; cpassword is decryptable. Finding plaintext GPP credentials is critical for privilege escalation and lateral movement. |
| ldap_vuln_accounts | LDAP (authenticated): searches for accounts with sensitive userAccountControl flags and adminCount=1. Scans description for regex patterns indicating embedded passwords. | Weak UAC settings and credentials in description fields are common misconfigurations. This technique flags high-value and easily abused accounts. |
| Technique | Method | Rationale |
|---|---|---|
| adcs_enum | LDAP (authenticated): reads Configuration partition for certificate templates and CAs. Evaluates templates for ESC1–8. Extracts enrollable principals from ACEs. | AD CS misconfigurations (ESC1–8) allow privilege escalation. Enumeration identifies vulnerable templates and high-value accounts that can enroll. |
| azure_enum | Calls the unauthenticated GetCredentialType API on login.microsoftonline.com for the target domain. Sends candidate usernames (embedded list or wordlist); interprets IfExistsResult (0/5/6 = exists, 1 = not found). Only runs if the domain is registered in Azure (OpenID config probe). |
Hybrid and cloud-only Azure AD accounts can be enumerated via this public API. |
| smtp_enum | Probes SMTP (port 25, fallbacks 587/465/2525). Tries VRFY first; if disabled (501/502), falls back to EXPN. For each candidate, parses reply: 2xx = user exists, 5xx = not found. Rate-limited with jitter. | Legacy and misconfigured SMTP servers reveal valid mailboxes without authentication. |
| owa_timing | Timing side-channel: discovers OWA/EWS endpoints. Sends auth requests with known-invalid usernames to establish a baseline response time. For each candidate, compares average response time; significantly slower responses indicate valid account. Confidence POSSIBLE due to false positives under load. | Exchange/OWA often take longer to respond for valid users than invalid ones. Allows user enumeration without valid credentials when other methods are locked down. |
| printer_spooler | Uses MS-RPRN over \pipe\spoolss. Calls EnumPrinters and EnumJobs to list printers and print job owners (usernames). Optionally checks OpenPrinterEx without credentials to assess PrinterBug (SpoolSample) NTLM relay surface. |
Print jobs are owned by real AD accounts; enumerating job owners reveals users and often privileged or service accounts. PrinterBug check identifies relay targets. |
Both techniques run when their preconditions are met. They use the embedded smart username list when no wordlist is provided.
- When it runs: (1) Target domain must be registered in Azure AD (verified via OpenID config probe). (2) Candidate usernames come from
-wwordlist if provided, otherwise from the embedded smart list. - How to verify: Request
https://login.microsoftonline.com/{domain}/.well-known/openid-configuration; look formicrosoftonline.comorlogin.windows.netin theissuerfield. If not found, the technique is skipped. - How to test: If the domain is in Azure, POST
user@domainto the GetCredentialType API (/common/GetCredentialType).IfExistsResult: 0/5/6 → user exists, 1 → not found. - Summary: If the domain is not an Azure AD tenant, Azure enum is skipped. Example:
adar -t dc -d corp.local --profile full(uses embedded list); add-w users.txtto extend with a file.
- When it runs: (1) OWA must be reachable on the target: ports 443 or 80 open and an OWA/EWS endpoint discoverable. (2) Candidates come from wordlist if provided, otherwise from the embedded smart list.
- How it is discovered: Check that 443/80 is open on the target, then probe:
/owa/auth.owa,/owa/,/EWS/Exchange.asmx,/autodiscover/autodiscover.xml,/Microsoft-Server-ActiveSync. The first URL that does not return 5xx is used as the OWA endpoint. - How to test: Establish a timing baseline with known-invalid usernames (e.g.
nonexistent_user_xzqj7). For each candidate, send an OWA login POST and measure response time; values clearly above the baseline (e.g. ~80 ms + 2σ) are treated as “likely valid” (timing side-channel). - Summary: If the target has no HTTP/HTTPS or OWA (e.g. target is only a DC), OWA timing is skipped or ends with “No OWA endpoint discovered”. To test OWA, the target must serve Exchange/OWA;
-w users.txtis optional (embedded list is used otherwise).
| Level | Use case | Delay |
|---|---|---|
very_low |
Stealth — passive/DNS | 0.5s + jitter |
low |
Normal pentest | 0.2s + jitter |
medium |
Fast scan | 0.05s + jitter |
high |
Maximum speed | 0s + jitter |
| Score | Meaning |
|---|---|
confirmed |
Definitive — LDAP attribute dump or KDC_ERR_PREAUTH_REQUIRED |
probable |
Likely valid — multiple sources |
possible |
Weak signal — single source, indirect |
GNU Affero General Public License v3.0 (AGPL-3.0) — see LICENSE. Use only for authorized security testing.
- Email: cumakurt@gmail.com
- LinkedIn: cuma-kurt-34414917
- GitHub: cumakurt/adar