cumakurt/adar
GitHub: cumakurt/adar
一款面向 Active Directory 的授权渗透侦察与攻击工具,覆盖多层次技术与认证方式。
Stars: 10 | Forks: 1
# ADAR — Active Directory 攻击与侦察工具
[](https://www.gnu.org/licenses/agpl-3.0)
[](https://www.python.org/downloads/)
## 架构概览
```
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 --help
```
**From source (requirements only):**
```
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python adar.py --help
```
Requires **Python 3.10+**. See [requirements.txt](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.local
```
Without 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.
### Kerberos、Azure 和 OWA 用户枚举
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.txt
```
### 认证扫描
```
python adar.py -t dc01.corp.local -d corp.local \
-u admin -p 'Password1!' \
-f json -f html -o ./reports/
```
### 隐身模式(IDS 规避)
```
python adar.py -t 10.0.0.5 -d lab.test \
--noise very_low --timeout 15 -w users.txt
```
### Pass-the-Hash(NT 哈希)
```
python adar.py -t 10.0.0.5 -d corp.local \
-u admin --hash aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0
```
## CLI 参数
| 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 |
## 示例 JSON 输出
```
{
"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).
### 层级 1 — 未认证,最小噪音
| 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. |
### 层级 2 — 被动 / 侧信道 / 低认证
| | 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`. 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. |
### 层级 3 — 需要凭据
| 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. |
### 层级 4 — 专门化 / 高级
| 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. |
### Azure 和 OWA 枚举 — 运行时机与测试方法
Both techniques run when their preconditions are met. They use the **embedded smart username list** when no wordlist is provided.
#### Azure 枚举(`azure_enum`)
- **When it runs:** (1) Target domain must be **registered in Azure AD** (verified via OpenID config probe). (2) Candidate usernames come from `-w` wordlist if provided, otherwise from the embedded smart list.
- **How to verify:** Request `https://login.microsoftonline.com/{domain}/.well-known/openid-configuration`; look for `microsoftonline.com` or `login.windows.net` in the `issuer` field. If not found, the technique is skipped.
- **How to test:** If the domain is in Azure, POST `user@domain` to 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.txt` to extend with a file.
#### OWA 计时(`owa_timing`)
**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.txt` is 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](LICENSE). Use only for authorized security testing.
## 开发者
- **Email:** cumakurt@gmail.com
- **LinkedIn:** [cuma-kurt-34414917](https://www.linkedin.com/in/cuma-kurt-34414917/)
- **GitHub:** [cumakurt/adar](https://github.com/cumakurt/adar)
标签:Active Directory, ADCS枚举, AGPLv3, AS-REP Roasting, Azure AD枚举, DNS 反向解析, DNS枚举, DNS 解析, DOS头擦除, ESC4, GPLv3, HTTP工具, Kerberoasting, LDAP, LDAP认证枚举, MS-SAMR, OSINT, OWA定时侧信道, OXID解析, Plaso, Python, Python 3.10+, Python 3.9+, SID循环, SMB空会话, SMTP VRFY, SYSVOL枚举, T1, T2, T3, T4, 凭证获取, 去重, 反取证, 噪声控制, 域渗透, 安全评估, 密码破解, 开源安全工具, 异步, 打印机后台程序枚举, 授权测试, 数据展示, 无后门, 无线安全, 标签:AD, 标签:内网渗透, 标签:安全工具, 标签:密码学, 标签:目录服务, 横向移动, 用户枚举, 电子数据取证, 红队, 编程规范, 网络安全审计, 网络安全工具, 计算机取证, 证书模板枚举, 逆向工具, 逆向工程平台, 风险评分