T1568.002

Domain Generation Algorithms

Adversaries use Domain Generation Algorithms (DGAs) to dynamically identify C2 destinations by algorithmically generating large numbers of candidate domain names. Only the operator-registered domain resolves successfully; all others return NXDOMAIN. This makes blocking impractical — defenders cannot predict the full space of generated domains. DGAs may produce random character strings (e.g., istgmxdejdnxuyla.ru) or concatenate dictionary words (e.g., cityjulydish.net). Many implementations are time-seeded, generating different candidate domains hourly or daily. Some incorporate a shared secret seed to prevent defender prediction. Detection focuses on statistical anomalies: abnormally high NXDOMAIN failure rates from a single host, domain names with low vowel ratios or high character entropy, rapid successive queries to many unique failing domains, and beaconing patterns once a DGA domain resolves. Malware families using DGA include QakBot, Conficker, Ursnif, DarkWatchman, BONDUPDATER, POSHSPY, CHOPSTICK, Aria-body, Milan, SombRAT, and MiniDuke. APT41 changes C2 monthly via DGA; TA551 generates URLs from executed macros.

Microsoft Sentinel / Defender
kusto
// T1568.002 — DGA Detection via NXDOMAIN Rate and Domain Entropy Analysis
// Requires: Azure DNS Analytics solution (DnsEvents table) or DNS server logs ingested via AMA/CEF
// Tune NXDomainThreshold and UniqueDomainsThreshold against your environment's DNS failure baseline
let TimeWindow = 1h;
let NXDomainThreshold = 20;
let UniqueDomainsThreshold = 15;
DnsEvents
| where TimeGenerated > ago(TimeWindow)
| where ResultCode == 3  // NXDOMAIN — query returned 'no such domain'
| extend Name = tolower(Name)
| extend DomainParts = split(Name, '.')
| extend SLD = tostring(DomainParts[array_length(DomainParts) - 2])
| where strlen(SLD) >= 7
| extend DomainLength = strlen(SLD)
// Vowel ratio: legitimate human-readable domains average 35-45% vowels
// DGA random-character strings typically have <20% vowels
| extend VowelCount = countof(SLD, 'a') + countof(SLD, 'e') + countof(SLD, 'i') + countof(SLD, 'o') + countof(SLD, 'u')
| extend VowelRatio = todouble(VowelCount) / todouble(DomainLength)
// Digit ratio: many DGAs embed digits; legitimate SLDs rarely exceed 30% digits
| extend DigitCount = countof(SLD, '0') + countof(SLD, '1') + countof(SLD, '2') + countof(SLD, '3') + countof(SLD, '4') + countof(SLD, '5') + countof(SLD, '6') + countof(SLD, '7') + countof(SLD, '8') + countof(SLD, '9')
| extend DigitRatio = todouble(DigitCount) / todouble(DomainLength)
| extend IsLikelyDGA = iff(
    VowelRatio < 0.20     // Very few vowels — algorithmically-generated random string
    or DigitRatio > 0.35  // High digit density — e.g., Conficker, QakBot variants
    or DomainLength > 16, // Abnormally long SLD uncommon in legitimate domains
    1, 0)
| summarize
    TotalNXDomain   = count(),
    UniqueNXDomains = dcount(Name),
    LikelyDGACount  = countif(IsLikelyDGA == 1),
    SampleDomains   = make_set(Name, 10),
    FirstSeen       = min(TimeGenerated),
    LastSeen        = max(TimeGenerated)
    by Computer, ClientIP
| where TotalNXDomain >= NXDomainThreshold and UniqueNXDomains >= UniqueDomainsThreshold
| extend DurationMinutes = iff(
    datetime_diff('minute', LastSeen, FirstSeen) < 1,
    todouble(1),
    todouble(datetime_diff('minute', LastSeen, FirstSeen)))
| extend QueryRate = round(todouble(UniqueNXDomains) / DurationMinutes, 2)
| extend AlertSeverity = case(
    LikelyDGACount > 10 and QueryRate > 5.0, 'Critical',
    LikelyDGACount > 5  or QueryRate > 2.0, 'High',
    'Medium')
| project
    Computer, ClientIP,
    TotalNXDomain, UniqueNXDomains, LikelyDGACount,
    QueryRate, DurationMinutes,
    AlertSeverity, SampleDomains,
    FirstSeen, LastSeen
| sort by LikelyDGACount desc, TotalNXDomain desc
high severity medium confidence

Data Sources

Network Traffic: DNS Resolution Azure DNS Analytics (DnsEvents table) DNS Server: Analytical Logs

Required Tables

DnsEvents

False Positives

  • Cloud infrastructure with GUID-based hostnames (Azure, AWS, GCP auto-generated resource names) performing DNS lookups that fail when services are deprovisioned or accessed cross-region
  • Security scanning and threat intelligence tools (Nessus, Qualys, Shodan crawlers, passive DNS enrichment pipelines) performing bulk DNS enumeration generating high NXDOMAIN rates
  • Content delivery networks using algorithmically-generated short-TTL subdomains with low vowel ratios — some Akamai, Cloudflare, and Fastly edge-node hostnames match entropy thresholds
  • Software development and CI/CD pipelines running integration tests that generate randomized ephemeral test domain names, or microservices discovery in misconfigured service meshes
  • Misconfigured DNS resolvers, split-horizon DNS setups, or VPN clients resolving internal domains against a public resolver — causing legitimate internal hostnames to return NXDOMAIN

Unlock Pro Content

Get the full detection package for T1568.002 including response playbook, investigation guide, and atomic red team tests.

Response PlaybookInvestigation GuideHunting QueriesAtomic Red Team TestsTuning Guidance

Related Detections