TWINLOOT: Microsoft 365 as C2
Ontinue's TWINLOOT analysis Living Off the Cloud: A Python Implant Hiding Its Entire C2 Inside Microsoft 365 & Azure describes a Python implant delivered through Teams. It uses a headless Edge to make Graph requests to an attacker-controlled SharePoint Online site, and a reverse SOCKS5 tunnel can use Teams TURN for interactive access. A direct TLS/WebSocket tunnel to attacker infra is also supported. Ontinue observed NTUSER.MAN persistence in one instance and recovered three other persistence options. In this post I'll assume you've already read the research and focus on analysis of TWINLOOT behaviors by mapping to detection rules and audit events.
Useful Catalog Matches
To hunt for external help desk impersonation, the Elastic rule M365 Teams Rogue Help Desk Chat Created can likely be adapted for use here. It uses the ChatCreated audit operation and o365.audit.ParticipantInfo.HasForeignTenantUsers field:
The Sigma rule Potential Data Stealing Via Chromium Headless Debugging looks for --remote-debugging, --user-data-dir, and --headless together in the command line.
You can find a related rule with a generic query like this:type:rule headless chromiumT1105 Ingress Tool TransferT1564.003 Hide Artifacts: Hidden WindowT1105 Ingress Tool TransferT1564.003 Hide Artifacts: Hidden WindowT1185 Browser Session HijackingT1564.003 Hide Artifacts: Hidden WindowT1059 Command and Scripting InterpreterT1105 Ingress Tool TransferT1497 Virtualization/Sandbox Evasion
Next, the TA abuses a neat feature known as Mandatory User Profiles. Quick plug: we have a KQL lab that uses this persistence technique! Anyway, there are a few rules that can help detect this.
The Elastic Defend rule Potential Persistence via Mandatory User Profile detects creation or modification of NTUSER.MAN, and you may be able to do this with your EDR. Note that this rule excludes the SID S-1-5-18 (SYSTEM).
The Sigma rule Potentially Suspicious Image Load of Offreg.dll might also be useful. However, note the excluded locations where legitimate programs are installed. It keys on Sysmon Event ID 7: Image loaded and fields like Image and ImageLoaded:field:ImageLoaded value:offreg.dllT1112 Modify RegistryImageLoaded ends_with \offreg.dll
Finally, Panos Gkatziroulis recently pointed out that User Profiles Service Event ID 5: Registry file is loaded (inspect File for a path ending in NTUSER.man) and Event ID 67 can help detect mandatory profile loading (check the ProfileType field for a mandatory profile). One approach to observe this technique is to correlate offreg.dll image loads, creation of NTUSER.MAN, and subsequent profile loading.
Moving on, Ontinue recovered code implementing the Ghost Scheduled Task technique (here is a handy explanation of the technique in the original repo) which writes task data directly to the TaskCache registry key. The query value:TaskCache has the rule Scheduled TaskCache Change by Uncommon Program as one of its results, which maps to Sysmon Event ID 13: RegistryEvent (Value Set). [Sysmon Event ID 12] is also complementary, although it isn't used in this rule. Here is that rule:
Another result is the Elastic Defend rule Suspicious Scheduled Task Registry Modification, which requires call stack enrichment.
Conclusion
TWINLOOT uses a legitimate Python runtime and shifts Graph traffic into Edge, which makes it challenging to detect. The Graph transport creates a process attribution gap for detections that expect Python to connect directly to Graph. The Sigma rule Python Initiated Connection can match Python-initiated authentication, tunnel, or internal connections, but it doesn't match Graph connections initiated by Edge. Elastic Defend's rule Connection to WebService by an Unsigned Binary requires a process without a trusted signature and includes SharePoint in its DNS list.
To overcome these challenges, Rhys has already made many excellent recommendations in the original report. Take a look!
Thanks for reading.
References
Ontinue - Living Off the Cloud: A Python Implant Hiding Its Entire C2 Inside Microsoft 365 & Azure
netero1010/GhostTask - Ghost Scheduled Task
Panos Gkatziroulis - Mandatory User Profile
Microsoft Learn - Mandatory User Profiles