The (!FALSE) Pattern | Huntress
Part four of Huntress's LDAP/AD detection series shows that querying a non-existent LDAP attribute with negation (e.g., SOAPHound's hardcoded (!soaphound=*) filter) gets optimized by Active Directory's LDAP engine into (! (FALSE)) before it is written to Event ID 1644, erasing the tool's signature from logs. The author verifies this is universal AD behavior (not SOAPHound-specific), correlates it with SOAPHound's SDFlags:0x7 server control and its ADWS/port-9389 localhost proxying behavior, and publishes two Sigma rules combining the (! (FALSE)) pattern, attribute lists, and SDFlags for high-fidelity detection.
What it is
Part 4 of Huntress's LDAP/ADWS detection series, analyzing how SOAPHound (by FalconForce) evades Event ID 1644 signature detection. SOAPHound hardcodes the LDAP filter (!soaphound=*) across its collection modes, querying a non-existent attribute. The post shows why the tool's name never reaches the logs — and what markers survive that you can hunt on instead.
How it works
Active Directory deviates from RFC 4511 (which says filters on unrecognized attributes evaluate to Undefined, returning nothing). Per Microsoft's AD Technical Specification, the DC's LDAP service instead evaluates a non-existent attribute to FALSE, then optimizes the negation server-side during query parsing — after schema validation, before writing to Event ID 1644. The result: (!soaphound=*) is logged as ( ! (FALSE) ) and returns every object in the domain (311 of 311 in the lab). This is universal AD behavior; any negated non-existent attribute produces the identical filter and full-object return.
Because SOAPHound uses ADWS (port 9389, SOAP/XML) rather than direct LDAP, the DC proxies the query locally — so Event 1644 shows a localhost/link-local client ([::1] or fe80::…), obscuring attribution.
What to do
The signature (!soaphound=*) is useless — it never appears. Hunt on what remains in Event ID 1644:
- Filter
( ! (FALSE) )— an unusual pattern most defenders have never baselined. - Combined with
Server controls: SDFlags:0x7and a localhost/link-localClientfield, this distinguishes real SOAPHound from a benign[all]-attributes,[none]-controls test query. - The specific attribute selection SOAPHound requests (a strong secondary signal):
name, sAMAccountName, cn, dNSHostName, objectSid, objectGUID, primaryGroupID, distinguishedName, lastLogonTimestamp, pwdLastSet, servicePrincipalName, nTSecurityDescriptor, userAccountControl, sIDHistory, member, adminCount, msDS-AllowedToDelegateTo, gPCFileSysPath, gPLink, and others.
Reproduce the transformation in a lab (Part 1's Event 1644 logging enabled):
$searcher = [adsisearcher]"(!soaphound=*)"
$searcher.PageSize = 1000 # Ensure we get all results
$results = $searcher.FindAll()
Write-Host "Query: (!soaphound=*)"
Write-Host "Results: $($results.Count) objects"Caveats
The ( ! (FALSE) ) pattern is not unique to SOAPHound — any tool or query negating a non-existent attribute triggers it, so the filter alone will false-positive. The distinguishing combination is filter + SDFlags:0x7 + localhost client + the attribute list. The post excerpt cuts off mid-sentence on the SDFlags point (referencing Part 3), so treat the SDFlags detail as continued from that earlier post.
Organisations named here
- Event 1644
- FalconForce
- LDAP_SERVER_SD_FLAGS_OID
- RFC 4511
- SDFlags
Technologies named here
- Active Directory
- SOAPHound
- Active Directory Web Services
- Impacket
- SharpHound
- adsisearcher
- Sigma
- PowerShell
- LDAP
Techniques named here
- LDAP FALSE negation query obfuscation
- SDFlags control abuse
- ADWS-based enumeration for attribution evasion
- AD reconnaissance / enumeration
Related in Blue Team & Detection
AI-Coded Malware | Analyzing Vibe-Coded AD Enumeration | Huntress
