{
	"id": "59740a04-515c-466e-b072-a957bea8e3e6",
	"created_at": "2026-04-06T00:09:52.202905Z",
	"updated_at": "2026-04-10T03:21:33.430261Z",
	"deleted_at": null,
	"sha1_hash": "f7c4904bb4bb66ca220d78d0a39b50d9abb16f64",
	"title": "MalwareAnalysisReports/Pikabot/Pikabot Loader.md at main · VenzoV/MalwareAnalysisReports",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 828788,
	"plain_text": "MalwareAnalysisReports/Pikabot/Pikabot Loader.md at main ·\r\nVenzoV/MalwareAnalysisReports\r\nBy VenzoV\r\nArchived: 2026-04-05 19:07:57 UTC\r\nSample Information\r\nPacked\r\nSHA25 SHA1 MD\r\nDBDD22025131EEBE52EFC5FBE70E2E87723FF1934C808901BBB176F6130F23F6 66CBE1E120A28E812B265880406305E578560FFF C85\r\nUnpacked\r\nSHA25 SHA1\r\n75CCCAE5F0B726F23DAA6BE69DD7C5E8FCD25A41C06191B84EB00EF945E5F7FA F269DDFFA7A741C879D712D7009A112402AAA0B2\r\nIntroduction\r\nPikabot is a relatively new malware. It has been analyzed and reversed before ( see references). This is my take and analysis\r\non the updated version of the loader. Earlier during the year the sample was smaller and also used different string\r\nencryption. Stack strings are still used, but now RC4 is used to decrypt them.\r\nPikabot is divided into two modules, the loader and the core. In this part we will take a look at the loader, which essentially\r\nhas the job to load the core module which will be responsible for C2 communication.\r\nHigh level behavior\r\nSo before going into the details the sample will perform the following actions, and during the analysis below I will show\r\ncase the assembly, decompiler and debugger evidence.\r\nThe malware uses a lot of junk code to try to hinder analysis.\r\nAccesses the PEB to get handle to kernel32.dll to fetch LoadlLibraryA \u0026 GetProcAddress this will be used to\r\ndynamically load API.\r\nStrings, in particular the API names passed to the API resolving function, are encrypted using RC4.\r\nThe core module is decrypted from png files located in the resource section.\r\nLegitimate windows binary process is started, and core module is decrypted and injected into the process\r\nMalware uses indirect syscalls\r\nPEB access\r\nThe first function to analyze is the one responsible for fetching LoadlLibraryA \u0026 GetProcAddress. To do this, the malware\r\ngoes through the PEB to reach to get the base address of the kernel32.dll.\r\nPEB structure is accessed, and the the code walks through InLoadOrderModuleList twice and finally reaches the third entry\r\nwhich is always kernel32.dll. I have added references below to read more on PEB structure and how it can be used.\r\nhttps://github.com/VenzoV/MalwareAnalysisReports/blob/main/Pikabot/Pikabot%20Loader.md\r\nPage 1 of 15\n\nOnce the module base for kernel32.dll is found, the two API can now be fetched. Two hashes are used and passed to a\r\nfunction which will resolve the API.\r\n0xB89FB14B - GetProcAddress\r\n0x7FA21D8F - LoadLibraryA\r\nRC4 Inline Decryption\r\nChecking the sample, it uses RC4 to decrypt the strings. The malware uses \"legit\" strings for the keystream. We can\r\nreceognize RC4 by typical 0x100 loops followed by another loop with XOR operation. Below is what the code looks like.\r\nKeep in mind that the malware uses a lot of junk code between the two loops and final decryption loop. Also, the decryption\r\nhappens in line and is not a function. Both factors make static analysis bothersome, and emulation also bothersome. The\r\ndecrypted strings can be fetched all at once using the debugger and some conditional break points. I will add the full list\r\nbelow.\r\n do\r\n {\r\n v333[v3 + 24] = v3;\r\n ++v3;\r\n }\r\n while ( v3 \u003c 0x100 );\r\n v4 = 0;\r\n v338 = 0xF;\r\n do\r\n {\r\n v5 = v333[v4 + 24];\r\n a1 = (a1 + *(dbg_key_rc4 + (v4 \u0026 0xF)) + v5);\r\n v333[v4++ + 24] = v333[a1 + 24];\r\n v333[a1 + 24] = v5;\r\n }\r\n while ( v4 \u003c 0x100 );\r\n v6 = v352;\r\n jj = 0;\r\n LOBYTE(v7) = 0;\r\n for ( i = 0; i \u003c 12; ++i )\r\n {\r\n v345 = (v7 + 1);\r\n v9 = v333[v345 + 24];\r\n v352 = -339480793 * v6;\r\n jj = (v9 + jj);\r\n v333[v345 + 24] = v333[jj + 24];\r\n v333[jj + 24] = v9;\r\n v7 = (v7 + 1);\r\n v6 = v352;\r\n v312[i] = *(\u0026encrypted_blob[2] + i) ^ v333[(v9 + v333[v7 + 24]) + 24];\r\n }\r\nDynamic API resolving\r\nThe First analyzed function and the RC4 encryption method, both are the main core of the APi resolving function. The\r\nfunction accepts two arguements:\r\nDLL flag -\u003e this is just a numerical value that tells the function in which DLL the API is; 1: Kernel32.dll, 2:\r\nUser32.dll, 3: ntdll.dll\r\nAPI name in cleartext\r\nWhichever dll is used, the end result is always a jump to LABEL 88 seen below which peforms LoadLibraryA and\r\nGetProcAddress to retrieve the address of the API.\r\nhttps://github.com/VenzoV/MalwareAnalysisReports/blob/main/Pikabot/Pikabot%20Loader.md\r\nPage 2 of 15\n\nDecrypted Strings\r\nSetting two conditional break points on the API resolving function it is possible to have the debugger decrypt all the strings\r\nand log them.\r\nFirst breakpoint is at the start of the funciton when the decrypted string passed as argument is saved to a variable\r\nSecond breakpoint is on the return, so we can read ESP to also get the return address and so we know on IDA where\r\nthis value needs to be added as comment and rename functions.\r\nThese are the parameters used for the conditional break point, the addresses refer to how may binary was rebased in IDA.\r\n\"##APICALL {utf8(edx)}\" -\u003e 0x6AB277B3 \"##APICALL Address 0x{[esp]} \"-\u003e 0x6AB27F86\r\nhttps://github.com/VenzoV/MalwareAnalysisReports/blob/main/Pikabot/Pikabot%20Loader.md\r\nPage 3 of 15\n\nOutput:\r\n##APICALL HeapAlloc\r\n##APICALL Address 0x6AB1ECFA\r\n##APICALL LoadLibraryA\r\n##APICALL Address 0x6AB1908A\r\n##APICALL FreeLibrary\r\n##APICALL Address 0x6AB190E3\r\n##APICALL LoadLibraryA\r\n##APICALL Address 0x6AB190FD\r\n##APICALL FreeLibrary\r\n##APICALL Address 0x6AB19246\r\n##APICALL LoadLibraryA\r\n##APICALL Address 0x6AB19260\r\n##APICALL FreeLibrary\r\n##APICALL Address 0x6AB192FA\r\n##APICALL LoadLibraryA\r\n##APICALL Address 0x6AB19314\r\n##APICALL LoadLibraryA\r\n##APICALL Address 0x6AB1950B\r\n##APICALL LoadLibraryA\r\n##APICALL Address 0x6AB1959A\r\n##APICALL GetCurrentProcess\r\n##APICALL Address 0x6AB19D5C\r\n##APICALL GetTickCount\r\n##APICALL Address 0x6AB2C823\r\n##APICALL GetCurrentThread\r\n##APICALL Address 0x6AB1A42C\r\n##APICALL GetThreadContext\r\n##APICALL Address 0x6AB1A44B\r\n##APICALL FindResourceA\r\nhttps://github.com/VenzoV/MalwareAnalysisReports/blob/main/Pikabot/Pikabot%20Loader.md\r\nPage 4 of 15\n\n##APICALL Address 0x6AB30F35\r\n##APICALL LoadResource\r\n##APICALL Address 0x6AB30F55\r\n##APICALL LockResource\r\n##APICALL Address 0x6AB30F7B\r\n##APICALL SizeofResource\r\n##APICALL Address 0x6AB30F9F\r\n##APICALL FreeResource\r\n##APICALL Address 0x6AB31F8A\r\n##APICALL FindResourceA\r\n##APICALL Address 0x6AB30F35\r\n##APICALL LoadResource\r\n##APICALL Address 0x6AB30F55\r\n##APICALL LockResource\r\n##APICALL Address 0x6AB30F7B\r\n##APICALL SizeofResource\r\n##APICALL Address 0x6AB30F9F\r\n##APICALL FreeResource\r\n##APICALL Address 0x6AB31F8A\r\n##APICALL FindResourceA\r\n##APICALL Address 0x6AB30F35\r\n##APICALL LoadResource\r\n##APICALL Address 0x6AB30F55\r\n##APICALL LockResource\r\n##APICALL Address 0x6AB30F7B\r\n##APICALL SizeofResource\r\n##APICALL Address 0x6AB30F9F\r\n##APICALL FreeResource\r\n##APICALL Address 0x6AB31F8A\r\n##APICALL FindResourceA\r\n##APICALL Address 0x6AB30F35\r\n##APICALL LoadResource\r\n##APICALL Address 0x6AB30F55\r\n##APICALL LockResource\r\n##APICALL Address 0x6AB30F7B\r\n##APICALL SizeofResource\r\n##APICALL Address 0x6AB30F9F\r\n##APICALL FreeResource\r\n##APICALL Address 0x6AB31F8A\r\n##APICALL FindResourceA\r\n##APICALL Address 0x6AB30F35\r\n##APICALL LoadResource\r\n##APICALL Address 0x6AB30F55\r\n##APICALL LockResource\r\n##APICALL Address 0x6AB30F7B\r\n##APICALL SizeofResource\r\n##APICALL Address 0x6AB30F9F\r\n##APICALL FreeResource\r\n##APICALL Address 0x6AB31F8A\r\n##APICALL FindResourceA\r\n##APICALL Address 0x6AB30F35\r\n##APICALL LoadResource\r\n##APICALL Address 0x6AB30F55\r\n##APICALL LockResource\r\n##APICALL Address 0x6AB30F7B\r\n##APICALL SizeofResource\r\n##APICALL Address 0x6AB30F9F\r\n##APICALL FreeResource\r\n##APICALL Address 0x6AB31F8A\r\n##APICALL FindResourceA\r\n##APICALL Address 0x6AB30F35\r\n##APICALL LoadResource\r\n##APICALL Address 0x6AB30F55\r\n##APICALL LockResource\r\n##APICALL Address 0x6AB30F7B\r\n##APICALL SizeofResource\r\n##APICALL Address 0x6AB30F9F\r\n##APICALL FreeResource\r\n##APICALL Address 0x6AB31F8A\r\n##APICALL FindResourceA\r\n##APICALL Address 0x6AB30F35\r\nhttps://github.com/VenzoV/MalwareAnalysisReports/blob/main/Pikabot/Pikabot%20Loader.md\r\nPage 5 of 15\n\n##APICALL LoadResource\r\n##APICALL Address 0x6AB30F55\r\n##APICALL LockResource\r\n##APICALL Address 0x6AB30F7B\r\n##APICALL SizeofResource\r\n##APICALL Address 0x6AB30F9F\r\n##APICALL FreeResource\r\n##APICALL Address 0x6AB31F8A\r\n##APICALL FindResourceA\r\n##APICALL Address 0x6AB30F35\r\n##APICALL LoadResource\r\n##APICALL Address 0x6AB30F55\r\n##APICALL LockResource\r\n##APICALL Address 0x6AB30F7B\r\n##APICALL SizeofResource\r\n##APICALL Address 0x6AB30F9F\r\n##APICALL FreeResource\r\n##APICALL Address 0x6AB31F8A\r\n##APICALL FindResourceA\r\n##APICALL Address 0x6AB30F35\r\n##APICALL LoadResource\r\n##APICALL Address 0x6AB30F55\r\n##APICALL LockResource\r\n##APICALL Address 0x6AB30F7B\r\n##APICALL SizeofResource\r\n##APICALL Address 0x6AB30F9F\r\n##APICALL FreeResource\r\n##APICALL Address 0x6AB31F8A\r\n##APICALL FindResourceA\r\n##APICALL Address 0x6AB30F35\r\n##APICALL LoadResource\r\n##APICALL Address 0x6AB30F55\r\n##APICALL LockResource\r\n##APICALL Address 0x6AB30F7B\r\n##APICALL SizeofResource\r\n##APICALL Address 0x6AB30F9F\r\n##APICALL FreeResource\r\n##APICALL Address 0x6AB31F8A\r\n##APICALL FindResourceA\r\n##APICALL Address 0x6AB30F35\r\n##APICALL LoadResource\r\n##APICALL Address 0x6AB30F55\r\n##APICALL LockResource\r\n##APICALL Address 0x6AB30F7B\r\n##APICALL SizeofResource\r\n##APICALL Address 0x6AB30F9F\r\n##APICALL FreeResource\r\n##APICALL Address 0x6AB31F8A\r\n##APICALL IsBadReadPtr\r\n##APICALL Address 0x6AB165DE\r\n##APICALL HeapAlloc\r\n##APICALL Address 0x6AB1ECFA\r\n##APICALL HeapFree\r\n##APICALL Address 0x6AB1EFB4\r\n##APICALL InitializeProcThreadAttributeList\r\n##APICALL Address 0x6AB24435\r\n##APICALL HeapAlloc\r\n##APICALL Address 0x6AB1ECFA\r\n##APICALL InitializeProcThreadAttributeList\r\n##APICALL Address 0x6AB24474\r\n##APICALL UpdateProcThreadAttribute\r\n##APICALL Address 0x6AB24541\r\n##APICALL CreateProcessW\r\n##APICALL Address 0x6AB245D5\r\n##APICALL DeleteProcThreadAttributeList\r\n##APICALL Address 0x6AB246D4\r\n##APICALL HeapFree\r\n##APICALL Address 0x6AB1EFB4\r\n##APICALL HeapAlloc\r\n##APICALL Address 0x6AB1ECFA\r\n##APICALL HeapFree\r\nhttps://github.com/VenzoV/MalwareAnalysisReports/blob/main/Pikabot/Pikabot%20Loader.md\r\nPage 6 of 15\n\n##APICALL Address 0x6AB1EFB4\r\n##APICALL HeapFree\r\n##APICALL Address 0x6AB1EFB4\r\n##APICALL Sleep\r\n##APICALL Address 0x6AB13B32\r\nAnti Analysis\r\nThere are three anti analysis functions I have identified so far. The first two are simple, and basically check for DLLs\r\nassociated with known sandbox/Vms. Again here there DLL names are RC4 encrypted. I have made use of conditional\r\nbreakpoints from x32 debug to extract from logging all the decrypted strings.\r\nmw_anti_vm():\r\n##DLL String Decrypted cmdvrt32.dll\r\n##Address 0x6AB1C945\r\n##DLL String Decrypted cmdvrt64.dll\r\n##Address 0x6AB1C95D\r\n##DLL String Decrypted dbghelp.dll\r\n##Address 0x6AB1C972\r\n##DLL String Decrypted cuckoomon.dll\r\n##Address 0x6AB1C987\r\n##DLL String Decrypted pstorec.dll\r\n##Address 0x6AB1C99C\r\n##DLL String Decrypted avghookx.dll\r\n##Address 0x6AB1C9B1\r\n##DLL String Decrypted avghooka.dll\r\n##Address 0x6AB1C9C6\r\n##DLL String Decrypted snxhk.dll\r\n##Address 0x6AB1C9DB\r\n##DLL String Decrypted api_log.dll\r\n##Address 0x6AB1C9F0\r\n##DLL String Decrypted dir_watch.dll\r\n##Address 0x6AB1CA05\r\n##DLL String Decrypted wpespy.dll\r\n##Address 0x6AB1CA1A\r\nmw_anti_vm1():\r\n##DLL Load Kernel32.dll\r\n##DLL Load Kernel32.DLL\r\n##DLL Load networkexplorer.DLL\r\n##DLL Load NlsData0000.DLL\r\n##DLL Load NetProjW.DLL\r\n##DLL Load Ghofr.DLL\r\n##DLL Load fg122.DLL\r\nhttps://github.com/VenzoV/MalwareAnalysisReports/blob/main/Pikabot/Pikabot%20Loader.md\r\nPage 7 of 15\n\nThe third anti analysis check, seems to perform some indirect syscalls by finding the address to functions for the ntdll.dll\r\ndirectly. I have not been able to understand this 100% yet. Also, in this function the only resolved API which is also called is\r\nGetTickCount. This is used to check the time since start of process, also typically used to check if process is running through\r\na debugger.\r\nCore Module Extraction\r\nAfter the anti-analysis checks, the malware will proceed to fetch the core module from PNG files located in the resource\r\nsection. Each png file has a section of data which needs to be combined with the others. As a delimiter the sample uses a 4\r\nbyte string as start of section. Each section is written to an allocated heap,thus combining them. In total the sample uses 12\r\nPNG files to store the core module. The function called has the following arguments:\r\n1. pointer to process\r\n2. PNG file name\r\n3. \"png\" string extension\r\n4. 4 byte delimiter string\r\n5. Heap offset\r\nhttps://github.com/VenzoV/MalwareAnalysisReports/blob/main/Pikabot/Pikabot%20Loader.md\r\nPage 8 of 15\n\nThe function called above performs the following:\r\nCall the API related to resource fetch - FindResourcaA, LoadResourceA, LockResourceA and finally\r\nSizeOfResource\r\nOnce the resource is loaded, the malware parses the PNG chunks and compare the name to the one passed as\r\nargument which is a 4 byte string. More on chunks check references, it is how PNG files are structured.\r\nWhen the correct chunk is found, all the data from that chuck is written to the allocated heap but it is first xored.\r\nhttps://github.com/VenzoV/MalwareAnalysisReports/blob/main/Pikabot/Pikabot%20Loader.md\r\nPage 9 of 15\n\nCore Module Decryption\r\nOnce the module is loaded into the heap memory, some more modifications need to be made to change it to a PE file. At the\r\nstart of the DLL the key is RC4 decrypted:\r\n1EmXwEpOYt6Cf8GyJVGXYUaqPnUapVrk\r\nThe call to decrypted has the key argument the heap with encrypted payload and new heap which will store the decrypted\r\npayload. The decryption seems to be AES 256, but need to check further.\r\nhttps://github.com/VenzoV/MalwareAnalysisReports/blob/main/Pikabot/Pikabot%20Loader.md\r\nPage 10 of 15\n\nFinally, once the core module is extracted the final function analyzed calls the following API and injects the code into\r\n\"SearchProtocolHost.exe\", which is spawned in a suspended state.\r\nInitializeProcThreadAttributeList\r\nUpdateProcThreadAttribute\r\nCreateProcessW\r\nDeleteProcThreadAttribute\r\nhttps://github.com/VenzoV/MalwareAnalysisReports/blob/main/Pikabot/Pikabot%20Loader.md\r\nPage 11 of 15\n\nChecking process hacker we can observe memory being allocated in the process and then the core payload is written here.\r\nhttps://github.com/VenzoV/MalwareAnalysisReports/blob/main/Pikabot/Pikabot%20Loader.md\r\nPage 12 of 15\n\nIndirect Sycalls\r\nAs mentioned above, the sample makes use of indirect syscalls. The calls made can be referenced on the eax register by their\r\nIDs. I expect NtAllocateVirtualMemory and NtWriteVirtualMemory to be called after process creation. We can run the code\r\nuntil CreateProcessW is called and then set two breakpoints on the wrapper function for the indirect syscalls. Once inside\r\nthe syscall id is processed and then called. We observe 0x18 and 0x3a being loaded to eax which correspond to the funcitons\r\nwe expect. Soon after these calls the memory is allocated and the corepayload is written to further evidence the usage of\r\nthese indirect syscall.\r\nSpecial thanks to @xleandr0 for helping to understand this.\r\nFollowing the code seen in IDA:\r\nFollowing the debugger view of the syscall ID:\r\nhttps://github.com/VenzoV/MalwareAnalysisReports/blob/main/Pikabot/Pikabot%20Loader.md\r\nPage 13 of 15\n\nUsing conditional breakpoints as above, we can print out all the syscall IDs used by the malware, to see what API are used. I\r\ndumped it all out, but there are a lot of repetitions and can't paste them all here, but the following are the API called without\r\ncounting duplicates:\r\n##SyscallID 19 -\u003e NtQueryInformationProcess -\u003e NtQueryInformationProcess\r\nINT3 breakpoint at pika.6AB139CF!\r\n##SyscallID 19 -\u003e NtQueryInformationProcess\r\n##SyscallID 3F -\u003e NtReadVirtualMemory\r\n##SyscallID 2A -\u003e NtUnmapViewOfSection\r\n##SyscallID 18 -\u003e NtAllocateVirtualMemory\r\n##SyscallID 3A -\u003e NtWriteVirtualMemory\r\n##SyscallID 3F -\u003e NtReadVirtualMemory\r\n##SyscallID F3 -\u003e NtGetCurrentProcessorNumber\r\n##SyscallID 52 -\u003e NtResumeThread\r\nThe breakpoint after NtQueryInformationProcess checks if eax value is 1 or 0. If 1 the process ends, so manually changing\r\nthe value to 0 avoids the check and continues execution. Most of the calls that generate volume are:\r\nNtReadVirtualMemory\r\nNtAllocateVirtualMemory\r\nNtWriteVirtualMemory\r\nWe can see the final Native API is NtResumeThread which makes sense, since the execution will continue from the injected\r\ncode.\r\nReferences\r\nhttps://d01a.github.io/pikabot/\r\nhttps://research.openanalysis.net/pikabot/debugging/string%20decryption/emulation/memulator/2023/11/19/new-pikabot-strings.html\r\nhttps://www.zscaler.com/blogs/security-research/technical-analysis-pikabot\r\nhttps://research.openanalysis.net/pikabot/debugging/string%20decryption/2023/11/12/new-pikabot.html\r\nhttps://www.ired.team/offensive-security/code-injection-process-injection/finding-kernel32-base-and-function-addresses-in-shellcode\r\nhttp://undocumented.ntinternals.net/index.html?\r\npage=UserMode%2FUndocumented%20Functions%2FNT%20Objects%2FProcess%2FPEB.html\r\nhttps://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/pebteb/peb/index.htm\r\nhttps://github.com/VenzoV/MalwareAnalysisReports/blob/main/Pikabot/Pikabot%20Loader.md\r\nPage 14 of 15\n\nhttps://www.w3.org/TR/PNG-Chunks.html\r\nhttps://0xk4n3ki.github.io/posts/Heavens-Gate-Technique/\r\nhttps://www.gosecure.net/blog/2021/12/03/trickbot-leverages-zoom-work-from-home-interview-malspam-heavens-gate-and-spamhaus/\r\nhttps://j00ru.vexillium.org/syscalls/nt/64/\r\nhttps://twitter.com/leandrofr0es\r\nSource: https://github.com/VenzoV/MalwareAnalysisReports/blob/main/Pikabot/Pikabot%20Loader.md\r\nhttps://github.com/VenzoV/MalwareAnalysisReports/blob/main/Pikabot/Pikabot%20Loader.md\r\nPage 15 of 15\n\nthis value needs These are the parameters to be added as comment used for the conditional and rename functions. break point, the addresses refer to how may binary was rebased in IDA.\n\"##APICALL {utf8(edx)}\" -\u003e 0x6AB277B3 \"##APICALL Address 0x{[esp]} \"-\u003e 0x6AB27F86\n  Page 3 of 15",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://github.com/VenzoV/MalwareAnalysisReports/blob/main/Pikabot/Pikabot%20Loader.md"
	],
	"report_names": [
		"Pikabot%20Loader.md"
	],
	"threat_actors": [],
	"ts_created_at": 1775434192,
	"ts_updated_at": 1775791293,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/f7c4904bb4bb66ca220d78d0a39b50d9abb16f64.pdf",
		"text": "https://archive.orkl.eu/f7c4904bb4bb66ca220d78d0a39b50d9abb16f64.txt",
		"img": "https://archive.orkl.eu/f7c4904bb4bb66ca220d78d0a39b50d9abb16f64.jpg"
	}
}