{
	"id": "c1c41893-f1a3-482c-aef3-a725c222d256",
	"created_at": "2026-04-06T00:21:03.195053Z",
	"updated_at": "2026-04-10T03:32:21.608829Z",
	"deleted_at": null,
	"sha1_hash": "fbb13800d3dc24e4ce7f42b58f7fa88be781ebef",
	"title": "DodgeBox | ThreatLabz",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 1192224,
	"plain_text": "DodgeBox | ThreatLabz\r\nBy Yin Hong Chang, Sudeep Singh\r\nPublished: 2024-07-10 · Archived: 2026-04-05 14:40:16 UTC\r\nTechnical Analysis\r\nAttack chain\r\nAPT41 employs DLL sideloading as a means of executing DodgeBox. They utilize a legitimate executable\r\n(taskhost.exe), signed by Sandboxie, to sideload a malicious DLL (sbiedll.dll). This malicious DLL, DodgeBox,\r\nserves as a loader and is responsible for decrypting a second stage payload from an encrypted DAT file\r\n(sbiedll.dat). The decrypted payload, MoonWalk functions as a backdoor that abuses Google Drive for command-and-control (C2) communication. The figure below illustrates the attack chain at a high level.\r\nFigure 1: Attack chain used to deploy the DodgeBox loader and MoonWalk backdoor.\r\nDodgeBox analysis\r\nhttps://www.zscaler.com/blogs/security-research/dodgebox-deep-dive-updated-arsenal-apt41-part-1\r\nPage 1 of 8\n\nDodgeBox, a reflective DLL loader written in C, showcases similarities to StealthVector in terms of concept but\r\nincorporates significant improvements in its implementation. It offers various capabilities, including decrypting\r\nand loading embedded DLLs, conducting environment checks and bindings, and executing cleanup procedures.\r\nWhat sets DodgeBox apart from other malware is its unique algorithms and techniques.\r\nDuring our threat hunting activities, we came across two DodgeBox samples that were designed to be sideloaded\r\nby signed legitimate executables. One of these executables was developed by Sandboxie ( SandboxieWUAU.exe ),\r\nwhile the other was developed by AhnLab. All exports within the DLL point to a single function that primarily\r\ninvokes the main function of the malware, as illustrated below:\r\nvoid SbieDll_Hook()\r\n{\r\n if ( dwExportCalled )\r\n {\r\n Sleep(0xFFFFFFFF);\r\n }\r\n else\r\n {\r\n hSbieDll_ = hSbieDll;\r\n dwExportCalled = 1;\r\n MalwareMain();\r\n }\r\n}\r\nMalwareMain implements the main functionality of DodgeBox, and can be broken down into three main phases:\r\n1. Decryption of DodgeBox’s configuration\r\nDodgeBox employs AES Cipher Feedback (AES-CFB) mode for encrypting its configuration. AES-CFB\r\ntransforms AES from a block cipher into a stream cipher, allowing for the encryption of data with different lengths\r\nwithout requiring padding. The encrypted configuration is embedded within the  .data section of the binary. To\r\nensure the integrity of the configuration, DodgeBox utilizes hard-coded MD5 hashes to validate both the\r\nembedded AES keys and the encrypted configuration. For reference, a sample of DodgeBox's decrypted\r\nconfiguration can be found in the Appendix section of this blog. We will reference this sample configuration using\r\nthe variable  Config in the following sections.\r\n2. Execution guardrails and environment setup\r\nAfter decrypting its configuration, DodgeBox performs several environment checks to ensure it is running on its\r\nintended target.\r\nExecution guardrail: Argument check\r\nDodgeBox starts by verifying that the process was launched with the correct arguments. It scans the  argv\r\nparameter for a specific string defined in  Config.szArgFlag . Next, it calculates the MD5 hash of the subsequent\r\nhttps://www.zscaler.com/blogs/security-research/dodgebox-deep-dive-updated-arsenal-apt41-part-1\r\nPage 2 of 8\n\nargument and compares it to the hash specified in  Config.rgbArgFlagValueMD5 . In this case, DodgeBox expects\r\nthe arguments to include  --type driver . If this verification check fails, the process is terminated.\r\nEnvironment setup: API Resolution\r\nAfterwards, DodgeBox proceeds to resolve multiple APIs that are utilized for additional environment checks and\r\nsetup. Notably, DodgeBox employs a salted FNV1a hash for DLL and function names. This salted hash\r\nmechanism aids DodgeBox in evading static detections that typically search for hashes of DLL or function names.\r\nAdditionally, it enables different samples of DodgeBox to use distinct values for the same DLL and function, all\r\nwhile preserving the integrity of the core hashing algorithm.\r\nThe following code shows DodgeBox calling its  ResolveImport function to resolve the address of  LdrLoadDll ,\r\nand populating its import table.\r\n// ResolveImport takes in (wszDllName, dwDllNameHash, dwFuncNameHash)\r\nsImportTable-\u003entdll_LdrLoadDll = ResolveImport(L\"ntdll\",0xFE0B07B0,0xCA7BB6AC);\r\nInside the ResolveImport function, DodgeBox utilizes the FNV1a hashing function in a two-step process. First,\r\nit hashes the input string, which represents a DLL or function name. Then, it hashes a salt value separately. This\r\ntwo-step hashing procedure is equivalent to hashing the concatenation of the input string and salt. The following\r\npseudo-code represents the implementation of the salted hash:\r\ndwHash = 0x811C9DC5; // Standard initial seed for FNV1a\r\npwszInputString_Char = pwszInputString;\r\ncchInputString = -1LL;\r\ndo\r\n ++cchInputString;\r\nwhile ( pwszInputString[cchInputString] );\r\npwszInputStringEnd = (pwszInputString + 2 * cchInputString);\r\nif ( pwszInputString\r\nA Python script to generate the salted hashes is included in the Appendix.\r\nIn addition to the salted hash implementation, DodgeBox incorporates another noteworthy feature in\r\nits  ResolveImport function. This function accepts both the DLL name as a string and its hash value as\r\narguments. This redundancy appears to be designed to provide flexibility, allowing DodgeBox to handle scenarios\r\nwhere the target DLL has not yet been loaded. In such cases, DodgeBox invokes the  LoadLibraryW function with\r\nthe provided string to load the DLL dynamically.\r\nFurthermore, DodgeBox effectively handles forwarded exports and exports by ordinals. It\r\nutilizes  ntdll!LdrLoadDll and  ntdll!LdrGetProcedureAddressEx when necessary to resolve the address of the\r\nexported function. This approach ensures that DodgeBox can successfully resolve and utilize the desired\r\nfunctions, regardless of the export method used.\r\nEnvironment setup: DLL unhooking\r\nhttps://www.zscaler.com/blogs/security-research/dodgebox-deep-dive-updated-arsenal-apt41-part-1\r\nPage 3 of 8\n\nOnce DodgeBox has resolved the necessary functions, it proceeds to scan and unhook DLLs that are loaded from\r\nthe System32 directory. This process involves iterating through the  .pdata section of each DLL, retrieving each\r\nfunction’s start and end addresses, and calculating an FNV1a hash for the bytes of each function. DodgeBox then\r\ncomputes a corresponding hash for the same function's bytes as stored on disk. If the two hashes differ, potential\r\ntampering can be detected, and DodgeBox will replace the in-memory function with the original version from the\r\ndisk.\r\nFor each DLL that has been successfully scanned, DodgeBox marks the corresponding  LDR_DATA_TABLE_ENTRY\r\nby clearing the  ReservedFlags6 field and setting the upper bit to 1. This marking allows DodgeBox to avoid\r\nscanning the same DLL twice.\r\nEnvironment setup: Disabling CFG\r\nFollowing that, DodgeBox checks if the operating system is Windows 8 or newer. If so, the code verifies whether\r\nControl Flow Guard (CFG) is enabled by calling  GetProcessMitigationPolicy with\r\nthe  ProcessControlFlowGuardPolicy parameter. If CFG is active, the malware attempts to disable it.\r\nTo achieve this, DodgeBox locates the  LdrpHandleInvalidUserCallTarget function within  ntdll.dll by\r\nsearching for a specific byte sequence. Once found, the malware patches this function with a simple  jmp rax\r\ninstruction:\r\nntdll!LdrpHandleInvalidUserCallTarget:\r\n00007ffe`fc8cf070 48ffe0 jmp rax\r\n00007ffe`fc8cf073 cc int 3\r\n00007ffe`fc8cf074 90 nop\r\nCFG verifies the validity of indirect call targets. When a CFG check fails,  LdrpHandleInvalidUserCallTarget is\r\ninvoked, typically raising an interrupt. At this point, the rax register contains the invalid target address. The patch\r\nmodifies this behavior, calling the target directly instead of raising an interrupt, thus bypassing CFG protection.\r\nIn addition, DodgeBox replaces  msvcrt!_guard_check_icall_fptr\r\nwith  msvcrt!_DebugMallocator::~_DebugMallocator , a function that returns 0 to disable the CFG check\r\nperformed by  msvcrt .\r\nExecution guardrail: MAC, computer name, and user name checks\r\nFinally, DodgeBox performs a series of checks to verify if it is configured to run on the current machine. The\r\nmalware compares the machine’s MAC address against  Config.rgbTargetMac , and compares the computer name\r\nagainst  Config.wszTargetComputerName . Depending on the  Config.fDoCheckIsSystem flag, DodgeBox checks\r\nwhether it is running with  SYSTEM privileges. If any of these checks fail, the malware terminates execution.\r\n3. Payload decryption and environment keying\r\nPayload decryption\r\nhttps://www.zscaler.com/blogs/security-research/dodgebox-deep-dive-updated-arsenal-apt41-part-1\r\nPage 4 of 8\n\nIn the final phase, DodgeBox commences the decryption process for the MoonWalk payload DAT file. The code\r\nstarts by inspecting the first four bytes of the file. If these bytes are non-zero, it signifies that the DAT file has\r\nbeen tied to a particular machine, (which is described below). However, if the DAT file is not machine-specific,\r\nDodgeBox proceeds to decrypt the file using AES-CFB encryption, utilizing the key parameters stored in the\r\nconfiguration file. In the samples analyzed by ThreatLabz, this decrypted DAT file corresponds to a DLL, which is\r\nthe MoonWalk backdoor.\r\nEnvironment keying of the payload\r\nAfter the decryption process, DodgeBox takes the additional step of keying the payload to the current machine. It\r\naccomplishes this by re-encrypting the payload using the Config.rgbAESKeyForDatFile key. However, in this\r\nspecific scenario, the process deviates from the configuration file's IV (Initialization Vector). Instead, it utilizes the\r\nMD5 hash of the current machine's GUID as the AES IV. This approach guarantees that the decrypted DAT file\r\ncannot be decrypted on any other machine, thus enhancing the payload's security.\r\nLoading the payload using DLL hollowing\r\nNext, DodgeBox reflectively loads the payload using a DLL hollowing technique. At a high level, the process\r\nbegins with the random selection of a host DLL from the  System32 directory, ensuring it is not on a blocklist\r\n(DLL blocklist available in the Appendix section) and has a sufficiently large .text section. A copy of this DLL is\r\nthen created at  C:\\Windows\\Microsoft.NET\\assembly\\GAC_MSIL\\System.Data.Trace\\v4.0_4.0.0.0__\\.dll .\r\nDodgeBox modifies this copy by disabling the NX flag, removing the  reloc and  TLS sections, and patching its\r\nentry point with a simple  return 1 .\r\nFollowing the preparation of the host  DLL for injection, DodgeBox proceeds by zeroing the PE headers, and\r\nthe  IMAGE_DATA_DIRECTORY structures corresponding to the  import ,  reloc , and  debug directories of the\r\npayload DLL. This modified payload DLL is then inserted into the previously selected host DLL. The resulting\r\ncopy of the modified host DLL is loaded into memory using the  NtCreateSection and  NtMapViewOfSection\r\nAPIs.\r\nOnce the DLL is successfully loaded, DodgeBox updates the relevant entries in the Process Environment Block\r\n(PEB) to reflect the newly loaded DLL. To further conceal its activities, DodgeBox overwrites the modified copy\r\nof the host DLL with its original contents, making it appear as a legitimate, signed DLL on disk. Finally, the\r\nmalware calls the entrypoint of the payload DLL.\r\nInterestingly, if the function responsible for DLL hollowing fails to load the payload DLL, DodgeBox employs a\r\nfallback mechanism. This fallback function implements a traditional form of reflective DLL loading\r\nusing  NtAllocateVirtualMemory and  NtProtectVirtualMemory .\r\nAt this stage, the payload DLL has been successfully loaded, and control is transferred to the payload DLL by\r\ninvoking the first exported function.\r\nCall stack spoofing\r\nThere is one last technique employed by DodgeBox throughout all three phases discussed above: call stack\r\nspoofing. Call stack spoofing is employed to obscure the origins of API calls, making it more challenging for\r\nhttps://www.zscaler.com/blogs/security-research/dodgebox-deep-dive-updated-arsenal-apt41-part-1\r\nPage 5 of 8\n\nEDRs and antivirus systems to detect malicious activity. By manipulating the call stack, DodgeBox makes API\r\ncalls appear as if they originate from trusted binaries rather than the malware itself. This prevents security\r\nsolutions from gaining contextual information about the true source of the API calls.\r\nDodgeBox specifically utilizes call stack spoofing when invoking Windows APIs that are more likely to be\r\nmonitored. As an example, it directly calls  RtlInitUnicodeString , a Windows API that only performs string\r\nmanipulation, instead of using stack spoofing.\r\n(sImportTable-\u003entdll_RtlInitUnicodeString)(v25, v26);\r\nHowever, call stack spoofing is used when calling NtAllocateVirtualMemory, an API known to be abused by\r\nmalware, as shown below:\r\nCallFunction(\r\n sImportTable-\u003entdll_NtAllocateVirtualMemory, // API to call\r\n 0, // Unused\r\n 6LL, // Number of parameters\r\n // Parameters to the API\r\n -1LL, \u0026pAllocBase, 0LL, \u0026dwSizeOfImage, 0x3000, PAGE_READWRITE)\r\nThe technique mentioned above can be observed in the figures below. In the first figure, we can see a typical call\r\nstack when explorer.exe invokes the CreateFileW function. The system monitoring tool, SysMon, effectively\r\nwalks the call stack, enabling us to understand the purpose behind this API call and examine the modules and\r\nfunctions involved in the process.\r\nhttps://www.zscaler.com/blogs/security-research/dodgebox-deep-dive-updated-arsenal-apt41-part-1\r\nPage 6 of 8\n\nFigure 2: Normal example of stack trace from  explorer.exe calling  CreateFileW .\r\nIn contrast, the next figure shows the call stack recorded by SysMon when DodgeBox uses stack spoofing to call\r\nthe CreateFileW function. Notice that there is no indication of DodgeBox’s modules that triggered the API call.\r\nInstead, the modules involved all appear to be legitimate Windows modules.\r\nhttps://www.zscaler.com/blogs/security-research/dodgebox-deep-dive-updated-arsenal-apt41-part-1\r\nPage 7 of 8\n\nFigure 3:  Stack trace of DodgeBox calling CreateFileW using the stack spoofing technique.\r\nThere is an excellent writeup of this technique, so we will only highlight some implementation details specific to\r\nDodgeBox:\r\nWhen the  CallFunction is invoked, DodgeBox uses a random  jmp qword ptr [rbp+48h] gadget\r\nresiding within the  .text section of K ernelBase .\r\nDodgeBox analyzes the unwind codes within the  .pdata section to extract the unwind size for the\r\nfunction that includes the selected gadget.\r\nDodgeBox obtains the addresses of  RtlUserThreadStart + 0x21 and  BaseThreadInitThunk + 0x14 ,\r\nalong with their respective unwind sizes.\r\nDodgeBox sets up the stack by inserting the addresses of  RtlUserThreadStart +\r\n0x21 ,  BaseThreadInitThunk + 0x14 , and the address of the gadget at the right positions, utilizing the\r\nunwind sizes retrieved.\r\nFollowing that, DodgeBox proceeds to insert the appropriate return address at  [rbp+48h] and prepares\r\nthe registers and stack with the necessary argument values to be passed to the API. This preparation ensures\r\nthat the API is called correctly and with the intended parameters.\r\nFinally, DodgeBox executes a  jmp instruction to redirect the control flow to the targeted API.\r\nExplore more Zscaler blogs\r\nSource: https://www.zscaler.com/blogs/security-research/dodgebox-deep-dive-updated-arsenal-apt41-part-1\r\nhttps://www.zscaler.com/blogs/security-research/dodgebox-deep-dive-updated-arsenal-apt41-part-1\r\nPage 8 of 8",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia",
		"ETDA"
	],
	"references": [
		"https://www.zscaler.com/blogs/security-research/dodgebox-deep-dive-updated-arsenal-apt41-part-1"
	],
	"report_names": [
		"dodgebox-deep-dive-updated-arsenal-apt41-part-1"
	],
	"threat_actors": [
		{
			"id": "4d5f939b-aea9-4a0e-8bff-003079a261ea",
			"created_at": "2023-01-06T13:46:39.04841Z",
			"updated_at": "2026-04-10T02:00:03.196806Z",
			"deleted_at": null,
			"main_name": "APT41",
			"aliases": [
				"WICKED PANDA",
				"BRONZE EXPORT",
				"Brass Typhoon",
				"TG-2633",
				"Leopard Typhoon",
				"G0096",
				"Grayfly",
				"BARIUM",
				"BRONZE ATLAS",
				"Red Kelpie",
				"G0044",
				"Earth Baku",
				"TA415",
				"WICKED SPIDER",
				"HOODOO",
				"Winnti",
				"Double Dragon"
			],
			"source_name": "MISPGALAXY:APT41",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "e698860d-57e8-4780-b7c3-41e5a8314ec0",
			"created_at": "2022-10-25T15:50:23.287929Z",
			"updated_at": "2026-04-10T02:00:05.329769Z",
			"deleted_at": null,
			"main_name": "APT41",
			"aliases": [
				"APT41",
				"Wicked Panda",
				"Brass Typhoon",
				"BARIUM"
			],
			"source_name": "MITRE:APT41",
			"tools": [
				"ASPXSpy",
				"BITSAdmin",
				"PlugX",
				"Impacket",
				"gh0st RAT",
				"netstat",
				"PowerSploit",
				"ZxShell",
				"KEYPLUG",
				"LightSpy",
				"ipconfig",
				"sqlmap",
				"China Chopper",
				"ShadowPad",
				"MESSAGETAP",
				"Mimikatz",
				"certutil",
				"njRAT",
				"Cobalt Strike",
				"pwdump",
				"BLACKCOFFEE",
				"MOPSLED",
				"ROCKBOOT",
				"dsquery",
				"Winnti for Linux",
				"DUSTTRAP",
				"Derusbi",
				"ftp"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "2a24d664-6a72-4b4c-9f54-1553b64c453c",
			"created_at": "2025-08-07T02:03:24.553048Z",
			"updated_at": "2026-04-10T02:00:03.787296Z",
			"deleted_at": null,
			"main_name": "BRONZE ATLAS",
			"aliases": [
				"APT41 ",
				"BARIUM ",
				"Blackfly ",
				"Brass Typhoon",
				"CTG-2633",
				"Earth Baku ",
				"GREF",
				"Group 72 ",
				"Red Kelpie ",
				"TA415 ",
				"TG-2633 ",
				"Wicked Panda ",
				"Winnti"
			],
			"source_name": "Secureworks:BRONZE ATLAS",
			"tools": [
				"Acehash",
				"CCleaner v5.33 backdoor",
				"ChinaChopper",
				"Cobalt Strike",
				"DUSTPAN",
				"Dicey MSDN",
				"Dodgebox",
				"ForkPlayground",
				"HUC Proxy Malware (Htran)"
			],
			"source_id": "Secureworks",
			"reports": null
		}
	],
	"ts_created_at": 1775434863,
	"ts_updated_at": 1775791941,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/fbb13800d3dc24e4ce7f42b58f7fa88be781ebef.pdf",
		"text": "https://archive.orkl.eu/fbb13800d3dc24e4ce7f42b58f7fa88be781ebef.txt",
		"img": "https://archive.orkl.eu/fbb13800d3dc24e4ce7f42b58f7fa88be781ebef.jpg"
	}
}