{
	"id": "fb916053-18fc-4c6e-bddd-7561687473d9",
	"created_at": "2026-04-06T00:07:42.197768Z",
	"updated_at": "2026-04-10T13:12:58.678878Z",
	"deleted_at": null,
	"sha1_hash": "09f0006eaed8609ec37641a0203782f7e78287ec",
	"title": "BAZARLOADER: Unpacking an ISO File Infection - 0ffset Training Solutions",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 1552337,
	"plain_text": "BAZARLOADER: Unpacking an ISO File Infection - 0ffset\r\nTraining Solutions\r\nBy Chuong Dong\r\nPublished: 2022-04-19 · Archived: 2026-04-05 22:22:00 UTC\r\nBAZARLOADER (aka BAZARBACKDOOR) is a Windows-based loader that spreads through attachments in\r\nphishing emails. During an infection, the final loader payload typically downloads and executes a Cobalt Strike\r\nbeacon to provide remote access for the threat actors, which, in a lot of cases, leads to ransomware being deployed\r\nto the victim’s machine.\r\nIn this initial post, we will unpack the different stages of a BAZARLOADER infection that comes in the form of\r\nan optical disk image (ISO) file. We will also dive into the obfuscation methods used by the main\r\nBAZARLOADER payload.\r\nTo follow along, you can grab the sample as well as the PCAP files for it on Malware-Traffic-Analysis.net.\r\nSHA256: 0900b4eb02bdcaefd21df169d21794c8c70bfbc68b2f0612861fcabc82f28149\r\nStep 1: Mounting ISO File \u0026 Extracting Stage 1 Executable\r\nRecent BAZARLOADER samples arrive in emails containing OneDrive links to download an ISO file to avoid\r\ndetection since most AVs tend to ignore this particular file type. With Windows 7 and above integrating the\r\nmounting functionality into Windows Explorer, we can mount any ISO file as a virtual drive by double-clicking\r\non it.\r\nWhen we mount the malicious ISO file, we see that a drive is mounted on the system that contains a shortcut file\r\nnamed “Attachments.lnk” and a hidden file named “documents.log”.\r\nThe shortcut file has to be run by the victim to begin the chain of infection. We can quickly extract the actual\r\ncommand being executed by this shortcut from its Properties window.\r\nC:\\Windows\\System32\\rundll32.exe documents.log,vspa\r\nhttps://www.0ffset.net/reverse-engineering/bazarloader-iso-file-infection/\r\nPage 1 of 13\n\nOnce the victim double-clicks on the shortcut file, the command executes the Windows rundll32.exe program to\r\nlaunch the “documents.log” file. This lets us know that the file being launched is a DLL file, and the entry point\r\nis its export function vspa.\r\nStep 2: Extracting Second Stage Shellcode\r\nTaking a quick look in IDA, we can somewhat tell that the extracted DLL is packed since it has only a few\r\nfunctions and a really suspicious looking buffer of ASCII characters in its custom .odata section.\r\nhttps://www.0ffset.net/reverse-engineering/bazarloader-iso-file-infection/\r\nPage 2 of 13\n\nWith that in mind, we will just perform some quick static analysis to determine where we can dump the next stage.\r\nIn the first function of the vspa export, we see sub_1800045D6 takes a DWORD in as the parameter. This\r\nfunction returns a variable that contains an address to a function that is later called in the code.\r\nAt this point, we can safely guess that sub_1800045D6 is an API resolving function, and the parameter it takes is\r\nthe hash of the API’s name. Because this is still the unpacking phase, we won’t dive too deep into analyzing this\r\nfunction.\r\nInstead, I’ll just use OALabs’s HashDB IDA plugin to quickly reverse-lookup the hashing algorithm used from\r\nthe hash. The result shows that the hash corresponds to an API name hashed with Metasploit’s hashing algorithm\r\nROR13.\r\nhttps://www.0ffset.net/reverse-engineering/bazarloader-iso-file-infection/\r\nPage 3 of 13\n\nAfter determining the hashing algorithm, we can use HashDB to quickly look up the APIs being resolved by this\r\nfunction. It becomes clear that this function resolves the RtlAllocateHeap API, calls that to allocate a heap buffer\r\nand writes the encoded ASCII data to it.\r\nFrom this point onward, we can guess that the packer will decode this buffer and launch it somewhere later in the\r\ncode. If we skip toward the end of the vspa export, we see a call instruction on a variable that is not returned from\r\nthe API resolving function, so it can potentially be our tail jump.\r\nhttps://www.0ffset.net/reverse-engineering/bazarloader-iso-file-infection/\r\nPage 4 of 13\n\nThe last function to modify that v19 variable is sub_180003FE6, so we can quickly take a look at that.\r\nIt turns out the sub_180003FE6 function just resolves and calls NtMapViewOfSection to map a view of a section\r\ninto the virtual address space and writes the base address of the view into the v19 variable. Then, it just executes\r\nqmemcpy to copy the data in the second variable to the returned virtual base address.\r\nThis tells us two things. First, our guess that the v19 variable will contain the address to executable code is\r\ncorrect. Second, we know that the executable code is shellcode since the data is mapped and executed directly at\r\noffset 0 from where it is written.\r\nFrom here, we can set up x64dbg, execute the DLL file at the vspa export, and break at the call instruction. After\r\nstepping into the function, we will be at the head of the shellcode.\r\nhttps://www.0ffset.net/reverse-engineering/bazarloader-iso-file-infection/\r\nPage 5 of 13\n\nWe can now dump this virtual memory buffer to retrieve the second stage shellcode for the next unpacking step.\r\nStep 3: Extracting The Final BAZARLOADER Payload\r\nWhen we examine the shellcode in IDA, we can quickly use the same trick with HashDB above to see that the\r\nshellcode also performs API hashing with Metasploit’s ROR13.\r\nAt the entry point above, the shellcode resolves a set of functions that it will call, most notably VirtualAlloc and\r\nVirtualProtect. These two functions are typically used by packers to allocate virtual memory to decode and write\r\nthe next stage executable in before launching it.\r\nWith this in mind, our next step should be debugging the shellcode and setting breakpoints at these two API calls.\r\nWe can pick up where we are after dumping in x64dbg during Step 2, or we can launch the shellcode directly in\r\nhttps://www.0ffset.net/reverse-engineering/bazarloader-iso-file-infection/\r\nPage 6 of 13\n\nour debugger using OALabs’s BlobRunner or similar shellcode launcher.\r\nOur first hit with VirtualAlloc is a call to allocate a virtual memory buffer at virtual address 0x204140000 with\r\nthe size of 0x2A000 bytes.\r\nWe can run until VirtualAlloc returns and start monitoring the memory at address 0x204140000. After running\r\nuntil the next VirtualProtect call, we see that a valid PE executable has been written to this memory region.\r\nFinally, we can dump this memory region into a file to extract the BAZARLOADER payload.\r\nStep 4: BAZARLOADER’s String Obfuscation\r\nAs we begin performing static analysis on BAZARLOADER, it is crucial that we identify obfuscation methods\r\nthat the malware uses.\r\nOne of those methods is string obfuscation, where the malware uses encoded stack strings to hide them from static\r\nanalysis.\r\nhttps://www.0ffset.net/reverse-engineering/bazarloader-iso-file-infection/\r\nPage 7 of 13\n\nAs shown, a typical encoded string is pushed on the stack and decoded dynamically using some multiplication,\r\nsubtraction, and modulus operations.\r\nThere are different ways to resolve these stack strings, such as writing IDAPython scripts, emulation, or just\r\nrunning the program in a debugger and dumping the stack strings when they are resolved.\r\nStep 5: BAZARLOADER’s API Obfuscation\r\nBAZARLOADER obfuscates most of its API calls through a few structures that it constructs in the DllEntryPoint\r\nfunction.\r\nFirst, the malware populates the following structure that contains a handle to Kernel32.dll and addresses to API\r\nrequired to load libraries and get their API addresses.\r\nstruct API_IMPORT_STRUCT {\r\n HANDLE kernel32_handle;\r\n FARPROC mw_GetProcAddress;\r\n FARPROC mw_LoadLibraryW;\r\n FARPROC mw_LoadLibraryA;\r\n FARPROC mw_LoadLibraryA2;\r\nhttps://www.0ffset.net/reverse-engineering/bazarloader-iso-file-infection/\r\nPage 8 of 13\n\nFARPROC mw_FreeLibrary;\r\n FARPROC mw_GetModuleHandleW;\r\n FARPROC mw_GetModuleHandleA;\r\n};\r\nIt calls GetModuleHandle to retrieve the handle to Kernel32.dll, calls GetProcAddress to retrieve the address of\r\nthe GetProcAddress API, and writes those in the structure.\r\nUsing the structure’s GetProcAddress API field, BAZARLOADER retrieves the rest of the required APIs to\r\npopulate other fields in the structure. This API_IMPORT_STRUCT structure will later be used to import other\r\nlibraries’ APIs.\r\nNext, for each library to be imported, BAZARLOADER populates the following LIBRARY_STRUCT structure\r\nthat contains a set of functions to interact with the library and the library handle.\r\nhttps://www.0ffset.net/reverse-engineering/bazarloader-iso-file-infection/\r\nPage 9 of 13\n\nstruct LIB_FUNCS\r\n{\r\n FARPROC free_lib;\r\n FARPROC w_free_lib;\r\n __int64 (__fastcall *get_API_addr)(API_IMPORT_STRUCT*, HANDLE, char*);\r\n};\r\nstruct LIBRARY_STRUCT\r\n{\r\n LIB_FUNCS *lib_funcs;\r\n HANDLE lib_handle;\r\n};\r\nThe first 2 functions in the LIB_FUNCS structure just call the FreeLibrary API from the global\r\nAPI_IMPORT_STRUCT to free the library module.\r\nThe third function calls the GetProcAddress from the API_IMPORT_STRUCT’s field to retrieve the address of\r\nan API exported from that specific library.\r\nTo begin populating each LIBRARY_STRUCT structure, BAZARLOADER decodes the library name from a\r\nstack string and populates it with the corresponding set of functions and the library handle retrieved from calling\r\nLoadLibraryA.\r\nhttps://www.0ffset.net/reverse-engineering/bazarloader-iso-file-infection/\r\nPage 10 of 13\n\nBelow is the list of all libraries used by the malware.\r\nkernel32.dll, wininet.dll, advapi32.dll, ole32.dll, rpcrt4.dll, shell32.dll, bcrypt.dll, crypt32.dll, dnsapi.dl\r\nThe LIBRARY_STRUCT structures corresponding to these are pushed into a global list in the order below.\r\nstruct LIBRARY_STRUCT_LIST\r\n{\r\n LIBRARY_STRUCT *lib_struct_kernel32;\r\n LIBRARY_STRUCT *lib_struct_wininet;\r\n LIBRARY_STRUCT *lib_struct_advapi32;\r\n LIBRARY_STRUCT *lib_struct_ole32;\r\n LIBRARY_STRUCT *lib_struct_rpcrt4;\r\n LIBRARY_STRUCT *lib_struct_shell32;\r\n LIBRARY_STRUCT *lib_struct_bcrypt;\r\n LIBRARY_STRUCT *lib_struct_crypt32;\r\n LIBRARY_STRUCT *lib_struct_dnsapi;\r\n LIBRARY_STRUCT *lib_struct_netapi32;\r\n LIBRARY_STRUCT *lib_struct_shlwapi;\r\n LIBRARY_STRUCT *lib_struct_user32;\r\n LIBRARY_STRUCT *lib_struct_ktmw32;\r\n};\r\nhttps://www.0ffset.net/reverse-engineering/bazarloader-iso-file-infection/\r\nPage 11 of 13\n\nAfter this global list of LIBRARY_STRUCT is populated, an API can be called from a function taking in its\r\ncorresponding library’s LIBRARY_STRUCT structure and its parameters.\r\nThis function resolves the API name from a stack string, retrieves the API’s address using the get_API_addr\r\nfunction from the library structure, and calls the API with its parameters.\r\nhttps://www.0ffset.net/reverse-engineering/bazarloader-iso-file-infection/\r\nPage 12 of 13\n\nThe way the wrapper function is setup to call the actual API is really intuitive, making the code simple to\r\nunderstand through static analysis. However, it’s a bit more difficult to automate the process since there is no API\r\nhashing involved.\r\nFor my analysis, I just manually decode the stack strings in my debugger and rename the wrapper function\r\naccordingly.\r\nAt this point, we have fully unpacked BAZARLOADER and understood how the malware obfuscates its strings\r\nand APIs to make analysis harder.\r\nIn the next blog post, we will fully analyze how the loader downloads and launches a Cobalt Strike beacon from\r\nits C2 servers!\r\nSource: https://www.0ffset.net/reverse-engineering/bazarloader-iso-file-infection/\r\nhttps://www.0ffset.net/reverse-engineering/bazarloader-iso-file-infection/\r\nPage 13 of 13",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://www.0ffset.net/reverse-engineering/bazarloader-iso-file-infection/"
	],
	"report_names": [
		"bazarloader-iso-file-infection"
	],
	"threat_actors": [
		{
			"id": "610a7295-3139-4f34-8cec-b3da40add480",
			"created_at": "2023-01-06T13:46:38.608142Z",
			"updated_at": "2026-04-10T02:00:03.03764Z",
			"deleted_at": null,
			"main_name": "Cobalt",
			"aliases": [
				"Cobalt Group",
				"Cobalt Gang",
				"GOLD KINGSWOOD",
				"COBALT SPIDER",
				"G0080",
				"Mule Libra"
			],
			"source_name": "MISPGALAXY:Cobalt",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		}
	],
	"ts_created_at": 1775434062,
	"ts_updated_at": 1775826778,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/09f0006eaed8609ec37641a0203782f7e78287ec.pdf",
		"text": "https://archive.orkl.eu/09f0006eaed8609ec37641a0203782f7e78287ec.txt",
		"img": "https://archive.orkl.eu/09f0006eaed8609ec37641a0203782f7e78287ec.jpg"
	}
}