Report an Incident Become a Partner Careers Contact
Book a Demo
Threat Research

Two New Domain Admins And Three New Trusts: Hunting The 3AM Ransomware Playbook In Active Directory

M Malek Badawi · SOC Analyst, Level 1 6 November 2026 8 min read
Three Active Directory domains labelled School A, B and C joined by red dashed two-way trust lines, with purple tags for the new Domain Admins "library" and "svc_bkpmon", beside the headline "Two new admins, three new trusts".

Over nine nights in September, an attacker inside a UK school estate read the passwords out of its backup servers, dumped credentials from memory, created two new domain administrators and joined three separate Active Directory domains together with trusts. On the tenth morning they deleted the system-state backups and encrypted the estate. Each of those steps left a mark a SOC could have caught.

The intrusion ended with 3AM ransomware. Researchers published a detailed timeline on 3 November, and BleepingComputer reported that about 37 of nearly 50 machines were encrypted. The school isn't named, and we won't guess. This post walks through the playbook and gives Defender and Sentinel queries for each stage.

The estate and the timeline

The environment had about 47 systems: roughly 21 servers, eight domain controllers and a mix of Windows 10 and 11 workstations, spread across several separate Active Directory domains. How the attacker got in wasn't established. All times below are UTC, from the published timeline.

  • 10 September, 23:50. A modified public PowerShell script, run Base64-encoded, read the backup software's SQL database and decrypted its stored credentials with Windows DPAPI.
  • 11 September. A browser's saved-password database was copied to C:\Windows\Temp.
  • 12 September. Port tests on 445, 3389 and 5985, an attempt to add a Defender exclusion for C:\Windows\Temp, a Mimikatz download, and a list of Domain and Enterprise Admins written to da_proof.txt.
  • 13 September. A search of SYSVOL logon scripts for the names and subnets of other schools, and nltest /domain_trusts.
  • 14 September. reg save of the SECURITY and SYSTEM hives, Mimikatz (renamed sysmon64.exe), and an attempted LSASS dump through comsvcs.dll.
  • 14–15 September. Two backdoor domain admins created: library and svc_bkpmon. Finance data staged in the registry and sent out by HTTP POST.
  • 18 September. Two-way trusts created between three domains that had been separate, within about three hours.
  • 19 September. Scripts to remove the endpoint security products (blocked by anti-tamper), wbadmin delete systemstatebackup, and the Rust encryptor, C:\Windows\Temp\1\host.exe, run from 05:07.

Why the researchers think AI was driving

The researchers judged it "strongly supported" that a language model generated the commands. Failed commands were retried 40 to 101 seconds later with small changes each time. Linux habits like 2>/dev/null turned up in Windows PowerShell. Output was self-labelled, confirmation files like psexec-ok and TASK-OK were left behind, and scripts came in numbered revisions. The backup server's API was called on the wrong port with the wrong authentication, which looks like recall rather than reading the documentation. They couldn't rule out a person copying commands between the implant and a model, because the attacker's own machine was an unmanaged host they couldn't examine.

For defenders the cause matters less than the effect. The attacker was patient, noisy and repetitive, and still got through because nobody was looking at the right signals in time.

Hunting in Defender and Sentinel

These queries are starting points to tune for your environment. They're built from the published timeline. Some need the Windows Security log from domain controllers in Sentinel, which most estates collect but not all.

1. New members of the most privileged groups

SecurityEvent
| where TimeGenerated > ago(30d)
| where EventID in (4728, 4732, 4756)
| where TargetUserName in~ ("Domain Admins", "Enterprise Admins", "Administrators", "Schema Admins")
| project TimeGenerated, Computer, Group = TargetUserName, MemberAdded = MemberName, AddedBy = SubjectUserName
| order by TimeGenerated desc

A new domain admin should map to a change ticket. The account names here were chosen to blend in: one sounds like a shared library login, the other like a backup monitoring service.

2. New or changed domain trusts

SecurityEvent
| where TimeGenerated > ago(90d)
| where EventID in (4706, 4707, 4716)
| project TimeGenerated, Computer, EventID, Activity, SubjectUserName, EventData
| union (
    DeviceProcessEvents
    | where Timestamp > ago(90d)
    | where ProcessCommandLine has_any ("netdom trust", "New-ADTrust", "CreateLocalSideOfTrustRelationship", "nltest /domain_trusts")
    | project TimeGenerated = Timestamp, Computer = DeviceName, ProcessCommandLine, AccountName)

Trusts change rarely, so any 4706 (trust created) deserves a question. Joining domains that were deliberately kept apart is how this attacker turned one school's compromise into several.

3. Credentials read out of the backup server

DeviceEvents
| where Timestamp > ago(30d)
| where ActionType == "PowerShellCommand"
| extend Cmd = tostring(parse_json(AdditionalFields).Command)
| where Cmd has_any ("ProtectedData", "Unprotect") and Cmd has_any ("Credentials", "VeeamBackup", "dbo.")
| project Timestamp, DeviceName, AccountName, Cmd
| union (
    DeviceProcessEvents
    | where Timestamp > ago(30d)
    | where FileName in~ ("powershell.exe", "pwsh.exe") and ProcessCommandLine has_any ("-enc", "-EncodedCommand")
    | where InitiatingProcessFileName in~ ("wmiprvse.exe", "services.exe")
    | project Timestamp, DeviceName, AccountName, Cmd = ProcessCommandLine)

The researchers recommend alerting on any credential-reading access to backup software databases. The second half catches encoded PowerShell launched remotely through WMI or a service, which is how the script was delivered.

4. LSASS dumps and registry hive saves

DeviceProcessEvents
| where Timestamp > ago(30d)
| where (ProcessCommandLine has "comsvcs" and ProcessCommandLine has "MiniDump")
   or (FileName =~ "reg.exe" and ProcessCommandLine has "save"
       and ProcessCommandLine has_any (@"\SAM", @"\SECURITY", @"\SYSTEM"))
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName

Outside your backup tooling, nothing legitimate saves the SECURITY hive. See our explainer on Mimikatz for what attackers do with these files.

5. Defence tampering and backup deletion

DeviceProcessEvents
| where Timestamp > ago(30d)
| where ProcessCommandLine has_any ("Set-MpPreference -ExclusionPath", "Add-MpPreference -ExclusionPath",
                                    "delete systemstatebackup", "delete catalog", "shadowcopy delete")
   or (FileName =~ "netsh.exe" and ProcessCommandLine has "Network Discovery" and ProcessCommandLine has "enable=Yes")
| project Timestamp, DeviceName, AccountName, ProcessCommandLine

6. The attacker's own markers

DeviceFileEvents
| where Timestamp > ago(30d)
| where FileName in~ ("da_proof.txt", "psx_mark.txt", "prx_go.cmd", "prx.txt", "svc_data.txt", "svc_test.ps1", "crackw.py", "av_remove.ps1", "av_remove2.ps1", "av_remove3.ps1")
   or FolderPath has @"\Windows\Temp\1\host.exe"
   or (FolderPath startswith @"C:\Windows\Temp" and FileName in~ ("sysmon64.exe", "svcstat.exe", "ls.dmp"))
| project Timestamp, DeviceName, FolderPath, FileName, InitiatingProcessCommandLine

Names like these change between intrusions, so treat a hit as confirmation rather than relying on them for detection.

7. Logons from machines you don't manage

let managedIPs = DeviceNetworkInfo
| where Timestamp > ago(7d)
| mv-expand ip = parse_json(IPAddresses)
| summarize by IP = tostring(ip.IPAddress);
SecurityEvent
| where TimeGenerated > ago(7d)
| where EventID == 4624 and LogonType in (3, 10)
| where IpAddress !in (managedIPs) and IpAddress !in ("-", "127.0.0.1", "::1")
| summarize Logons = count(), Accounts = make_set(TargetUserName, 10), Targets = make_set(Computer, 10) by IpAddress
| order by Logons desc

The encryption was pushed from an unmanaged host, so it never showed up in endpoint telemetry. Network logons from addresses with no onboarded device behind them point to exactly that kind of blind spot.

What would have stopped it

  • Treat backup servers as Tier 0. They hold credentials for everything they back up. Restrict who can log on to them, monitor their databases, and keep at least one copy of backups immutable and offline from the domain.
  • Keep domains separate on purpose. Don't reuse privileged credentials across domains, and alert on any new trust.
  • Harden LSASS. Turn on Credential Guard, LSA protection and the attack surface reduction rule that blocks credential stealing from LSASS.
  • Close remote execution paths. Restrict WMI, remote registry, scheduled task creation and admin shares to the management hosts that need them.
  • Put an agent on everything. Every unmanaged Windows machine on the network is somewhere an attacker can work unseen.
  • Keep anti-tamper on. In this case it stopped the attacker removing endpoint protection. It didn't stop the encryptor, but it kept the detection running.

How a managed SOC helps

  • Nine days is a long time to be unseen. The new domain admins alone should have triggered an investigation within the hour. Our SOCs are staffed 24/7, and senior analyst sign-off is the default on the managed service.
  • Directory changes treated as incidents. We watch privileged group changes, new trusts and credential access on backup infrastructure across Defender and Sentinel, not only malware alerts.
  • Help when it does happen. Our incident response team scopes the intrusion, and our compromise assessment checks whether anyone is still inside.

If you'd like us to check when your Domain Admins group last changed, and who changed it, book a demo or talk to our team.

Threat Research3AM RansomwareRansomwareActive DirectoryDomain TrustsMimikatzBackup SecurityCredential DumpingMicrosoft DefenderMicrosoft SentinelKQLThreat Hunting

Ready to see the agents work?

Book a demo of CYBERSHIELD AI against a real scenario.