-
-
Notifications
You must be signed in to change notification settings - Fork 97
Obfuscation
PowerView.py uses ldapx-py to obfuscate LDAP queries and related parameters, varying observable patterns while preserving query intent. This feature transforms LDAP filters, distinguished names, and attribute lists using composable chain codes, making queries less predictable and harder to signature.
Pass the --obfuscate flag when launching PowerView. With no value, default chains are used:
powerview range.net/lowpriv:Password123@192.168.86.192 --obfuscateYou can also specify custom chain codes to control which techniques are applied:
powerview range.net/lowpriv:Password123@192.168.86.192 --obfuscate CZANDRToggle the Obfuscate option in the Settings panel. This applies to subsequent queries for the active session.
Obfuscation is applied to three components of LDAP queries:
| Component | Default Chain | Description |
|---|---|---|
| Filter | CZNDR |
Transforms attribute names, operators, and values within LDAP search filters |
| DN | CX |
Mutates the search base distinguishedName |
| Attributes | CR |
Mutates the requested attribute list |
Each letter in the chain string applies an obfuscation technique in order. Run ldapx codes --all to see all available codes.
| Code | Technique | Description |
|---|---|---|
C |
Random case | Attribute names and values are randomly uppercased and lowercased |
Z |
Prepend zeros | Numeric and SID values are prepended with leading zeros |
X |
Hex encode | DN-type values are hex-encoded |
A |
Approx match | The = operator is replaced with ~= (approximate match). Auto-skips non-string attributes |
N |
ANR | Compatible attributes are replaced with Ambiguous Name Resolution |
D |
Double negation | Filters are wrapped in double negation (!(!(filter)))
|
M |
De Morgan transform | Boolean logic is rewritten using De Morgan's laws |
R |
Reorder | AND/OR clause order is shuffled |
B |
Add boolean | Filters are wrapped in redundant AND/OR |
T |
Tautologies | Presence filters are replaced with equivalent tautologies |
s |
Substring split | Equality matches are split into substring matches |
x |
Extensible match | Equality matches are converted to extensible match syntax |
b |
Bitwise breakout | Equality is converted to bitwise matching rules |
d |
Bitwise decompose | Bitwise values are broken into individual bits |
I |
Equality by inclusion | Equality is rewritten as range + exclusion |
E |
Equality by exclusion | Equality is rewritten as presence + NOT range |
L |
Transitive eval | Link attributes are converted to matching rule 1.2.840.113556.1.4.1941 |
F |
objectCategory form | Toggles between short name and full DN form |
t |
Timestamp garbage | Noise is added to timestamp patterns |
P |
dnAttributes noise |
:dn: is randomly toggled on extensible match rules |
Using filter (&(samAccountType=805306368)(sAMAccountName=Administrator)) as input:
C — Random case
(&(saMAccoUntTyPE=805306368)(sAMAccouNTNAme=AdmIniStratOR))
Z — Prepend zeros
(&(samAccountType=00805306368)(sAMAccountName=Administrator))
X — Hex encode (on DN-type value memberOf=CN=Domain Admins,...)
(memberOf=CN=D\6fm\61i\6e Admins,CN=Users,DC=abc,DC=l\6fcal)
A — Approx match (note: samAccountType is skipped because it's numeric)
(&(samAccountType=805306368)(sAMAccountName~=Administrator))
N — ANR
(&(samAccountType=805306368)(aNR==Administrator))
D — Double negation
(&(!(!(!(!(!(!(!(!(samAccountType=805306368)))))))))(!(!(sAMAccountName=Administrator))))
M — De Morgan transform
(!(|(!(samAccountType=805306368))(!(sAMAccountName=Administrator))))
R — Reorder
(&(sAMAccountName=Administrator)(samAccountType=805306368))
s — Substring split
(sAMAccountName=Administ*rator)
x — Extensible match
(sAMAccountName:=Administrator)
Default CZNDR — all default techniques combined
(&(!(!(!(!(!(!(!(!(!(!(aNR==adminisTrAtor)))))))))))(!(!(!(!(!(!(!(!(!(!(!(!(samaccounTType=805306368)))))))))))))
| Code | Reason |
|---|---|
G |
Injects garbage attribute names that AD rejects |
O |
Generates OID format with oID. prefix that ldap3 rejects |
| Code | Safe? | Technique |
|---|---|---|
C |
Yes | Random case |
X |
Yes | Hex encode values |
S |
No | ldap3 DN parser rejects spaces |
Q |
No | ldap3 DN parser rejects quotes |
O |
No | ldap3 DN parser rejects oID. prefix |
The default CX chain is the safest combination for BaseDN.
Using DC=abc,DC=local with default chain CX:
DC=ab\63,DC=loca\6c
| Code | Safe? | Technique |
|---|---|---|
C |
Yes | Random case |
R |
Yes | Shuffle order |
D |
Yes | Add duplicates |
g |
Yes | Adds real random attributes (extra data returned) |
G |
No | Adds fake attributes that cause errors |
O |
No | AD rejects OID attribute names in some contexts |
W/w
|
Caution | Replaces/adds wildcard — changes what server returns |
p |
Caution | Adds operational attributes — changes what server returns |
e |
No | Replaces with empty list — breaks result parsing |
The default CR chain is the safest combination for attribute lists.
Using ['sAMAccountName', 'memberOf', 'description'] with default chain CR:
['description', 'memBerOF', 'sAMAcCountName']
| Scenario | Chain |
|---|---|
| Light evasion | --obfuscate C |
| Default (balanced) | --obfuscate |
| Heavy evasion | --obfuscate CZXNDMRB |
Use -d (debug) and --no-cache to see the actual obfuscated queries being sent:
powerview domain.local/user:pass@dc --obfuscate --no-cache -d
PV > Get-DomainUser AdministratorLook for Modified Filter:, Modified DN:, and Modified Attributes: in the debug output.
-
Results returned by obfuscated queries are functionally equivalent to non-obfuscated queries. However,
A(approximate match) ands(substring split) techniques can broaden the result set, potentially returning additional matches beyond what a standard query would produce. -
Strict LDAP server configurations may reject heavily obfuscated queries. If you encounter errors or unexpected failures with obfuscation enabled, consider using a lighter chain or testing against the target server incrementally.
-
Chain ordering matters. Some techniques depend on attribute names being in their original form, so the order of codes in the chain can affect the output.
- ldapx-py — LDAP query obfuscation library
- ldapx — Original Go LDAP proxy
- MaLDAPtive — DEF CON 32 talk on LDAP obfuscation and de-obfuscation
- Sabajete Elezaj (@sabi_elezi), Daniel Bohannon (@danielhbohannon)
- Introduction
- Installation
- Supported Authentication
- Cheatsheets
- Obfuscation
- User Defined Rules
- Public Writeups
LDAP Operations
- Get-DomainUser
- Get-DomainComputer
- Get-DomainGroup
- Get-DomainGroupMember
- Get-DomainOU
- Get-Domain
- Get-DomainController
- Get-DomainDNSRecord
- Get-DomainDNSZone
- Get-DomainObject
- Get-DomainObjectAcl
- Get-DomainObjectOwner
- Get-DomainSCCM
- Get-DomainRBCD
- Get-DomainWDS
- Get-LocalUser
- Set-DomainObject
- Set-DomainObjectDN
- Set-DomainObjectOwner
- Set-DomainUserPassword
- Set-DomainComputerPassword
- Set-DomainRBCD
- Set-DomainDNSRecord
- Add-DomainUser
- Add-DomainComputer
- Add-DomainGroup
- Add-DomainGroupMember
- Add-DomainOU
- Add-DomainGPO
- Add-DomainObjectAcl
- Add-DomainDNSRecord
- Remove-DomainUser
- Remove-DomainComputer
- Remove-DomainObject
- Remove-DomainGroupMember
- Remove-DomainOU
- Remove-DomainObjectAcl
- Remove-DomainDNSRecord
- Disable-DomainDNSRecord
- Restore-DomainObject
- Unlock-ADAccount
- Enable-ADAccount
- Disable-ADAccount
- Login-As
- Clear-Cache
Computer Enumeration
- Get-NetSession
- Get-NetShare
- Get-NetLoggedOn
- Get-RegLoggedOn
- Get-NetComputerInfo
- Get-NetTerminalSession
- Get-NetProcess
- Stop-NetProcess
- Get-EventLog
- Get-EventLogChannel
- Get-EventLogPublisher
- Get-NetService
- Start-NetService
- Stop-NetService
- Add-NetService
- Set-NetService
- Remove-NetService
- Stop-Computer
- Restart-Computer
- Remove-NetTerminalSession
- Remove-NetSession
- Logoff-Session