{
	"id": "97c1854e-1d90-41d0-bd9b-ad44636417bd",
	"created_at": "2026-04-06T00:12:54.318533Z",
	"updated_at": "2026-04-10T03:21:17.402912Z",
	"deleted_at": null,
	"sha1_hash": "f27e787f93d046bdee629b90179fa4026074320d",
	"title": "Pikabot | ThreatLabz",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 71271,
	"plain_text": "Pikabot | ThreatLabz\r\nBy Brett Stone-Gross, Nikolaos Pantazopoulos\r\nPublished: 2023-05-24 · Archived: 2026-04-05 15:51:24 UTC\r\nTechnical Analysis\r\nIn the following sections, we focus on Pikabot’s core module and its injector since the downloader does not\r\ncontain any functionality/features worth mentioning.\r\nCore Module Injector\r\nPikabot uses an injector to run a series of anti-analysis tests and then decrypt and inject the core module payload.\r\nIf any of these tests fail, Pikabot will terminate execution. ThreatLabz has identified the following anti-analysis\r\nmethods implemented by the injector:\r\nException Handlers by using int 2d and int 3 instructions to raise them.\r\nReading the BeingDebugged flag of the process environment block (PEB).\r\nUse of the Windows API function Beep to delay the execution.\r\nAttempt to load junk and incorrect libraries in order to detect sandboxes. \r\nUse of the Windows API functions CheckRemoteDebuggerPresent and IsDebuggerPresent for debugger\r\ndetection.\r\nThe value of the NtGlobalFlag in the PEB that indicates a debugger is present.\r\nUse of the Windows API function NtQueryInformationProcess with the classes ProcessDebugPort and\r\nProcessDebugFlags.\r\nUse of the GetWriteWatch API. The implementation seems to have been copied from here:\r\nhttps://github.com/BaumFX/cpp-anti-debug/blob/master/anti_debug.cpp#L260\r\nUse of the OutputDebugString function in order to detect a debugger. The implementation has been copied\r\nfrom here: https://github.com/BaumFX/cpp-anti-debug/blob/master/anti_debug.cpp#L456\r\nCheck the number of processors, which should be greater than or equal to 2.\r\nUse of the rdtsc instruction to check for single stepping during debugging.\r\nThe system random access memory (RAM) must be greater than 2GB.\r\nDetection of hardware breakpoints.\r\nDetection by checking the trap flag via __readeflags.\r\nANALYST NOTE: It should be noted that the use of exceptions is used in many parts of the code, for example,\r\nduring the decryption of the core payload.\r\nThe injector decrypts the core module as follows:\r\n1. Loads a set of PNG images, which are stored in the resources section (RCDATA), and decrypts them using\r\na bitwise XOR operation with a hardcoded 32-byte key. Note that each PNG image holds an encrypted\r\nhttps://www.zscaler.com/blogs/security-research/technical-analysis-pikabot\r\nPage 1 of 5\n\nchunk of the core module.\r\n2. Decrypt the XOR decrypted data using AES (CBC mode) with the same 32-byte key and use the first 16\r\nbytes of the encrypted data as an initialization vector (IV).\r\nOnce the core payload has been decrypted, the Pikabot injector creates a process with a specified file path (e.g.\r\nWerFault) and injects the core module into it. Finally, the Pikabot injector sets the\r\nPROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON flag in\r\norder to protect the injected process from non-signed Microsoft binaries.\r\nCore Module\r\nIn the following sections, the core module is analyzed with samples compiled in May 2023.\r\nAnti-Analysis\r\nSimilar to the injector, the Pikabot core module performs additional anti-analysis checks. One notable technique is\r\na “sleep” function, which Pikabot uses to delay execution. Instead of using common Windows API functions,\r\nPikabot uses the NtContinue API function in order to set a timer. The technique is not new and it is similar to other\r\nproof-of-concepts implementations.\r\nIn addition to the tests above, Pikabot stops execution if the system's language is any of the following:\r\nGeorgian (Georgia)\r\nKazakh (Kazakhstan)\r\nUzbek (Cyrillic)\r\nTajik (Tajikistan)\r\nRussian (Russia)\r\nUkrainian (Ukraine)\r\nBelarusian (Belarus)\r\nSlovenian (Slovenia)\r\nThis check is common for many threat actors that originate from countries in the Commonwealth of Independent\r\nStates (CIS) to reduce the chances of criminal prosecution.\r\nPersistence\r\nPikabot uses two methods to add persistence on a host:\r\n1. Upon execution, Pikabot retrieves its current execution folder and checks if it is located in the AppData\r\nfolder under a hardcoded folder name (might differ from sample to sample).\r\nIf Pikabot is not run from this specific file path, then it will add persistence on the compromised host by\r\ncreating a new value with its file path in the Run registry key (the key name is hardcoded in the binary). On\r\ntop of that, Pikabot corrupts the current executable file by replacing it with its PE header (512 bytes length)\r\nfollowed by null bytes (3,584 bytes in length).\r\nhttps://www.zscaler.com/blogs/security-research/technical-analysis-pikabot\r\nPage 2 of 5\n\n2. Pikabot downloads a PowerShell script from the command-and-control server and stores it in\r\nHKEY_CURRENT_USER\\Software\\predefined_name, where predefined_name is a hardcoded string in the\r\nbinary file. Additionally, it stores the encrypted command-and-control servers in the same registry path.\r\nLastly, Pikabot sets a value in the Run registry key to execute a command line that invokes this PowerShell\r\nscript (e.g., cmd /q /c start /min \" powershell \"$cimeter = Get-ItemProperty -Path\r\nHKCU:\\Software\\cimeter; powershell -encodedcommand $cimeter.unbevelledHamuli\")\r\nANALYST NOTE: Pikabot also has the option to directly execute a downloaded file instead of using this\r\npersistence mechanism (Even though this is not currently being used).\r\nCommand-and-Control Configuration\r\nPikabot does not store the command-and-control information in a single block (e.g. as Qakbot does). Instead, each\r\ncomponent (e.g. URIs) is encrypted using ADVobfuscator and the command-and-control server IP addresses and\r\nports are further decrypted during runtime using the following algorithm. Firstly, Pikabot decrypts a string that\r\nincludes a set of Base64 encoded strings. Then it parses the string using the delimiter '\u0026' and decrypts the contents\r\nby following the below steps:\r\n1. Read the first 32 bytes of the string and use them as an AES key.\r\n2. Decode the rest of the string using Base64.\r\n3. Read the first 16 bytes of the decoded string and use them as an IV.\r\n4. Read the rest of the decoded data and decrypt it using AES (CBC mode).\r\n5. The decrypted output is a Base64 string, which results in the command-and-control server IP address and\r\ncorresponding port. Note that many of the Pikabot command-and-control servers listen on ports that are\r\nidentical to the ports used by Qakbot’s proxy module such as 1194, 2078, and 2222.\r\nThere have been some minor changes over the last few months in the way that Pikabot command-and-control\r\nservers have been stored. For example, in previous versions, the command-and-control servers were only encoded\r\nusing Base64 and no further encryption or parsing was required.\r\nPikabot also appears to contain a campaign ID and binary version in each sample. These can be observed during\r\nthe network communication, where the JSON data has the keys \"version\" and \"stream\". The latter appears to be a\r\ncampaign ID. An example request (before encryption) containing these values is shown below:\r\n{\"uuid\": \"F37670100000074E33652510483\", \"stream\": \"BB1@T@2e88e610b66b4205853b211f21873208\",\r\n\"os_version\": \"Win 10.0 19050\", \"product_number\": 161, \"username\": \"test\", \"pc_name\": \"DESKTOP-TEST\",\r\n\"cpu_name\": \"11th Gen Intel(R) Core(TM)\", \"pc_uptime\": 29884462, \"gpu_name\": \"GPU_NAME\",\r\n\"ram_amount\": 8096, \"screen_resolution\": \"1560x1440\", \"version\": \"0.5.3\", \"domain_name\": \"\",\r\n\"domain_controller_name\": \"unknown\", \"domain_controller_address\": \"unknown\", \"knock_timeout\": 254,\r\n\"is_elevated\": 0}\r\nThe campaign ID values observed by Threatlabz are particularly interesting because of the prefixes BB1 and\r\neu_bb_0. These resemble some of the campaign IDs that have been observed in Qakbot binaries, which frequently\r\nhttps://www.zscaler.com/blogs/security-research/technical-analysis-pikabot\r\nPage 3 of 5\n\ncontain the prefix BB followed by an integer.\r\nNetwork communication\r\nPikabot starts by registering the compromised host with the command-and-control servers. The registration\r\nprocess involves collecting system information and reporting it to the command-and-control server with an\r\nHTTPS POST request. A variety of data is collected such as the following:\r\n1. Network information by executing the command ipconfig.exe /all\r\n2. User/groups information by executing whoami.exe /all\r\n3. Windows build information.\r\n4. Generic host information (e.g. available RAM, screen resolution)\r\n5. Domain controllers information.\r\nSimilar to other botnets, Pikabot generates a unique bot identifier for the compromised host. The algorithm, which\r\nPikabot uses to generate the bot identifier can be replicated in Python using the code here.\r\nOnce the registration procedure has been completed and persistence to the compromised host has been established,\r\nPikabot starts requesting tasks from the server.  Pikabot supports the following command types:\r\ntask - a command to execute\r\nknock - a keep-alive message\r\nThe tasks that Pikabot currently supports are described in Table 1.\r\nTask Name Description\r\ncmd Executes a shell command via cmd.exe.\r\ndestroy Exits the current process.\r\nshellcode Injects and executes downloaded shellcode.\r\ndll Injects a downloaded DLL file.\r\nexe Injects a downloaded EXE file.\r\nadditional Collects additional host information by executing one of the commands in Table 2.\r\nknock_timeout Updates the timer value, which indicates how often Pikabot should send a knock request.\r\nTable 1 - Pikabot tasks description\r\nPikabot also supports the “additional” commands shown in Table 2, which are focused on collecting further\r\nsystem information.\r\nCommand Description\r\nhttps://www.zscaler.com/blogs/security-research/technical-analysis-pikabot\r\nPage 4 of 5\n\nscreenshoot Not implemented.\r\nwhoami Executes the shell command whoami /all.\r\nipconfig Executes the shell command ipconfig /all.\r\nprocesses Collects process information.\r\nTable 2 - Additional Pikabot commands description\r\nIt is worth noting that depending on the network request, Pikabot uses a different URI (which may differ among\r\nsamples). For example, for reporting a command output, the URI may be Duenna/ZuGAYDS3Y2BeS2vW7vm?\r\nAnacrusisCrotalinae=zH4Tfz.\r\nThe network data encryption procedure is similar to the configuration's decryption process. Pikabot encrypts a\r\nnetwork request by following the steps below:\r\n1. The request data is encoded using Base64.\r\n2. Pikabot generates a random 32-byte key and encodes the data again using Base64.\r\n3. Pikabot reads the first 16-bytes of a function prologue and uses these bytes as an IV.\r\n4. The data is encrypted using AES (CBC mode) and encoded with Base64.\r\n5. The 32-byte key is prepended to the encoded data.\r\n6. The hardcoded URI key (e.g. mMG50=) is prepended to the final output.\r\nExplore more Zscaler blogs\r\nSource: https://www.zscaler.com/blogs/security-research/technical-analysis-pikabot\r\nhttps://www.zscaler.com/blogs/security-research/technical-analysis-pikabot\r\nPage 5 of 5",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia",
		"MITRE"
	],
	"references": [
		"https://www.zscaler.com/blogs/security-research/technical-analysis-pikabot"
	],
	"report_names": [
		"technical-analysis-pikabot"
	],
	"threat_actors": [],
	"ts_created_at": 1775434374,
	"ts_updated_at": 1775791277,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/f27e787f93d046bdee629b90179fa4026074320d.pdf",
		"text": "https://archive.orkl.eu/f27e787f93d046bdee629b90179fa4026074320d.txt",
		"img": "https://archive.orkl.eu/f27e787f93d046bdee629b90179fa4026074320d.jpg"
	}
}