{
	"id": "1362f4dd-70b8-4215-9bc5-95acb4e98786",
	"created_at": "2026-05-05T02:45:12.48679Z",
	"updated_at": "2026-05-05T02:46:36.971085Z",
	"deleted_at": null,
	"sha1_hash": "46555680be49926a4d2a7468afa827a10298f65d",
	"title": "The Brothers Grim",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 3415208,
	"plain_text": "The Brothers Grim\r\nArchived: 2026-05-05 02:05:00 UTC\r\nExecutive summary\r\nRansomware activity increased drastically over the past couple of years and became the face of cybercrime by\r\n2021.\r\nAccording to the “Ransomware Uncovered 2020-2021” report, the number of ransomware attacks increased by\r\nmore than 150% in 2020. The attacks grew in not only number but also scale and sophistication — the average\r\nransom demand increased by more than twofold and amounted to $170,000 in 2020. The norm is shifting toward\r\nthe millions: the Colonial Pipeline allegedly paid USD 5 million to get its business back. The case propelled the\r\nquestion of ransomware to the top of the political agenda.\r\nIn the meantime, 2021 continues to prove that no company is immune to the ransomware plague. Ransomware\r\noperators are not concerned about the industry so long as the victim can pay the ransom. The prospect of quick\r\nprofits motivates new players to join big game hunting. Ransomware operations show no signs of slowing down.\r\nThe gangs evolve. They change their tactics, defense evasion techniques, and procedures to ensure that their illicit\r\nbusiness thrives.\r\nGiven that ransomware attacks are conducted by humans, understanding the modus operandi and toolset used by\r\nattackers is essential for companies that want to avoid costly downtimes. Ultimately, knowing how ransomware\r\ngangs operate and being able to thwart their attacks is more cost-effective than paying ransoms.\r\nOne of the underlying trends of 2021 to keep in mind is the use of commodity malware. The infamous\r\nransomware gang Ryuk, which is responsible for many high-profile cyber heists (including the attack on the\r\nBaltimore County Public Schools system) followed suit. The most recent addition to their arsenal, which is yet to\r\nbe explored, is the malware called GrimAgent.\r\nOur team did the first comprehensive analysis of the GrimAgent backdoor. It is intended mainly for reverse\r\nengineers, researchers and blue teams so that they can create and implement rules that help monitor this cyber\r\nthreat closely. Group-IB’s Threat Intelligence team has created Yara and Suricata rules as well as mapped\r\nGrimAgent’s TTPs according to the MITRE ATT\u0026CK® matrix.\r\nIntroduction\r\nGrimAgent is a malware classified as a backdoor and that has been used as a prior stage to Ryuk ransomware. The\r\nransomware family appeared in 2018 and was mistakenly linked to North Korea. Later on, it was attributed to two\r\nthreat actors, FIN6 and Wizard Spider.\r\nhttps://blog.group-ib.com/grimagent\r\nPage 1 of 24\n\nGiven the limited knowledge about the links between Ryuk and GrimAgent, we decided to research GrimAgent\r\nsamples discovered in the wild and show how GrimAgent is connected to Ryuk. The article analyzes the\r\nexecution chain, TTPs, and the malware’s relevant characteristics.\r\nThe first known GrimAgent sample (SHA-256:\r\n03ec9000b493c716e5aea4876a2fc5360c695b25d6f4cd24f60288c6a1c65ce5) was uploaded to VirusTotal on\r\nAugust 9, 2020 at 19:20:54. It is noteworthy that an embedded binary into the initial malware was employed\r\nhttps://blog.group-ib.com/grimagent\r\nPage 2 of 24\n\nand had a timestamp of 2020-07-26, the timestamp could have been altered but the dates coincide with our\r\nhypothesis about the new malware.\r\nFrom a functionality point of view the malware is a backdoor, but it behaves like a bot. We analyzed a completely\r\ndifferent custom network protocol where the infected computer would register on the server side and provide a\r\nreconnaissance string of the client, after which it would constantly make requests to the C\u0026C server asking which\r\nare the next commands to be executed. During our research we performed several tests with the aim to get the next\r\nstage payload. We infected several testing devices with different settings, but did not manage to obtain any\r\npayloads. Based on our findings, it is likely that the actor implemented different defense and delivery mechanisms\r\nto protect the integrity of its systems and ensure that the operations are flawless — which is not uncommon and\r\nwe have witnessed this in the past. This means that GrimAgent developers potentially implemented threat\r\ndetection systems capable of detecting sandboxes or bot requests in order to protect themselves from things such\r\nas analysis, added filters based on geolocation and blacklists/whitelists. The extreme meticulousness shown by the\r\nactors behind the malware and their attention to detail when carrying out attacks is both relevant and remarkable.\r\nAccording to Group-IB’s Threat Intelligence \u0026 Attribution system, Ryuk operators used different commodity\r\nmalware over time (including Emotet, TrickBot, Bazar, Buer, and SilentNight) to deploy ransomware. However,\r\nthe big blows suffered by Trickbot and Emotet could have prompted Ryuk operators to partner with GrimAgent. A\r\ndetailed analysis of the latest TTPs used by various ransomware strains is available in the Ransomware Uncovered\r\n2020/2021 report.\r\nConnections to Ryuk\r\nAnalyzing the GrimAgent Command and Control domain revealed an interesting URL. When making a request on\r\nthe domain, the Command and Control server returns a content designed for victims of the Ryuk ransomware, in\r\naddition to revealing its location on the TOR network.\r\nCommand and control landing page:\r\nFig. 1: C2 landing page\r\nCommand and control landing page source code:\r\nhttps://blog.group-ib.com/grimagent\r\nPage 3 of 24\n\n\u003c html \u003e \u003c body \u003e \u003c style \u003e p:hover {\r\n background: black;\r\n color:white\r\n} \u003c /style\u003e \u003c p onclick = 'info()' style = 'font-weight:bold;font-size:127%;\r\ntop:0;left:0;border: 1px solid black;padding: 7px 29px;width:85px;' \u003e \r\ncontact \u003c /p\u003e\r\nbalance of shadow universe\r\n \u003c div style = 'font-size: 551%;font-weight:bold;width:51%;height:51%;overflow:auto;margin:auto;posit\r\ny\r\nu\r\nk \u003c /div\u003e \u003c /body\u003e\r\nFig. 2: Ryuk Cpanel (TOR)\r\nThese findings show that the GrimAgent backdoor is being used as a part of Ryuk’s operations. We have not\r\nobserved any selling or advertising related to GrimAgent on underground forums, nor any use of the malware in\r\nthe infection chain of any other malware besides Ryuk. Based on the above facts we believe that this malware is\r\nused by the same TA that uses Ruyk ransomware and does not use MaaS.\r\nGrimAgent in a nutshell\r\nFile Information\r\nMD5 015E5A1FA9D8151EE51D6E53E187FBB2\r\nSHA1 163917CED2D1B33023FA47ECA8BEEC3EA871D517\r\nhttps://blog.group-ib.com/grimagent\r\nPage 4 of 24\n\nSHA256 63BD614434A70599FBAADD0EF749A9BB68F712ACA0F92C4B8E30A3C4B4DB5CAF\r\nCPU 32-bit\r\nSize 270,945 (bytes)\r\nCompiler\r\nstamp\r\nOct 31 22:57:25 2020\r\nDebugger\r\nstamp\r\nOct 31 22:57:25 2020\r\nResource\r\nlanguage\r\nRussian\r\nFunctionality\r\nRetrieve information about the victim:\r\nIP and country code\r\nDomain\r\nVendor\r\nBuild version\r\nOS\r\nArch\r\nUsername\r\nPrivileges\r\nuser_id (computed to identify infected clients)\r\nAES key obtained from C2 to encrypt the communications\r\nExecute\r\nExecute shellcode (MZ launcher)\r\nDownload and execute\r\nUpdate\r\nExecute DLL (MZ launcher trampoline)\r\nEncryption/decryption scheme\r\nTwo decryption keys used to decrypt the strings (decrypted by the same algorithm).\r\nFour keys are used:\r\n1. Hardcoded server public RSA key: Used to encrypt the first request to the Command and Control server and\r\nregister the infected client on the server side.\r\n2. Generated client RSA public and private keys: Both stored at the config file.\r\nhttps://blog.group-ib.com/grimagent\r\nPage 5 of 24\n\na. Public RSA key\r\ni. Used to compute the user_id in order to track and identify infected users.\r\nii. Sent to C2 on the first request along with client reconnaissance; used to encrypt\r\nthe AES key sent by C2.\r\n3. Used to compute the user_id in order to track and identify infected users.\r\nb. Private RSA key: Used to decrypt the AES key received.\r\n4. AES key: Used on command and control further communications (symmetric encryption).\r\nFig. 3: Execution flow diagram\r\n*Command 6 has been added on new versions of the malware, check “Dealing with newer GrimAgent versions”\r\nsection.\r\nhttps://blog.group-ib.com/grimagent\r\nPage 6 of 24\n\nIn-depth analysis\r\nThis section details the malware’s behavior. It covers the following points:\r\nBypassing anti-analysis mechanisms\r\nMalware execution\r\nNetwork protocol\r\nBypassing anti-analysis mechanisms\r\nOverlapping instruction obfuscation\r\nOur investigation involved dealing with anti-analysis techniques, which complicated our task of analyzing the\r\nmalware in addition to breaking the IDAPro Hex-Rays display view.\r\nBasically, the execution flow has been altered with the entire code region between the pusha and popa\r\ninstructions, as well as the stack usage. This code region does not perform any relevant actions while executing\r\nthe binary, so we can NOP all these instructions.\r\nFig. 4: Anti-analysis technique at WinMain\r\nOnce done, we can set WinMain as a function and try to visualize the pseudocode as well as the IDA graph mode.\r\nString encryption\r\nhttps://blog.group-ib.com/grimagent\r\nPage 7 of 24\n\nWhen executing the WinMain routine, the first step is to decrypt the key that will later be used to decrypt the\r\nsensitive strings needed to continue its execution. In order to decrypt the key, the malware uses a function which\r\nmay vary depending on the sample.\r\nThen, decrypt some basic strings to be able to execute their most basic actions and decrypt the second key that\r\nwill be used on the decryption of all the necessary strings for their complete and correct execution.\r\nIDA Python script\r\nSince, in most cases, it is better to automate than perform a task manually, we use IDA Python to ensure it is done\r\nquickly.\r\nIDAPro script: https://github.com/apriegob/GrimAgent/blob/main/IDAPro/IDAPro_string_decryptor.py\r\nThe “decrypt_strings_func” and “decrypt_strings2_func” values should be changed to the memory location where\r\nthey are placed. The value of key1 and key2 will be the buffers that contain the keys used by the malware (which\r\nare easily obtained through the debugger).\r\nMalware execution\r\nThe execution of GrimAgent from can be divided into the following subsections.\r\nDecrypting strings and calculating indirect calls\r\npath_mutex_buffer\r\nMutex\r\nConfiguration file\r\nFirst launch of the malware\r\nHandling commands\r\nDealing with newer GrimAgent versions\r\nDecrypting strings and calculating indirect calls\r\nThis is the first step the malware must take because it needs to decrypt the sensitive and relevant strings as well as\r\ncalculate the indirect calls in order to continue with its normal execution flow.\r\npath_mutex_buffer (deprecated)\r\nOne of the most relevant features of GrimAgent is that it uses the last 64 bytes of the binary for two purposes:\r\n1. Compute mutex name\r\n2. Check path for store malware configuration\r\nThis means that after decrypting strings and calculating indirect calls, GrimAgent will read itself, and more\r\nspecifically its last 64 bytes. Henceforth we will call this set of bytes “path_mutex_buffer“.\r\nhttps://blog.group-ib.com/grimagent\r\nPage 8 of 24\n\nFig. 5: GrimAgent sections\r\nMutex\r\nThe function that creates the mutex will iterate over the 64 bytes, checking if the value is alphanumeric and, if it is\r\nnot, the function will try to transform it into an alphanumeric value.\r\nIf the name of the mutex created is not valid, it will create a mutex with the hardcoded name “mymutex”. In case\r\nof an error, the execution will terminate.\r\nhttps://blog.group-ib.com/grimagent\r\nPage 9 of 24\n\nFig. 6: Computing Mutex\r\nConfiguration file\r\nThe malware will check if it has a specific path hardcoded. The path corresponds to the buffer that it read in its\r\nlast 64 bytes (“path_mutex_buffer“).\r\nCustom path syntax (deprecated):\r\nSHA256 [unicode(FilePath)] + SHA256 [unicode(Filename)] → length of SHA256 x 2 = 64 (0x40) bytes\r\nTo do so, the malware will make recursive calls to check if the SHA256 of the different writable paths and\r\nfilenames matches with the buffer retrieved.\r\nIn terms of writing its config, the malware has three possibilities:\r\n1. Custom Path → SHA256[unicode(Path)] + SHA256[unicode(FileName)]: The malware will start from\r\n“C:\\” path, and it will call a function recursively (find_custompath) in which it will compute the SHA256\r\nof the different directories to see if it matches with the first 32 bytes of “path_mutex_buffer” and, if It does,\r\nit will try to find the filename by performing the SHA256 of every filename in the matched directory by\r\nchecking the next 32 bytes.\r\n2. Hardcoded path 1 → C:\\Users\\Public\\config; used if unable to get the custom path.\r\n3. Hardcoded path 2 → C:\\Users\\Public\\reserve.sys\r\nhttps://blog.group-ib.com/grimagent\r\nPage 10 of 24\n\na. This path will be used when a custom path is matched with the character ‘ * ‘, for example: “C:\\Users\\*”\r\nb. There is a string “reserve.exe” that will replace the last 3 characters from “exe” to “sys” during\r\nexecution time.\r\nWith the config path defined, the malware checks if there is a valid config file:\r\nIf the config file is less than 0x32 bytes in size, it has no valid config. Otherwise, the config will be\r\nconsidered as valid and continue the execution to an infinite loop that will perform C2 requests asking for\r\nnew commands to execute.\r\nA valid configuration file will contain three different objects:\r\n1. Generated client public RSA key: to compute user_id and encrypt the AES key that the C2 will send.\r\n2. Generated client private RSA key: to decrypt the AES key sent by C2.\r\n3. AES encrypted key received from C2: to encrypt/decrypt C2 communications.\r\nFirst launch of the malware\r\nWhen the malware is executed, the first step is to decrypt the strings and create a mutex based on the last 64 bytes\r\n(path_mutex_buffer), but there are cases where GrimAgent binaries have been compiled without these last bytes.\r\nUnable to read its last 64 bytes\r\nThis execution branch can only occur on malware first execution. If we enter this execution branch, the malware\r\nwill perform the following actions:\r\nRetrieve the writable path\r\nCompute the new path_mutex_buffer based writable path and filename\r\nCopy itself into the writable path\r\nAppend the new path_mutex_buffer at the end of the new copied binary\r\nSet persistence of the copied binary\r\nTask scheduler\r\nRegistry key\r\nExecute copied malware\r\nDelete old sample\r\nExits\r\nReconnaissance\r\nAt this point, the malware will have been able to get its path to store its configuration file where it will store the\r\nkeys necessary for its execution and communication with C2 as well as for creating a mutex to avoid conflicts if it\r\nis executed several times.\r\nGrimAgent will then perform a system reconnaissance and collect device information. It will collect the\r\nfollowing fields:\r\nCountry code (api.myip.com)\r\nhttps://blog.group-ib.com/grimagent\r\nPage 11 of 24\n\nIP (api.myip.com)\r\nVendor\r\nDomain\r\nBuild Version\r\nOS\r\nArchitecture\r\nUsername\r\nPrivileges (A/U)\r\nA = Admin\r\nU = User\r\nTo retrieve fields such as the internet IP address and country code, which will append into the reconnaissance\r\nstring, the malware will use public resources. In our case, this means performing a GET request to api.myip.\r\nRSA key generation and user_id\r\nGrimAgent calls a function in order to compute a user_identifer (used to identify the infected user) and\r\ngenerates the client RSA public and private keys:\r\n1. Generates the client RSA public and private keys by using CryptGenKey.\r\n2. Retrieves the new generated client RSA public key in PEM format (with the headers ‘—–BEGIN\r\nPUBLIC KEY—–‘ and ‘—–END PUBLIC KEY—–‘).\r\n3. Computes the hash for that key, which generates a random id to be included in the reconnaissance string\r\n(used as a user identifier): This user_id would be different for every execution but, to be able to identify the\r\ninfected user and not generate a random key each time, the new key will be stored and used to compute the\r\nuser_id when needed.\r\n4. Retrieves the generated client RSA private key.\r\n5. Stores both public and private keys in the config file.\r\nThe next screenshot shows the finished string obtained by the malware with the value of user_id added at the end.\r\nhttps://blog.group-ib.com/grimagent\r\nPage 12 of 24\n\nFig. 7 – Complete victim reconnaissance. NB: Country code and IP address values are invalid because we\r\nexecuted the malware in a controlled environment without internet access.\r\nExample of a reconnaissance string:\r\n\u003cpre\u003evendor=\u003cvendor_id\u003e\u0026country=\u003ccountry\u003e\u0026ip=\u003cip\u003e\u0026domain=\u003cdomain\u003e\u0026build_version=\r\n\u003cbuild_version\u003e\u0026systemOS=\u003cOS\u003e\u0026registry=\u003c32/64\u003e\u0026username=\u003cusername\u003e\u0026privileges=\u003cU/A\u003e\u0026id=\r\n\u003cuser_id\u003e\u003c/pre\u003e\r\nNext, the malware sends this information along with the generated client public RSA key to the Command\r\nand Control server and waits until the reply contains ‘fr’ or ‘ar’ as the first characters in the reply. Only if the first\r\ncharacters received are ‘fr’ will the malware store the reply as hex values. The reply from C2 will be a\r\nsymmetric encryption key (AES) that the malware will use from then on in order to interact with the\r\nCommand and Control server.\r\nThe malware will JMP to the ‘exist_conf‘ location and proceed with the execution.\r\nHandling commands\r\nWe land in this section once the malware obtains a valid configuration and is about to enter an infinite loop where\r\nit will make requests for new commands to the Command and Control server. For GrimAgent, the configuration\r\nfile will be valid if it is ≥ 32 bytes.\r\nReading config: the AES Key\r\nIn this case, the malware will decrypt and import the AES key received from the C2 which will be in the config\r\nfile. Then, the key will be used in order to encrypt and decrypt subsequent communications between the infected\r\nclient and the C2.\r\nCommands\r\nhttps://blog.group-ib.com/grimagent\r\nPage 13 of 24\n\nGrimAgent will start an infinite loop (while 1) in order to request the next commands to execute to the Command\r\nand Control server. The loop is made up of three points:\r\n1. C2 request and decryption\r\n2. Execute command\r\n3. Sleep [180-190] seconds and start again\r\nCommand table:\r\nCommand id Functionality\r\n1 Execute\r\n2 Execute Shellcode (MZ Launcher)\r\n3 Download and Execute (Schtask)\r\n4 Update\r\n5 Execute DLL (MZ trampoline)\r\n6 Download and Execute (ShellExecuteW)\r\nThe commands and other malware features have been updated in newer versions of the malware, explained at\r\nDealing with newer GrimAgent versions section.\r\nOn receiving the C2 reply, the malware parses the command and executes it.\r\nCommand 1: Execute\r\nAt this point, the malware uses the same logic for execution that we have already seen. It creates a task with a\r\nrandom name and length 8. The task will be executed through the task scheduler with maximum privileges.\r\nAfterwards, the malware removes the task to avoid being detected.\r\nCommand 2: Execute shellcode (MZ launcher)\r\nWhen command ‘2’ is received, the malware parses the shellcode received as an argument. The malware checks\r\nfor ‘\\\\’ and ‘x’ bytes, which are common delimiters used in binary data.\r\nAfter parsing the shellcode, the malware calls the ‘drop_and_execute_shellcode’ function, which drops an\r\nexecutable MZ (embedded into initial binary) with the appended shellcode into a writable directory that\r\nwill act as a launcher of the received binary data. The embedded MZ contains the compiler stamp from July\r\n2020. This point in time could be when the first version of GrimAgent appeared. Moreover, it contained another\r\nembedded MZ with the same behavior, but designed for 64b architecture systems. The 64b launcher has nearly the\r\nsame time stamp.\r\nhttps://blog.group-ib.com/grimagent\r\nPage 14 of 24\n\nFig. 8: MZ Shellcode/DLL launcher properties\r\nThe most interesting part of the new executable is how it executes the shellcode using sentinel bytes, with two\r\npossibilities:\r\n1. @@@@@@@ + shellcode\r\n2. @@@@@@d + DLL path + ‘:’ + arguments (used at command 5)\r\nIn both cases, the malware parses the sentinel bytes and executes the shellcode/DLL.\r\nThe sentinel bytes are used to calculate where the shellcode is located and be able to execute the malicious\r\ncode.\r\nOnce dropped, this MZ launcher will be executed through task scheduler with a random name of 8 alphanumeric\r\ncharacters.\r\nBy executing this command, the malware will also try to privesc by executing the payload as the highest\r\nprivileges possible. It will then sleep for 195-205 seconds, after which the malware will delete the newly created\r\ntask.\r\nCommand 3: Download and Execute (Schtask)\r\nThis is the basic functionality found in many malware families. It is the common download and execute command\r\nfunctionality.\r\nIn order to receive the payload after the request of a new command, GrimAgent performs a request to obtain the\r\npayload to the specified URI received as an argument. The payload will be dropped into a writable folder and\r\nexecuted through the task scheduler, as in command 1.\r\nCommand 4: Update\r\nWhen this command is received, the malware updates itself by dropping the new updated GrimAgent file into its\r\ncurrent directory and appending padding bytes (this action will change the file hash, used as a defensive\r\nhttps://blog.group-ib.com/grimagent\r\nPage 15 of 24\n\nmechanism) as well as the same path_mutex_buff at the end of the new binary. By appending these bytes, the\r\nmalware creates the same mutex and checks for the same custom path for the config file. When finished, it runs\r\nthe new updated binary (ShellExecuteW) and exits the process.\r\nFig. 9: Updated GrimAgent\r\nCommand 5: Execute DLL\r\n(MZ launcher trampoline) This command is very similar to command 2. The function is called with three\r\nparameters:\r\n1. Payload size to be received by C2 on the next request\r\n2. DLL arguments\r\n3. Bool if the DLL is 32b or 64b\r\nAs in previous commands, the malware will receive the URI to download the payload and, once executed, it will\r\nobtain a writable directory in order to be able to drop payloads. It will then perform a GET request to the URI in\r\norder to download the DLL to be executed.\r\nNext, the malware will drop the DLL launcher (MZ) with the sentinel bytes “@@@@@@d” and append (at the\r\nnext bytes) the path of the DLL to be executed + “:” + arguments. The file extension of the DLL launcher will be\r\n“.exe”. On the other hand, it will also drop the DLL to be executed (with the file extension .dll).\r\nSentinel bytes syntax:\r\n@@@@@@d DLL_path : arguments\r\nOnce everything has been prepared, the malware will execute the launcher through the task scheduler and this will\r\nact as a stepping stone for executing the DLL, sending the previously obtained arguments.\r\nhttps://blog.group-ib.com/grimagent\r\nPage 16 of 24\n\nFig. 10: DLL execution\r\nCommand 6: Download and Execute (ShellExecuteW)\r\nThis command obtains the payload by making a request to the URI (received as the command argument), drops it\r\ninto the current directory and executes through a ShellExecuteW call.\r\nThis command was found in the newer versions of the malware.\r\nDealing with newer versions of GrimAgent\r\nWhile working on this article, we found some new GrimAgent samples in the wild with variations from the\r\nversion explained above.\r\nAs a sample of the different changes detailed below, we have the hash SHA256 –\r\nD6EE553F52F20127301F737237B174EF6241EC9049AB22155DCE73144EF2354D, which presents variations\r\nsuch as:\r\nHardcoded mutex name “T10”: This malware version does not generate a mutex name; instead, it creates\r\none based on a hardcoded value.\r\nHardcoded config path “\\Users\\Public\\microsoft.cfg”: As with the mutex, a path is no longer defined for\r\nthe configuration; instead, it is hardcoded in the sample.\r\nCopies itself into a hardcoded path and filename (“\\Users\\Public\\svchost.exe”), and then sets\r\npersistence through the registry Run key. The execution is done directly through the call ShellExecuteW\r\n\u003cpath\u003e instead of schtask.\r\nThe function that searches writable directories by creating and writing a new file with a random integer\r\ninside has been removed.\r\nhttps://blog.group-ib.com/grimagent\r\nPage 17 of 24\n\nHardcoded payload path: Commands that used writable paths found now use a hardcoded path\r\n“\\Users\\Public\\system+\u003crandom\u003e.exe“, for example command 3 (download and execute) and command 5\r\n(execute DLL).\r\nAdded command 6 (drop and execute into the current path): The file will be executed through a\r\nShellExecuteW call.\r\nIt does not contain path_mutex_buffer (last 64 bytes in the binary).\r\nUpdated command 4: The screenshot below compares the command 4 (update) of both GrimAgent\r\nversions. On the left is the old one (already explained in the article) and on the right is the updated one,\r\nwhich appends ’00’ bytes in the last 64 bytes of the updated binary and ignores whether or not it can read\r\nthe last 64 bytes of the binary.\r\nFig. 11: Comparison of GrimAgent command 4 versions\r\nThe changes mean that the malware is being actively developed and it is highly likely that it will present even\r\nmore different versions and changes over time. The fact that some forms of execution have been changed (such as\r\nthe use of “path_mutex_buffer“) does not mean that a threat actor will never use the former malware version\r\nagain, so we must remain attentive and follow any new updates closely.\r\nNetwork protocol\r\nBase protocol\r\nGrimAgents implements a custom network protocol in order to interact with the Command and Control server,\r\nand it follows the following syntax:\r\nHeader = MSG Flag Padding Padding Size\r\nMSG: The message to be sent.\r\nFlag: The value used to indicate what kind of connection needs to be made with the C2.\r\na: On requests for new commands. It makes a POST request to the Command and Control server.\r\nd: First request to the C2. It makes a POST request to the Command and Control server to register\r\nthe client on the server side.\r\n*r: It is used internally in the malware, although it is not added directly in the request to the C2.\r\nWhen the function responsible for contacting the Command and Control server is called with this\r\nflag, the malware will make a GET request to a URI in order to obtain (read) the payload (the next\r\nstage).\r\nhttps://blog.group-ib.com/grimagent\r\nPage 18 of 24\n\nPadding: Random generated values.\r\nPadding Size: The last two bytes are the decimal value of padding length – 3 (decimal format).\r\nRandomization of connection fields\r\nTo establish a connection with the C2, GrimAgent randomizes some values as an evasive mechanism and tries to\r\nchange request fields on the C2 request, such as User-Agent, referer, content-length and language.\r\nAs an interesting detail, if you look at the languages that the malware tries to adopt in the ‘Accept-Language’ field\r\nwhen connecting to the Command and Control server, it is possible that there is a relationship with the group’s\r\ncurrent targets. If so, they would be the following:\r\nUnited Kingdom\r\nUnited States\r\nSpain\r\nFrance\r\nDetection opportunities\r\nWe have examined how GrimAgent behaves throughout its execution, when and what it does. We will now\r\nanalyze the various opportunities to detect the malware. We can use the way in which it executes these actions to\r\nmonitor the behavior in the different defense mechanisms or match them using Sigma, Yara or Suricata rules.\r\nDetection opportunity 1: Persistence\r\nOn the first run, the malware copies itself to another directory, runs while establishing persistence on itself, and\r\ndeletes the old file. A common path the malware uses is C:/Users/Public. GrimAgent carries out specific calls and\r\nthey can be monitored to identify related behaviors.\r\nCheck the IOC section for the full information about the commands used on the malware persistence.\r\nDetection opportunity 2: Mutex (old malware version)\r\nOne of GrimAgent’s most characteristic factors is using the last 64 bytes of the binary to compute the name of the\r\nmutex. The characteristic can be used to create a behavior rule and therefore predict what mutex name it will\r\ncreate in the system.\r\nAll we have to do is to recreate the algorithm used in your different solutions by taking the last 64 bytes of the file\r\nand compute the possible mutex name. You can spot the algorithm used by the malware in the Mutex section.\r\nDetection opportunity 3: Network\r\nThe first domain to contact is “api.myip.com” in order to obtain the country code and client IP (http://ip-api.com/csv/?fields=query,countryCode) and then make the request to the C2 to obtain the AES key. Once\r\nfinished, it will make periodic requests to the C2 infrastructure to obtain the following commands and/or to get\r\nnext stage payloads. We can take advantage of the usage of the path “/gate.php” in conjunction with specific fields\r\nsuch as the referer (google.com, youtube.com, etc.) when contacting the C2.\r\nhttps://blog.group-ib.com/grimagent\r\nPage 19 of 24\n\nLink to Suricata rule.\r\nDetection opportunity 4: Payload drop\r\nWhile executing the malware commands related to executing shellcode and DLLs, it uses a binary embedded in\r\nthe initial malware. We can create detection rules for this binary and alert our defense teams if a match is found.\r\nThe following Yara rule was created to detect shellcode and DLL launchers (32b/64b) embedded in GrimAgent.\r\nLink to Yara rule.\r\nDetection opportunity 5: Payload execution\r\nAs we have shown throughout the article, to execute payloads GrimAgent uses both the ShellExecute call and\r\nindirect execution through scheduled tasks. Given that it always uses the same syntax on schtasks, we can try to\r\nmatch these actions. As it is suspicious behavior to create a scheduled task and try to execute it nearly at the same\r\ntime as its creation, try to execute it with maximum privileges and delete it.\r\nCheck the IOC section for the full information about the commands used on the payload execution.\r\nHunt or be hunted\r\nWe have created various behaviors as well as static and network rules in order to be able to hunt and detect the\r\nGrimAgent malware family. The following screenshot shows Group-IB’s Managed XDR and how the GrimAgent\r\nsample has been detonated and detected.\r\nFig. 12 – Group-IB Managed XDR detecting GrimAgent malware\r\nConclusion\r\nhttps://blog.group-ib.com/grimagent\r\nPage 20 of 24\n\nThere can be no doubt that we are facing a meticulous, careful and highly skilled adversary. Many have already\r\nfallen victim to Ryuk ransomware, which is known to target large companies, encrypt their content, and ask for\r\nlarge sums of money. When it comes to such threats, all defensive measures are not enough and we believe that\r\nwe must direct our IR teams and companies in intelligence-based environments. We must get ahead of the\r\nadversary before they carry out their attack.\r\nTo help the cyber community better detect the adversary, IOC and Rules sections are provided below.\r\nI would like to give a special thank you to my father, who has always supported me and lent me a helping hand\r\nwhen I have needed him. Thank you, always.\r\nAlbert\r\nMITRE ATT\u0026CK\r\nhttps://blog.group-ib.com/grimagent\r\nPage 21 of 24\n\nIndicators of Compromise\r\nTask scheduler\r\narrow_drop_down\r\n/CREATE /SC ONSTART /TN [A-Za-z0-9]{4,9} /TR “\u003cpath to file\u003e” /f\r\nhttps://blog.group-ib.com/grimagent\r\nPage 22 of 24\n\n/CREATE /SC ONSTART /TN [A-Za-z0-9]{4,9} /TR “\u003cpath to file\u003e” /f /RL HIGHEST\r\n/CREATE /SC ONCE /ST hh:mm:ss /TN [A-Za-z0-9]{8} /TR “\u003cpath to file\u003e” /f\r\n/CREATE /SC ONCE /ST hh:mm:ss /TN [A-Za-z0-9]{8} /TR “‘\u003cpath to file\u003e /f /RL HIGHEST\r\n/DELETE /TN [A-Za-z0-9]{8} /f\r\nFile deletion\r\narrow_drop_down\r\ncmd /c timeout 10 \u0026 del \u003cpath to file\u003e\r\nRegistry\r\narrow_drop_down\r\nREG ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run” /V “microsoft update” /t\r\nREG_SZ /F /D “SCHTASKS /run /tn [A-Za-z0-9]{8}”\r\nDirectories and files\r\narrow_drop_down\r\nC:\\Users\\Public\\config\r\nC:\\Users\\Public\\reserve.sys\r\nCommand and Control server\r\narrow_drop_down\r\nmicrosoftupdate[.]top/gate.php\r\nmicrosoftsystemcloud[.]com/gate.php\r\nchaseltd[.]top/gate.php\r\nHashes\r\nName GrimAgent\r\nMZ Shellcode Launcher\r\n32b\r\nMZ Shellcode Launcher 64b\r\nMD5\r\n015E5A1FA9D81\r\n51EE51D6E53 E187FBB2\r\n5F28D4AB1992685115\r\nBD46726189C92B\r\n530D2FF5A0F1B5FCDF\r\n4442655B570FCA\r\nSHA1\r\n163917CED2D1B33023FA\r\n47ECA8BEEC3E\r\nA871D517\r\n2A2C0DB4D7D018B9AC13\r\n268D1BE0AC9985464691\r\nE8621C3BA3B91EB4D0F80\r\nFB6371028B73CA19626\r\nSHA256 63BD614434A70599FBAA\r\nDD0EF749A9BB68F712AC\r\nAEC3BF81EA6DF2C7F820\r\n10A7D6144CFF67B106BFA\r\n8D20AC7EBB09B5E41594E2\r\n3B5B07596CEA7E7DC4C383\r\nD39BEFFA7AD4E3F7FDF8\r\nhttps://blog.group-ib.com/grimagent\r\nPage 23 of 24\n\nName GrimAgent\r\nMZ Shellcode Launcher\r\n32b\r\nMZ Shellcode Launcher 64b\r\nA0F92C4B8E30A3C4B4DB\r\n5CAF\r\n7BDBDDA8A39FC501\r\nF5D908C\r\nCPU 32-bit 32-bit 64-bit\r\nSize 270,945 (bytes) 8,192 (bytes) 8,192 (bytes)\r\nCompiler\r\nstamp\r\nOct 31 22:57:25 2020 Sun Jul 26 09:55:21 2020 Sun Jul 26 09:55:23 2020\r\nDebugger\r\nstamp\r\nOct 31 22:57:25 2020 Sun Jul 26 09:55:21 2020 Sun Jul 26 09:55:23 2020\r\nResource\r\nlanguage\r\nRussian – –\r\nSource: https://blog.group-ib.com/grimagent\r\nhttps://blog.group-ib.com/grimagent\r\nPage 24 of 24",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://blog.group-ib.com/grimagent"
	],
	"report_names": [
		"grimagent"
	],
	"threat_actors": [],
	"ts_created_at": 1777949112,
	"ts_updated_at": 1777949196,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/46555680be49926a4d2a7468afa827a10298f65d.pdf",
		"text": "https://archive.orkl.eu/46555680be49926a4d2a7468afa827a10298f65d.txt",
		"img": "https://archive.orkl.eu/46555680be49926a4d2a7468afa827a10298f65d.jpg"
	}
}