Introduction: "When Ransomware Eats Your Forest"

Active Directory (AD) is like the central nervous system of an organization. One wrong move, and the body seizes up. In my case, ransomware fried the old forest, leaving me with busted domain controllers and zero trust in what was left.

Fortunately, I still had my synced objects in Entra ID (formerly Azure AD). The challenge: could I rebuild a brand-new forest using nothing but the cloud?

Spoiler: yes, but it was part archaeology, part neurosurgery, and part comedy of errors.

Step 1: Exporting from Entra

I quickly realized that Export-Clixml wasn't the silver bullet. Entra objects don't translate neatly into AD. Instead, I leaned on the Microsoft Graph PowerShell SDK and custom scripts to dump:

  • Users (UPN, ImmutableID, proxyAddresses, departments, etc.)
  • Groups (including memberships)
  • Exchange Online attributes (mail, alias, targetAddress, etc.)

⚡ Tip: Don't export everything at once. My first attempt gave me ~900 users, half of them disabled. I refined my export to a specific group of ~200 users who actually needed to exist in AD again. This kept my test cycles fast and my mistakes contained.

Step 2: Seeding the New Forest

With a new forest in place, I wrote a script (Seed-NewAD.ps1) to generate user objects from my CSVs.

Discoveries along the way:

  • PowerShell 5 hates inline ?: syntax. My script broke until I rewrote ternary logic as proper if blocks.
  • Some attributes (like mailNickname) aren't valid for New-ADUser. I had to check the schema and only populate what AD actually accepts.
  • PostalCode and ProxyAddresses are available, but only on update, not creation.

⚡ Tip: Build a schema support cache in your script (Get-ADObject -SearchBase $schemaNamingContext). That way, you can programmatically test if an attribute exists before writing it.

Step 3: Hard Match Magic (msDS-ConsistencyGuid)

This was the breakthrough. To sync existing Entra users with my new AD users, I needed hard match:

  • Entra uses ImmutableID (a base64-encoded GUID).
  • AD uses msDS-ConsistencyGuid (a raw byte array).
  • I converted Entra's ImmutableID back to a byte array and stamped it into AD.

💡 Gotcha: PowerShell exposes this attribute as mS-DS-ConsistencyGuid (note the casing). You can only update it reliably with Set-ADObject and the literal name. After that, Entra Connect was able to map users one-to-one.

Step 4: Groups, Memberships, and Alternative Approaches

Groups were trickier. My first attempt to re-import them created new groups in Entra instead of mapping to the old ones. That's because I hadn't stamped the msDS-ExternalDirectoryObjectId.

Real-World Plot Twist

While I was planning the Group Writeback approach below, my customer needed a faster solution for managing orphaned groups. We ended up using the sync disable/enable method instead (see the Project Update section above). However, I'm keeping the Group Writeback information here as it's still a valid technical approach for other scenarios.

Group Writeback Approach (Alternative Method):

  • Enable Group Writeback in Entra Connect.
  • Let Entra push existing groups down into a dedicated OU in AD.
  • Flip the source-of-authority (SOA) later, so I manage them from AD again.

⚡ Tip: Always stage group work in a separate OU. If you mess up, you can roll it back without touching production groups.

Step 5: Password Hash Sync (PHS) Confusion

This was the rabbit hole. Every blog I found swore there had to be a DLL called AzureADPasswordProtectionDCP.dll in System32. I tore my servers apart looking for it. It wasn't there.

Turns out: modern Entra Connect Sync doesn't use that DLL anymore. The password sync logic lives entirely inside the sync engine's assemblies (Microsoft.Online.PasswordSynchronization.*).

Real blockers I hit:

  • "User must change password at next logon" flag → If that's set, PHS ignores the password. Resetting with that flag disabled fixed it.
  • Missing replication rights → The ADSync service account needs Replicating Directory Changes (All). Without it, no passwords.
  • Wrong logs → Password events are under Applications and Services Logs → Microsoft → AzureADConnect, not the old Directory Synchronization → PasswordSync.

⚡ Tip: Enable verbose password sync logging

reg add "HKLM\SOFTWARE\Microsoft\Azure AD Sync\PasswordHashSync" /v VerboseLogging /t REG_DWORD /d 1 /f
Restart-Service ADSync

Step 6: Password Write-Back

Getting PHS working was half the battle. Write-back (cloud → on-prem) had its own requirements:

  • Enabled both in AADC wizard and Entra tenant password reset settings.
  • Connector account delegated Reset password, Write lockoutTime, Write pwdLastSet, Write userAccountControl.
  • Write-back doesn't work in Staging Mode.
  • AD password policy is enforced → if Entra accepts a password but AD rejects it, write-back fails.

⚡ Tip: If you get "Access Denied" errors, check with dsacls. The fastest way is to delegate control on the OU → "Reset user passwords and force password change at next logon." Then clear the flag with Set-ADUser -ChangePasswordAtLogon $false.

Lessons Learned (a.k.a. "Don't Do What I Did")

  • Don't chase ghost DLLs — check the product version before believing blog posts.
  • Always pilot with a handful of users in a controlled OU. CSV subsets saved me from syncing garbage.
  • Remember that Exchange attributes (aliases, targetAddress) must be exported from Exchange Online separately.
  • Sometimes the simplest solution wins — Group Writeback was technically correct, but the sync disable/enable method was faster and met the customer's urgent needs.
  • The "must change password" flag silently kills PHS. Check it first.
  • Customer timelines matter — don't get too attached to a technical approach if business needs require a different solution.
  • Document both approaches — what didn't get implemented this time might be perfect for the next project.

Project Update: The Faster Path

While the Group Writeback approach I outlined above was technically sound, my customer needed a faster solution to manage orphaned groups in the cloud. Before we had a chance to fully implement and test Group Writeback, they decided to go with a more direct approach.

The Solution We Actually Implemented

Instead of using Group Writeback, we went with the sync disable/enable method I describe in my Active Directory to Entra ID Migration article:

  1. Temporarily disabled synchronization in Entra ID
  2. Re-enabled synchronization
  3. Cleaned up connector space errors

Result: Objects that don't exist in on-premises AD became manageable cloud-only objects in Entra ID and Exchange Online.

⚡ Why this worked better: It was faster to implement, required no additional Entra Connect configuration changes, and gave immediate results. The customer could start managing their orphaned groups right away instead of waiting for Group Writeback testing and configuration.

The End: Rising from the Ashes

In the end, I was able to rebuild a dead forest using Entra as my source of truth:

  • Users recreated with ImmutableIDs matching cloud identities.
  • Groups and orphaned objects converted to cloud-only management using the sync disable/enable method.
  • Password hash sync and write-back working like new.
  • A new appreciation for how much misinformation exists about AADC internals.
  • Sometimes the simplest solution (temporarily disabling sync) works better than complex workarounds.

I went in thinking this would be a "click, export, import" weekend job. Instead, it was an adventure full of scripting, schema spelunking, and a few laughs when I realized the DLL I'd been hunting for doesn't even exist anymore.

But hey — the forest is back, my users are happy, orphaned groups are manageable again, and I have a story worth telling.

Ofir Gavish

Ofir Gavish

Microsoft MVP | Senior Cloud Solutions Architect specializing in Microsoft 365, Azure, and enterprise disaster recovery. When not rebuilding forests from the ashes, I enjoy documenting the journey for fellow cloud ninjas.

Share this article

Related Articles