Back to Feed
Threat IntelligenceAug 11, 2026

Project CAV3RN continues: Google Apps Script as C2 relay and DNS-based C2 channel selection

Project CAV3RN uses Google Apps Script as C2 relay and DNS for C2 channel selection.

Summary

Project CAV3RN, an espionage framework targeting Israel, has evolved with new C2 capabilities. It now employs a complex module that uses DNS A-record responses to dynamically switch between a direct HTTPS channel and a Google Apps Script relay. This allows operators to rotate the Google channel and blend C2 traffic with legitimate Google services for evasion.

Full text

Table of Contents Multi-transport C2 communication moduleGoogle Apps Script channelDirect HTTPS channelInter-component DLL brokerInfrastructureConclusionsIndicators of compromiseFile hashesDomains and IPs Authors GReAT Project CAV3RN is a modular espionage framework used against targets in Israel. This report expands on two earlier publications: the first was published in June 2026 as part of our Kaspersky Threat Intelligence Reporting service, and the second was published on Securelist the following month, further documenting the framework’s evolving architecture and C2 capabilities. Continued tracking of this cluster in early August 2026 uncovered several previously undocumented components that expanded the framework’s communication and orchestration capabilities. The main finding is a complex C2 module that uses DNS A-record responses to choose between direct HTTPS and a Google Apps Script relay for each transaction. The same DNS infrastructure can validate and replace the relay deployment ID, allowing the operator to rotate the Google channel. We also identified the framework’s local broker, which discovers and loads DLL components, routes messages between them, and supports runtime upgrades. Multi-transport C2 communication module The communication module, GoogleService.dll, is a 64-bit DLL compiled with Microsoft .NET 8 NativeAOT. Its PDB path is: C:\Users\user\Desktop\Modules\broker-cavern\communication\GoogleCommunication\bin\Release\net8.0\win-x64\native\GoogleService.pdb 1 C:\Users\user\Desktop\Modules\broker-cavern\communication\GoogleCommunication\bin\Release\net8.0\win-x64\native\GoogleService.pdb NativeAOT data also revealed references to eight source files, including the Direct.cs, FindMode.cs, and Google.cs. The DLL exports GroupByCategory, CheckAvailability, IsPrimeNumber, and OrderByDate. During initialization, its host (local broker) registers the module’s callback and starts CheckAvailability. After three seconds, the module sends a type-0 frame to the fixed identifier 33A4BA78-E286-4FF2-85EC-7365265F3D93. The broker returns Err1::33A4BA78-E286-4FF2-85EC-7365265F3D93, which the module expects and uses to learn the broker’s name before starting its C2 worker. C2 packets contain type, cid, and payload fields. Packets of the type icmgdd are processed by the communication module itself, while other types, including broker, are forwarded to the local broker. Within command payloads, _;;_ separates the command from its arguments and _,_ separates individual arguments. At startup, the worker internally sends: {"type":"icmgdd","cid":0,"payload":"s_version_;;_"} 1 {"type":"icmgdd","cid":0,"payload":"s_version_;;_"} The s_version handler enumerates DLLs under AppContext.BaseDirectory, collects their company names and versions, and appends the communication module’s name/version and the local broker’s name. This inventory is serialized as JSON, XORed with 0xAC, Base64-encoded, and sent as the module’s initial C2 report. The module supports five internal commands: Command Functionality s_version Returns the DLL-version inventory described above. The command is executed automatically at startup. s_config Returns the active configuration and, when provided with a JSON configuration object, replaces it in memory. s_enLog Enables diagnostic logging at the Debug level. s_deLog Disables diagnostic logging and sets the logging level to Fatal. s_write Base64-decodes and GZip-decompresses provided data before writing it to the specified file path. The module reads conf.json from the process’s current working directory. If it is missing, the module generates a seven-character client identifier and writes its embedded defaults to disk. { "to": "<generated seven-character ID>", // Client ID "ad": "https://api.studiotikva.com/api/v1/update/check", // Direct C2 URL "ho": "studiotikva.com", // DNS domain "gi": "<redacted>", // Apps Script deployment ID "de": false, // Enable Debug logging at startup "mi": 120000, // Poll-delay reset after a non-empty response "ma": 18000000, // Progressive poll-delay cap "ri": 30000, // Base DNS recovery/error delay, with positive jitter "ga": "s3criitC0d3/8-)B-,)", // Apps Script relay authentication key "gu": "https://script.google.com/macros/s/{0}/exec", "ua": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31", "mcc": 50, // unknown "mtc": 10 // unknown } 123456789101112131415 { "to": "<generated seven-character ID>", // Client ID "ad": "https://api.studiotikva.com/api/v1/update/check", // Direct C2 URL "ho": "studiotikva.com", // DNS domain "gi": "<redacted>", // Apps Script deployment ID "de": false, // Enable Debug logging at startup "mi": 120000, // Poll-delay reset after a non-empty response "ma": 18000000, // Progressive poll-delay cap "ri": 30000, // Base DNS recovery/error delay, with positive jitter "ga": "s3criitC0d3/8-)B-,)", // Apps Script relay authentication key "gu": "https://script.google.com/macros/s/{0}/exec", "ua": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31", "mcc": 50, // unknown "mtc": 10 // unknown} The s_config command can replace these settings in memory but does not update the file. DNS recovery is the exception: a recovered Apps Script deployment ID is written back to conf.json. Before polling for commands or sending a result, the module performs a DNS A-record query to select Direct HTTPS or Google Apps Script: <random nonce><error state>.<hex-encoded client ID>.m.studiotikva.com The first label combines a three- or four-character uppercase alphanumeric nonce with the current error state: 0 for None, 1 for GIDFailed, 2 for GoogleFailed, and 3 for DirectFailed. Each new transaction starts in state 0. The exact response 12.19.29[.]30 is treated as a rejection. Other responses are interpreted according to their fourth octet: Fourth octet None (0) GIDFailed (1) GoogleFailed (2) DirectFailed (3) 120 (0x78) Google Apps Script Direct HTTPS Direct HTTPS Google Apps Script 130 (0x82) Direct HTTPS Direct HTTPS Direct HTTPS Close the transaction (no channel) 140 (0x8C) Exception Exception Exception Exception All other values Google Apps Script Google Apps Script Google Apps Script Google Apps Script During analysis, valid .m queries returned 12.121.234[.]120, while malformed queries returned 12.19.29[.]30. For example, YCZ2.41414141303030.m.studiotikva[.]com carries state 2, so the final octet 120 selects Direct HTTPS. CAV3RN DNS control-plane response: the final octet 120 selects the direct HTTPS channel When Google mode is selected, the module calculates the MD5 digest of its stored deployment ID and compares its first four bytes with the A record returned by <random5>.<hex-ID>.q.studiotikva[.]com. A mismatch causes the module to retrieve a replacement through .p queries: <random5>.<hex-ID>.p.studiotikva[.]com. DNS-based deployment-ID freshness check The offset-0 response contains a one-byte length followed by the first three ID bytes. Each subsequent response contributes four bytes. The observed response 74.65.75.102 represents 4A 41 4B 66: a length of 74 followed by AKf. The DLL stops after collecting the declared length and discards the final padding byte rather than requesting offset 76. DNS recovery of the Google Apps Script deployment ID: the offset-0 response contains the length byte and first three ID characters, followed by four-byte continuation chunks One initial response and 18 continuation responses produced a 74-character deployment ID, shown redacted as AKfycby46v0DPSEKWYa****dvQ. The .q response 247.188.216[.]122 contains the bytes f7 bc d8 7a, matching the first four MD5 bytes of the recovered value. This is a 32-bit freshness check. Wireshark capture showing the .p query sequence used for chunked retrieval of the Google Apps Script deployment ID Google Apps Script channel When DNS selects Google mode, the module inserts the deployment ID into https://script.g

Indicators of Compromise

  • domain — studiotikva.com
  • url — https://api.studiotikva.com/api/v1/update/check
  • hash_sha256 — 1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
  • mitre_attack — T1071.001
  • mitre_attack — T1102.002
  • mitre_attack — T1001
  • mitre_attack — T1059.003

Entities

Project CAV3RN (threat_actor)Google Apps Script (product).NET NativeAOT (technology)Google (vendor)Microsoft (vendor)