{
	"id": "0539a167-6436-43d6-ba9f-b0488ca1a5d2",
	"created_at": "2026-04-06T00:10:00.13229Z",
	"updated_at": "2026-04-10T13:11:30.885371Z",
	"deleted_at": null,
	"sha1_hash": "35803cfa08e4810fe7f04c1b8b9c8641fc776fa5",
	"title": "[QuickNote] Technical Analysis of recent Pikabot Core Module",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 4061376,
	"plain_text": "[QuickNote] Technical Analysis of recent Pikabot Core Module\r\nPublished: 2024-01-06 · Archived: 2026-04-05 23:33:57 UTC\r\n1 Votes\r\n1. Overview\r\nIn early February 2023, cybersecurity experts on Twitter issued a warning about a new malware variant/family\r\nbeing distributed by the #TA577 botnet (associated with the same group from #Qakbot). This malware shares\r\nsimilarities with the Qakbot Trojan, including distribution methods, campaigns, and behaviors. It was quickly\r\nnicknamed Pikabot.\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 1 of 27\n\nPikabot consists of two components: loader/injector and core module. It utilizes loader/injector to decrypt and\r\ninject the core module. Core module then performs malicious behaviors, including gathering information about\r\nthe victim machine, connecting to command and control server to receive and execute arbitrary commands,\r\ndownloading and injecting other malware.\r\nPikabot is continuously upgraded, employing various anti-analysis techniques and different obfuscation methods\r\nto make it difficult for analysts to understand its behavior. In the next section of this article, I will focus on\r\nanalyzing the Pikabot core module, including:\r\nHow Pikabot obfuscates and decrypts strings.\r\nHow Pikabot retrieves API addresses.\r\nHow Pikabot slows down the analysis process.\r\nHow Pikabot generates victim uuid.\r\nCollecting information from the victim’s machine.\r\nHow Pikabot decrypts C2 addresses.\r\nHow Pikabot utilizes Syscall.\r\nSample hash: ce742b7cc94a5c668116d343b6a9677523dc13b358294bba3cd248fba8b880da\r\n2. Decrypt string\r\nIn some older versions, to decode strings, Pikabot utilizes a XOR loop to decode encrypted data stored on the\r\nstack:\r\nIn recent versions of Pikabot, the process of decrypting strings has become more sophisticated.\r\nRC4 is used to decrypt encrypted data stored on stack. Each encrypted data has a corresponding RC4 key.\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 2 of 27\n\nThe RC4-decrypted string will be converted to a valid Base64 string (by replacing the character ‘ _ ’ with\r\n‘ = ’) and then decoded using Base64.\r\nFinally, AES-CBC will be used to decrypt the decoded data to return the original string.\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 3 of 27\n\nAES Key and AES IV used in this sample are also decrypted using RC4:\r\nDecrypted AES Key: “ dVOEz=/e/Xf=0WMiz6uR9cZKe+tyb+VJhSu+tfi0HzT2COoz25r4+8osEx4 “\r\nDecrypted AES IV: “ nsdA1ANUAH+K1XhVjnsg92tGMNQG=fsgrqJQ8AtZIacqaYg ”\r\nHowever, Pikabot only uses 32 bytes from the decrypted AES Key and 16 bytes from the decrypted AES IV .\r\nTherefore, the final AES Key and IV used for string decryption are:\r\nAES Key: “ dVOEz=/e/Xf=0WMiz6uR9cZKe+tyb+VJ ”\r\nAES IV: “ nsdA1ANUAH+K1XhV ”\r\nThe entire process was simulated using CyberChef as follows:\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 4 of 27\n\nHere is the CyberChef recipe:\r\n1 https:\r\n3. Retrieve API address\r\nTo get the address of API functions, Pikabot does the following:\r\nIt gets the base address of the corresponding Dll based on the decrypted input string.\r\nDecrypts the API function name, then uses GetProcAddress to optain the real address of the API.\r\nThe function pkb_load_dll_based_on_input_str (0x41E657) has the following code graph:\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 5 of 27\n\nIn this function, Pikabot decrypts relevant strings and compares them to the string passed to the function. If the\r\nstrings match, Pikabot decrypts the name of the corresponding DLL and loads it using LoadLibraryA . Firstly,\r\nPikabot finds the addresses of the GetProcAddress and LoadLibraryA functions using pre-calculated hash\r\nvalues.\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 6 of 27\n\nThe pseudo-code for calculating the hash of API functions is as follows:\r\nBased on the pseudo-code above, we can rewrite it in Python and perform a brute-force to find the API function\r\nname corresponding to the pre-calculated hash values:\r\nWith the API function addresses obtained above, Pikabot will load the corresponding DLL:\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 7 of 27\n\nHere is the list of DLLs that Pikabot will load during execution:\r\nInput string Dll to load\r\nCzYNRd Kernel32.dll\r\nosPFU User32.dll\r\nQJJniV Shell32.dll\r\nMlT3nE Ole32.dll\r\nfWHur Wininet.dll\r\nYgeYS Advapi32.dll\r\nss6HQA NetApi32.dll\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 8 of 27\n\noIOo ntdll.dll\r\nThe function pkb_get_api_addr_by_name_using_GetProcAddress (0x41E636) will decrypt the API function name\r\nand call GetProcAddress to retrieve the function address:\r\n4. Slowing down the analysis process\r\nIn order to slow down the code analysis, Pikabot inserts a large number of meaningless junk functions into the\r\nexecution flow. These functions typically do nothing. This can make it much more time-consuming for analysts to\r\nunderstand the code and identify its malicious behavior.\r\n5. System language check\r\nPikabot checks the system language code of the victim’s machine before executing its main task by using API\r\nfunction GetUserDefaultLangID . In the previous version, if the result returned a region code for a country such\r\nas Russia or Ukraine , the malware would immediately exit without any further activity.\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 9 of 27\n\nHowever, in the version I am analyzing, Pikabot simply checks the return code if it is different from 0x1 , the\r\nfunction pkb_check_default_lang (0x0042F7A0) will return 0x0 :\r\n6. Create Mutex\r\nWhen the result of the function pkb_check_default_lang (0x42F7A0) return 0x0 , Pikabot will continue\r\nexecuting, with the sample I am analyzing it uses the hardcoded mutex name (after decrypting): “ {F0B9756B-5D50-4696-A969-4C9AF7B69188} ” to prevent reinfection on the victim’s machine.\r\n7. Create victim uuid\r\nAfter creating the Mutex as described above, Pikabot creates the victim uuid using the function\r\npkb_collect_victim_info_n_gen_victim_uuid (0x42E233) . The graph code for this function is as follows:\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 10 of 27\n\nThe uuid string is generated based on the information collected from the victim machine, including:\r\nVolume serial number by using API function GetVolumeInformationW . This is a unique identifier\r\nassigned to each physical volume on a computer.\r\ncomputer name by using API function GetComputerNameW . This is the name of the computer that the\r\nmalware is running on.\r\nuser name by using API function GetUserNameW . This is the name of the user who is currently logged on\r\nto the computer.\r\nOS product type by using API function GetProductInfo .\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 11 of 27\n\nThe information collected above will be formatted as follows: “ \u003ccomputer_name\u003e\\\u003cuser_name\u003e|\u003cos_type\u003e “. This\r\ninformation will then be hashed using the algorithm mentioned in 3. Retrieve API address with the hash value\r\nwill be initialized to the value of VolumeSerialNumber .\r\nThe hash value calculated for the collected information along with the VolumeSerialNumber will be futher\r\ncalculate by using function pkb_calc_hash_2 (0x42E123) below:\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 12 of 27\n\nFinally, use the API function wsprintfW to format the uuid string in the format %07lX%09lX%lu :\r\n8. Collecting victim machine information\r\nBefore connecting to the C2 server, Pikabot will collect some information about the victim machine. The function\r\npkb_collect_victim_system_info (0x410E37) performs the following collection tasks:\r\nRetrieves the PEB , gather operating system information, including ( OSMajorVersion , OSMinorVersion ,\r\nOSBuildNumber ), determines whether it is running on a 64-bit operating system or not through the API\r\nfunction IsWow64Process .\r\nCollects the operating system type by using the GetProductInfo .\r\nGathers the computer name and username by calling the GetComputerNameW and GetUserNameW .\r\nCollects CPU information by employing cpuid with the initial value of EAX = 0x80000000 .\r\nObtains information about display devices on the machine through the API EnumDisplayDevicesW .\r\nRetrieves the RAM capacity of the victim’s machine using GlobalMemoryStatusEx .\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 13 of 27\n\nGets the system uptime by utillizing the API funciton GetTickCount .\r\nChecks if its process is running in admin privileges or not through the GetCurrentProcess ,\r\nOpenProcessToken , GetTokenInformation .\r\nRetrieves information about screen resolution using the GetDesktopWindow and GetWindowRect .\r\nCollects the domain name using the API GetComputerNameExW with NameType is\r\nComputerNameDnsDomain .\r\nGathers DomainControllerName , DomainControllerAddress using DsGetDcNameW . If no information is\r\navailable, Pikabot will assign it as “ unknown ”.\r\nNext, Pikabot decrypts information related to pikabot version and stream , my sample has respectively info\r\n“ 1.1.17-ghost ” and “ GG13TH@T@f0adda360d2b4ccda11468e026526576 “. Then, the information about the victim\r\ncollected above will be constructed into a JSON string with the following format:\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 14 of 27\n\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n{\r\n\"Xtt2VRnA\" : \"%s\" ,\r\n\"qleNiC\" : \"%s\" ,\r\n\"LPLLXuTl2\" : \" Win %d.%d %d \" ,\r\n\"0RbIhQuDq\" : % s,\r\n\"6bw35n\" : \"%s\" ,\r\n\"FQkA0G\" : \"%s\" ,\r\n\"bFFqxURzx\" : \"%s\" ,\r\n\"a0xIcXZI\" : % d,\r\n\"LkLMKwP1\" : \"%s\" ,\r\n\"R8N3ujt\" : % d,\r\n\"2sIw0rUG\" : \"%s\" ,\r\n\"UTrXReY\" : \"%s\" ,\r\n\"YoViBQC\" : \"%s\" ,\r\n\"QeMM8\" : \"%s\" ,\r\n\"VLsFyV4d\" : \"%s\" ,\r\n\"EcZbr\" : % d,\r\n\"XKb5WP\" : % d\r\n}\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 15 of 27\n\nAll information after being formatted into a JSON string will be encrypted. The encryption process is as follows:\r\nCall the function pkb_gen_random_chars(0x41BC4A) to generate the session key: aes_key (32 bytes) and\r\naes_iv (16 bytes).\r\nCall the function pkb_gen_random_chars(0x41BC4A) for generating 3 random characters, which was used\r\nas a marker. I will temporarily call it marker .\r\nCall the function pkb_aes_crypt_data (0x40A97A) to encrypt the JSON string with the generated\r\naes_key and iv .\r\nCall the function pkb_base64_encode (0x0040B4DD) to encode the encrypted data above.\r\nThen all information will be stored in the following format: \u003cmarker (rand_3_chars)\u003e\u003caes_key (first 16\r\nbytes)\u003e\u003caes_iv\u003e\u003cencoded data\u003e\u003caes_key (last 16 bytes)\u003e .\r\nFinally, use a loop to iterate through the entire buffer to replace the character ‘ = ’ with ‘ _ ’.\r\nHere is the code flow:\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 16 of 27\n\n9. Information gathering with other commands\r\nIn addition to the information collected as mentioned above, Pikabot also executes the following commands to\r\ngather additional information from the victim’s machine:\r\nnetstat.exe –aon\r\nipconfig.exe /all\r\nwhoami.exe /all\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 17 of 27\n\nThe results of these commands are also encrypted and stored in the same way as above. However, the sample that\r\nI am analyzing is configured as DISABLED .\r\n10. Collect running processes\r\nPikabot call the function pkb_enum_n_collect_all_running_processes (0x415BAF) to gather information about\r\nrunning processes on the victim’s machine by employing the API functions CreateToolhel32Snashot ,\r\nProcess32FirstW và Process32NextW . The graph code of this function is as follows:\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 18 of 27\n\nThe information collected will be compiled in the following format:\r\nThen, the information will also be encrypted and encoded in the same way as described above:\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 19 of 27\n\n11. Decrypt C2 configuration\r\nThe C2 addresses (IP and port) will be decrypted by Pikabot during execution. First, Pikabot performs the\r\ndecryption of C2 encrypted data using RC4, with the decryption key in this sample being “ threadId ”:\r\nHere is the result with CyberChef:\r\nThen, Pikabot decrypts the character “ \u0026 ” and uses it as delimiter to extract the decrypted string above into sub\r\nbase64 strings:\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 20 of 27\n\nResult of the above process when debugged with x32dbg:\r\nNext, Pikabot calls function pkb_decrypt_data (0x41D07B) to perform the task of decrypting the C2 address.\r\nThe graph code of this function is as follows:\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 21 of 27\n\nThe entire decrypting process is as follows:\r\nAllocate buffers to store the AES key and iv .\r\nConvert the string to the valid Base64 string by replacing the character “ _ “ with “ = “.\r\nDiscard first 3 characters of string, take the next 16 characters (bytes) and store them to the buffer to create\r\nthe first part of the AES key .\r\nTake the next 16 characters (bytes) and store them to the buffer to use as AES iv .\r\nTake the last 16 characters (bytes) to make the second part of the AES key , combine it with the first part\r\nto create the complete AES key .\r\nGet the string to be decoded after obtaining the AES key and iv .\r\nPerform Base64 decode.\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 22 of 27\n\nUse AES-CBC with AES key and iv above to decrypt the final C2 data.\r\nPseudocode of the entire process is as follows:\r\nUsing CyberChef, we get the following results:\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 23 of 27\n\nWe can write a Python script to decrypt all the C2 addresses that Pikabot will use:\r\n12. Pikabot uses Syscall\r\nDuring the analysis, we will encounter the following functions:\r\nThe above function will perform the following tasks:\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 24 of 27\n\nIterate over the PEB, check if the loaded dll is ntdll.dll\r\nIf yes, proceed to find API functions starting with “ Zw ” exported by ntdll.dll .\r\nThe found functions will be hashed, and the result will be stored in the format: \u003ccalced_hash\u003e\r\n\u003capi_func_RVA\u003e\r\nThe calculated table will be then sorted by Function RVA in ascending order:\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 25 of 27\n\nFinally, compare the pre-calculated hash value with the table containing the calculated hash values above,\r\nif equal, return the function ID. This ID value is stored in the EAX register:\r\nBased on the hash algorithm, we can find out the API functions that Pikabot will use as follows:\r\n13. References\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 26 of 27\n\nPikaBot Tiny loader that seems very familiar\r\nPikaBot Is Back With a Vengeance – Part 1\r\nPikaBot Is Back With a Vengeance – Part 2\r\nTechnical Analysis of Pikabot\r\nPikabot deep analysis\r\n2023-10-03 (TUESDAY) – PIKABOT INFECTION WITH COBALT STRIKE\r\nPikaBot distributed via malicious search ads\r\nPikabot Loader\r\nEnd.\r\nm4n0w4r\r\nSource: https://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nhttps://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/\r\nPage 27 of 27",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://kienmanowar.wordpress.com/2024/01/06/quicknote-technical-analysis-of-recent-pikabot-core-module/"
	],
	"report_names": [
		"quicknote-technical-analysis-of-recent-pikabot-core-module"
	],
	"threat_actors": [
		{
			"id": "b4f83fef-38ee-4228-9d27-dde8afece1cb",
			"created_at": "2023-02-15T02:01:49.569611Z",
			"updated_at": "2026-04-10T02:00:03.351659Z",
			"deleted_at": null,
			"main_name": "TA577",
			"aliases": [
				"Hive0118"
			],
			"source_name": "MISPGALAXY:TA577",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "22d450bb-fc7a-42af-9430-08887f0abf9f",
			"created_at": "2024-11-01T02:00:52.560354Z",
			"updated_at": "2026-04-10T02:00:05.276856Z",
			"deleted_at": null,
			"main_name": "TA577",
			"aliases": [
				"TA577"
			],
			"source_name": "MITRE:TA577",
			"tools": [
				"Pikabot",
				"QakBot",
				"Latrodectus"
			],
			"source_id": "MITRE",
			"reports": null
		}
	],
	"ts_created_at": 1775434200,
	"ts_updated_at": 1775826690,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/35803cfa08e4810fe7f04c1b8b9c8641fc776fa5.pdf",
		"text": "https://archive.orkl.eu/35803cfa08e4810fe7f04c1b8b9c8641fc776fa5.txt",
		"img": "https://archive.orkl.eu/35803cfa08e4810fe7f04c1b8b9c8641fc776fa5.jpg"
	}
}