{
	"id": "2f7d6a7d-8200-4f85-b90a-b89cb30bc1ba",
	"created_at": "2026-04-06T01:32:40.813072Z",
	"updated_at": "2026-04-10T03:21:44.282066Z",
	"deleted_at": null,
	"sha1_hash": "9b6cb528642f13f221d5248308993741f92ae23a",
	"title": "Raspberry Robin Analysis | ThreatLabz",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 766039,
	"plain_text": "Raspberry Robin Analysis | ThreatLabz\r\nBy Nikolaos Pantazopoulos\r\nPublished: 2024-11-19 · Archived: 2026-04-06 00:07:08 UTC\r\nTechnical Analysis\r\nIn the following sections, we present the features and functionalities of Raspberry Robin, including its obfuscation and anti-analysis methods.\r\nDue to the amount of different components, the analysis is divided into four major sections.\r\n1. Execution layers\r\n2. Obfuscation methods\r\n3. Decoy payload\r\n4. Core layer\r\nExecution layers\r\nThe core functionality of Raspberry Robin is unwrapped after executing a series of different layers. Each layer serves a\r\ndifferent purpose with three of them (highlighted in bold) being the most important. In the table below, we briefly describe\r\nthe functionality of each layer.\r\nExecution Layer\r\nName/Index\r\nDescription\r\nFirst Layer\r\nUses the segments registers GS/CS for code emulation detection and  (XOR) decrypts the\r\nnext layer.\r\nSecond Layer Decompresses (using a modified aPLib algorithm) and executes the next layer.\r\nThird Layer\r\nMeasures the performance of the CPU to verify if Raspberry Robin is executed in an\r\nanalysis/sandbox environment and decrypts the next layer using the RC4 algorithm.\r\nFourth Layer Decrypts (via XOR) and executes the next layer.\r\nFifth Layer Decompresses (with a modified aPLib algorithm) and executes the next layer.\r\nSixth Layer\r\nRuns a series of anti-analysis techniques and executes a decoy payload if an analysis\r\nenvironment is detected. Otherwise, it decrypts the next layer using the Rabbit stream\r\ncipher.\r\nSeventh Layer Decrypts (using XOR) and executes the next layer.\r\nEighth Layer Decompresses (using a modified aPLib algorithm) and executes the core layer.\r\nTable 1: Raspberry Robin execution layers.\r\nhttps://www.zscaler.com/blogs/security-research/unraveling-raspberry-robin-s-layers-analyzing-obfuscation-techniques-and\r\nPage 1 of 18\n\nANALYST NOTE: Even though this is not mentioned in the table above, recent samples of Raspberry Robin do a filename\r\ncheck in the initial executable file. Specifically, the binary compares its filename with the string  loaddll . We assess that\r\nthe purpose of this check is to detect commercial sandboxes. Moreover, there are code checks to detect inline hooking of\r\nWindows APIs.\r\nThe relationship among the different layers is shown in the figure below:\r\nFigure 1: High-level diagram of the multi-layered architecture of Raspberry Robin.\r\nFirst execution layer\r\nThe first layer performs the following anti-analysis actions to detect code emulators:\r\nVerifies that the code segment register (CS) holds the correct value ( 0x23 ). In the event of an incorrect value, the\r\nprocess crashes.\r\nSwitches the value of the global segment register and calculates how many iterations were required to reset it to the\r\ndefault value ( 0x2B ) due to context switches. Then, the first layer uses the calculated value to determine if the code\r\nhas been emulated. This operation takes place multiple times (4,070 times in the samples we analyzed) and can be\r\nreproduced with the following Python code:\r\ncounter = 0\r\nfor _ in range(4070):\r\n calculated_gs_value = switch_gs_value()\r\nseeder = ((-counter - 1 ) ^ 0x1f) \u0026 0xff\r\nval_1 = rol(counter, seeder, 32) \u0026 0xffffffff\r\nval_2 = rol(calculated_gs_value, seeder, 32) \u0026 0xffffffff\r\nrotation_bits = (-((-counter - 1) ^ 0x3F)) \u0026 0xff\r\ncounter = rol( (val_2 | val_1) \u0026 0xffffffff, rotation_bits, 32)\r\nif counter == 0xFFFF:\r\nprint(\"Detection passed\")\r\nANALYST NOTE: Emulation detection with the segment register GS has been previously documented. If the last anti-analysis technique does not pass successfully, the code enters an infinite loop state since it passes an incorrect key value for\r\nthe array table of the flattened control flow (which will be discussed later).\r\nThird execution layer\r\nhttps://www.zscaler.com/blogs/security-research/unraveling-raspberry-robin-s-layers-analyzing-obfuscation-techniques-and\r\nPage 2 of 18\n\nThe third layer uses an interesting trick, which is quite effective in detecting an analysis environment, even when set up on a\r\nphysical machine. Specifically, Raspberry Robin (ab)uses a write-combining technique. The use cases for this method are\r\nlimited and usually applied only in critical-performance operations (e.g. in graphics programming). Consequently, this\r\ntechnique affects the system's cache model in different ways:\r\nPrevents data caching.\r\nReduces the CPU overhead since there are less write-operations. \r\nCombining the information above with the fact that analysis environments (virtual or physical) have a limited amount of\r\nresources, Raspberry Robin uses this limitation to detect analysis environments, which either do not provide hardware\r\nsupport for this operation or their write/read operations are slow. The anti-analysis method can be reproduced with the\r\nfollowing steps and the C++ code here.\r\nAllocates a large amount of virtual memory (size of 16,474,112 bytes) with the flags  PAGE_WRITECOMBINE\r\n/PAGE_READWRITE . \r\nOnce the memory has been allocated, a new thread starts to increment a global variable by one.\r\nThe primary thread reads the global variable and starts writing a hardcoded-byte (different per sample) to the entire\r\nallocated memory area.\r\nAfter completing the operation, the completion time is calculated by reading again the (now increased) global\r\nvariable and subtracting from it the old value.\r\nRepeats the same process with a read operation from the allocated memory.\r\nLastly, the result from the write operation is divided with the result of the read operation. If the result is higher than\r\nor equal to the value 6 for six times, then the check is passed successfully. Otherwise, the code does not proceed to\r\nthe next layer.\r\nANALYST NOTE: The expected minimum return value for the method above might vary from sample to sample. For\r\nexample, recent samples have increased this variable.\r\nIf the anti-analysis method does not detect an unusual behavior (as described above), then the fourth layer is decrypted using\r\nthe RC4 algorithm.\r\nSixth execution layer\r\nThe sixth execution layer includes the majority of the anti-analysis techniques. Moreover, if an anti-analysis method is not\r\npassed in this layer successfully, then Raspberry Robin deploys a decoy payload. \r\nInterestingly, this layer does not execute its functionality (the anti-analysis methods) immediately. Instead, it replaces any\r\nstack addresses, that point to any address of the code segment of the initial executable file, with the address of the malicious\r\nfunction. This results in the execution of this layer when a return (ret) instruction executes any of the modified pointers.\r\nTo accomplish this, this layer follows the procedure described below.\r\nStarts by reading the name of the current file and compares its checksum with the checksum of two (currently\r\nunknown) filenames. If there is a match, then the  LDR_DATA_TABLE_ENTRY  field  ObsoleteLoadCount/LoadCount is\r\nset to  -1 (to mark the current executable file as a static DLL load) along with the  Flags field that is set to  0x20\r\n( ProcessStaticImport ). Also, a global variable, which is used later during the decryption of the next layer, is set\r\nto  true .\r\nAttempts to fetch the base address and the code segment address range of an (unknown) loaded module.\r\nRetrieves the address range of the code segment of the initial executable file.\r\nObtains the base of the stack by reading the fourth offset of the Thread Information Block (TIB).\r\nStarts iterating the stack and checks how many addresses (that point to the code segment) can be replaced with the\r\nmalicious function address of this layer. The same check applies to the address range of the unknown module (if\r\nfound).\r\nWhen the iteration has been completed, the algorithm chooses which module to target (initial file or unknown loaded\r\nmodule) by picking the one with the highest occurrences of addresses to replace. If the (unknown) module is chosen,\r\nthen a global variable is set to  true .\r\nThe stack iteration starts again and replaces the candidate addresses with a pointer to the malicious function, as\r\nshown in the figure below.\r\nhttps://www.zscaler.com/blogs/security-research/unraveling-raspberry-robin-s-layers-analyzing-obfuscation-techniques-and\r\nPage 3 of 18\n\nFigure 2: Raspberry Robin return address patching.\r\nHaving completed the steps above, Raspberry Robin returns the execution to the initial executed file, which in return\r\nexecutes the malicious patched address. \r\nUpon execution, the sixth layer starts running a series of anti-analysis techniques. A notable observation is the marking of\r\nany detected anti-analysis method using the reserved field of the Process Environment Block (PEB) at offset  0x30 .\r\nSpecifically, this field is set to zero by default and Raspberry Robin updates it with a constant value, which indicates the\r\nanti-analysis method that was triggered (as shown in the table below). For example, detecting an unwanted process sets the\r\nfield to the value  0x100000 plus the index of the detected process name in the list.\r\nBase\r\nValue\r\nAnti-Analysis Method\r\n0x20000\r\nChecks for presence of a debugger by reading the PEB fields  BeingDebugged ,  NtGlobalFlag ,\r\nand  ForceFlags .\r\nChecks for the presence of a kernel-mode debugger by reading the field  KdDebuggerEnabled of\r\nthe  KUSER_SHARED_DATA  structure.\r\nChecks if the number of active processors is less than two.\r\n0x30000\r\nObtains the value of field  NumberOfPhysicalPages from the  KUSER_SHARED_DATA  to get the total\r\nRAM size and checks if the size is less than 800MB.\r\n0x70000 Checks the username of the compromised user against an embedded blocklist.\r\n0x80000 Checks the filename of the currently executed file against an embedded blocklist.\r\n0x90000 Collects the loaded modules and checks if any of them reside in an embedded blocklist.\r\n0xA0000 Checks if the CPU name is included in an embedded blocklist.\r\n0xB0000\r\nUses the assembly instruction  cpuid to detect a virtualized environment. It is important to note\r\nthat if the hypervisor leaf is hidden, the check proceeds and verifies that the machine is indeed not\r\na hypervisor.\r\n0xC0000 Checks for the presence of files that are commonly present in sandbox/analysis environments.\r\n0xD0000 Checks the product ID of the current physical drive ( PhysicalDrive0 ) of the hard disk.\r\n0xE0000 Checks if the monitor’s display name is included in an embedded blocklist.\r\nhttps://www.zscaler.com/blogs/security-research/unraveling-raspberry-robin-s-layers-analyzing-obfuscation-techniques-and\r\nPage 4 of 18\n\nBase\r\nValue\r\nAnti-Analysis Method\r\n0xF0000 Checks the MAC address(es) of the host against an embedded blocklist.\r\n0x100000 Collects the process names and checks if any of them reside in an embedded blocklist.\r\n0x110000\r\nRetrieves the firmware table using the Windows information\r\nclass  SystemFirmwareTableInformation , iterates the table, and checks if any of its values are\r\npresent in an embedded blocklist.\r\nUses the Windows information class  SystemVhdBootInformation  and reads the structure\r\nmember  OsDiskIsVhd to verify if the disk is virtual.\r\n0x120000\r\nChecks if the registry value  VBAWarnings  is set to true . This check applies to all versions of\r\nMicrosoft Office.\r\n0x160000\r\nRetrieves the sessions' named objects and verifies if these are included in an embedded blocklist.\r\nNames such as  HGFSMUTEX or  HGFSMEMORY are detected.\r\nTable 2: Raspberry Robin anti-analysis techniques.\r\nANALYST NOTE: In addition to the methods above, Raspberry Robin uses other minor evasion techniques such as using\r\nrandom offsets in a memory-allocated area. Furthermore, certain anti-analysis methods, which were described by other\r\nresearchers in the past, were not present in the recent samples we analyzed. For example, detection by using the MulDiv\r\nWindows API or mapping a large virtual memory blob with junk data were removed.\r\nThe same PEB field is updated before executing the next stage with the following operations.\r\nBitwise OR operation with  0x20000000 if any of the two aforementioned unknown modules were detected during\r\nthe stack modification process. This is set to  true by default and does not appear to have any actual effect.\r\nBitwise OR operation with  0x40000000 if no file path could be retrieved from the LDR table.\r\nBitwise OR operation with  0x80000000 if the unknown module was targeted during the stack patching process.\r\nBased on our analysis, the final value serves an important role in both the decoy payload and the final stage in the execution\r\nchain.\r\nLastly, if all anti-analysis checks have passed successfully, the current layer decrypts the seventh layer using the Rabbit\r\nstream cipher and executes it. Otherwise, the layer executes a decoy payload.\r\nDecoy payload\r\nThe decoy payload is executed using a reflective loader and does not have any obfuscation methods applied (unlike all other\r\nlayers). Despite this, all of the following conditions must be met in order to proceed:\r\nVerifies that User Account Control (UAC) is enabled by checking if the flag  DbgElevationEnabled is set in the\r\nstructure member  SharedDataFlags  of  KUSER_SHARED_DATA . If UAC is not enabled, then the execution stops.\r\nChecks if the process’s session ID is not zero.\r\nReads the PEB field  SystemReserved , which is modified from the previous layer, and determines whether the\r\nexecution should proceed or not. As an example, assuming that only an anti-analysis method triggered the\r\nmodification of this field, the decoy payload proceeds only if this value is  0xC0000 or higher.\r\nChecks if the compromised host is running for more than 13 minutes.\r\nhttps://www.zscaler.com/blogs/security-research/unraveling-raspberry-robin-s-layers-analyzing-obfuscation-techniques-and\r\nPage 5 of 18\n\nRead the registry key  COMPUTERNAME from  SOFTWARE\\Microsoft\\Mediaplayer . If the key exists already, then\r\nexecution stops. Otherwise, the decoy payload creates the aforementioned key and sets its value to zero. We assess\r\nthat this is a method to mark the system as an analysis environment.\r\nCreates a UUID, calculates its CRC32 checksum, and compares the calculated checksum with the\r\nvalue  0x2AE5FD01 . In case of a match, the execution stops. It should be noted that it is highly unlikely to generate a\r\nUUID value that matches this checksum. We assess with low confidence that the developer(s) attempted to detect the\r\npresence of inline Windows API hooking.\r\nReads the environmental variable  COMPUTERNAME and stops if the returned value is included in an embedded list of\r\nCRC32 checksums (e.g., JOHN-PC, USER-PC, LISA-PC, ANNA-PC and FRANK-PC).\r\nAfter passing the checks above, the decoy payload collects system information and sends the following data to a hardcoded\r\ndomain. \r\nA generated UUID.\r\nThe value of the  SystemReserved field of the PEB that represents the anti-analysis method that was detected.\r\nA hard-coded integer value. e.g.,  0xDC656D80  \r\nRunning time of the compromised host (in minutes).\r\nHostname and username.\r\nExecutable’s file path and the command-line.\r\nCPU name.\r\nInformation about display monitors (device name, ID, monitor resolution, and refresh rate).\r\nOnce the information above has been collected, the decoy payload prepends the CRC32 value of the username, the  Cookie\r\nvalue from  KUSER_SHARED_DATA , and the system’s timestamp.\r\nIf the length of this data is greater than 105 bytes, the code encrypts the data after this offset using the RC4 encryption\r\nalgorithm (the encryption key is the first 12 bytes of the packet, which consists of the CRC32 of the username,  Cookie\r\nvalue, and system’s timestamp). The RC4 encrypted data is not used by Raspberry Robin, thus it may be an artifact from\r\nolder code or an oversight by the malware author. The first 105 bytes of the data (including the CRC32 of the\r\nusername,  Cookie value, and system’s timestamp) are encrypted using the RSA algorithm (with a hard-coded key) and\r\nencoded with Base64.\r\nAs a last step, the decoy payload replaces the characters  + ,  / ,  = with  - ,  _ ,  0 respectively and uses the output as a\r\nURI. Lastly, the expected response is a Windows executable file, which is saved to a filename that is the hex-encoded CPU\r\nname of the compromised host.\r\nANALYST NOTE: Considering the amount of information collected from the system along with the rest of the operational\r\nchecks, we assess with medium confidence that this payload might (also) be used as a method for the threat actors to track\r\nunexpected compromised hosts (for example, sandbox environments).\r\nObfuscation methods\r\nRaspberry Robin extensively uses a variety of different obfuscation methods. These are:\r\nControl flow flattening.\r\nBogus control flow.\r\nStrings obfuscation - The decryption routine is unique per string.\r\nMixed Boolean-Arithmetic Operations (MBA) - In many occasions, the open-source projects msynth and SiMBA can\r\nassist with the deobfuscation.\r\nIndirect calls combined with MBA obfuscation.\r\nEncryption and checksum algorithms.\r\nThe first five methods are applied during compilation at the intermediate representation (IR) level.\r\nObfuscated function key\r\nEach obfuscated function includes an encrypted array table (unique per function). This array table is used during the entire\r\nexecution of the function for any of the following reasons:\r\nMapping the variables of the conditional statements of the flattened control-flow.\r\nhttps://www.zscaler.com/blogs/security-research/unraveling-raspberry-robin-s-layers-analyzing-obfuscation-techniques-and\r\nPage 6 of 18\n\nDecrypting strings.\r\nCalculating the offset of indirect calls and as a result, their addresses.\r\nAn example is shown in the figure below.\r\nFigure 3: Raspberry Robin encrypted strings and control-flow flattening example.\r\nHowever, the major issue is that in order to decrypt the array table, an integer key needs to be used. This key is passed into\r\nthe function in one of the following ways:\r\nPassed directly from the caller function as a parameter.\r\nhttps://www.zscaler.com/blogs/security-research/unraveling-raspberry-robin-s-layers-analyzing-obfuscation-techniques-and\r\nPage 7 of 18\n\nUses the value of a global variable (as seen in the figure above) or a variable passed from a previous layer.\r\nThe key is already part of the function’s local variables.\r\nThe first two cases are related to each other because each key passed to a function has been derived either from the global\r\nvariable of the current layer or the variable passed from the previous layer. For example, in the figure below, the global\r\nvariable has its value calculated based on a value passed from the previous execution layer. \r\nFigure 4: Raspberry Robin layer decryption using a global variable.\r\nAs a result, retrieving the initial/global variable of a layer is important since without it, it is not possible to conduct any\r\nanalysis (with a few exceptions).\r\nEven though it was rarely required, our approach to solve this problem was the following:\r\n1. Reverse the decryption algorithm of the given function’s array table.\r\n2. Brute-force until there is a match in any conditional statement.\r\nControl flow flattening\r\nThe implemented control flow flattening method, which Raspberry Robin uses, is encountered in all layers (including the\r\nfinal stage) and makes the analysis more tedious and time-consuming. \r\nEach conditional statement is calculated by using a substitution, addition, or bitwise XOR operation on the state variable\r\nwith an integer from the decrypted array table and then comparing the output with another value from the same array table.\r\nRaspberry Robin takes care of boolean conditional cases by using a similar approach. In general, boolean comparisons are\r\ntreated with one of the following methods:\r\nMultiply the boolean value directly with values from the decrypted array table and update the state variable.\r\nExample:\r\nhttps://www.zscaler.com/blogs/security-research/unraveling-raspberry-robin-s-layers-analyzing-obfuscation-techniques-and\r\nPage 8 of 18\n\nstate_variable -= array_table[21] - array_table[25] * boolean_value_output\r\nSubtract the boolean value from the integer value1 and then update the state variable. Example: \r\nstate_variable ^= array_table[9] + array_table[31] * (1 - boolean_value_output)\r\nAs expected, the formulas above might vary from function to function (for example, the order might be different), but the\r\ncore concept remains the same in all of them.\r\nLastly, considering all of the information above, encountering the obfuscated flow was a priority during our analysis and as\r\na result we ended up creating our own IDA (decompiler) plugin.\r\nObfuscation algorithms\r\nIn addition to the previous obfuscation methods, both the execution layers and the core layer of Raspberry Robin contain\r\ndifferent algorithms to either obfuscate or decrypt parts of the code. These are:\r\nModified aPLib decompression algorithm (used only in the execution layers) - The developers have added an extra\r\nlayer by adding the following formula in the  tag member (in  aP_getbit function) and on each read source byte:\r\n(input ^ 0xE9) - 0x66)\r\nCustom XOR decryption loop (used only in the execution layers) - This can be replicated with the following Python\r\ncode:\r\ndata = data[8:]\r\nkey = int.from_bytes(data[:4], byteorder='little')\r\nfor idx in range(len(data)):\r\n enc_key = (0xb85ce6a1 + (key ^ 0x6ddfff7f \u0026 0x5EB467BF)) \u0026 0xffffffff\r\n dec_key = enc_key \u003e 96) \u0026 0xffffffff\r\n carry_field = enc_key \u003e\u003e (0x5f % 32)\r\n key = (carry_field + dec_key) \u0026 0xffffffff\r\n decrypted_byte = key ^ data[idx + 4]\r\n decrypted_byte \u0026= 0xff\r\nCustom checksum algorithm (also available on GitHub) to replace plaintext strings comparisons. (Used across the\r\nentire execution process.)\r\nANALYST NOTE: Constant numbers in the algorithms above are different per sample. For example, the constant numbers\r\n0xe9 and 0x66 (in the modified aPLib algorithm) are expected to be different.\r\nCore layer\r\nIn this section, we describe the functionality of the core features for the final and main layer of Raspberry Robin.\r\nSynchronization and code-execution behavior\r\nThe dynamic behavior of Raspberry Robin mostly depends on three factors:\r\nFile path parameter - This parameter is passed to the final layer from the previous layers and contains the file path\r\nof the initial executable file. This parameter is used in different features of Raspberry Robin and as a result, the\r\nbehavior might differ depending on its presence. Even though the majority of the available functionalities of\r\nRaspberry Robin require this parameter to point to valid data, there are checks to verify its presence in the unlikely\r\nevent of not being available.\r\nSemaphores and mutants - As with other malware families, Raspberry Robin ensures that certain features do not\r\nrun simultaneously by creating semaphores and mutants. The object name for each one of them is generated based on\r\nan input seed using the mulberry PRNG algorithm.\r\nModified PEB field - The modified field of the PEB from the sixth layer appears to affect the behavior of the last\r\nlayer. In this case, Raspberry Robin searches and obtains a handle to the process  msiexec  and hides its window (if\r\nvisible). However, it is necessary to mention that we have not identified any value in the previous layers that can\r\ntrigger this functionality.\r\nhttps://www.zscaler.com/blogs/security-research/unraveling-raspberry-robin-s-layers-analyzing-obfuscation-techniques-and\r\nPage 9 of 18\n\nEvasion and anti-analysis\r\nDespite the amount of anti-analysis techniques used in previous layers, the final layer includes its own set of anti-analysis\r\nmethods.\r\nThe implemented anti-analysis and evasion methods in the core layer are mentioned below.\r\nHides any new thread by using the Windows class  ThreadHideFromDebugger .\r\nUses the assembly instruction  cpuid to detect a virtualized environment.\r\nUses the Windows classes  ProcessDebugFlags ,  ProcessDebugObjectHandle , and  ProcessDebugPort for debugger\r\ndetection.\r\nModifies the Windows API  DbgBreakPoint  to prevent a debugger from attaching to the process.\r\nUses the Windows class  ObjectAllTypesInformation with the Windows API  NtQueryObject  for debugger\r\ndetection.\r\nUses the WMI query  SELECT * FROM UWF_Filter to verify if the Unified Write Filter (UWF) feature option is\r\nenabled.\r\nEven though not strictly an anti-analysis technique, the core layer compares the system’s timestamp with a hardcoded\r\none and exits if this date has passed. This is a constant check, which takes place before and after each network\r\nrequest.\r\nMonitors the system’s activity. In case of a shutdown event, Raspberry Robin attempts to prevent this action by\r\nshowing the message “Adding features Don’t turn off your computer shutdown”. This string is obtained from the\r\nlegitimate DLL file  CbsMsg.dll .\r\nUses a  VMEXIT  assembly instruction ( cpuid ) to detect a virtualized environment. This method has been\r\npublicly documented already.\r\nSets custom exception handlers and triggers debugging exceptions to detect debugger single-stepping and\r\nbreakpoints (including hardware breakpoints). In any other case, the exception handler terminates the process except\r\nwhen the downloaded payload is running or the exception code is lower than  0xC0000000 .\r\nDetects process suspension by creating a thread with\r\nflags  THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH ,  THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER , and  THREAD_CREATE_FLAGS_BYPASS_PRO\r\nThe technique has already been described in the public domain.\r\nUsage of a direct Import Address Table (IAT) and as a result rebuilding a memory dump becomes a complicated task.\r\nTools such as the Universal Import Fixer (UIF) can assist with solving this issue, but manual modifications are still\r\nrequired.\r\nWhen required, certain files/processes are added to the Microsoft Windows Defender exclusions list.\r\nAdds junk data into the injected code of a target process to evade detection.\r\nAttempts to evade detection when allocating memory space by writing at a random offset and not at the start of the\r\nallocated memory area.\r\nRemoves the command-line of the current Raspberry Robin process by setting the PEB\r\nfield  CommandLine  of  ProcessParameters  to zero.\r\nDisables Windows crash reporting.\r\nRemoves the Image File Execution Options (IFEO) registry keys of specific processes\r\n( regsvr32.exe ,  dllhost.exe ,  hh.exe ,  msiexec.exe ,  regasm.exe ,  explorer.exe ).\r\nObscure registry modification\r\nIn addition to the techniques above, Raspberry Robin uses an interesting approach to avoid detection while adding registry\r\ndata. \r\nRather than modifying the Windows registry directly using common Windows API functions\r\n(e.g.  RegOpenKey ,  RegSetValueEx ), Raspberry Robin first renames the target registry key to a random one, writes the\r\nregistry data into the renamed key, and renames it back to its original name.\r\nHowever, if administrator privileges are available, Raspberry Robin uses a different approach. At first, it renames the\r\nregistry key, creates an offline registry hive in the Windows temporary directory with a random filename. Then, it writes the\r\nregistry data in the offline registry hive and loads the offline hive to the global registry tree using  ZwRestoreKey .\r\nPersistence\r\nRaspberry Robin uses the Windows registry  Run  keys for adding persistence on the compromised host. \r\nhttps://www.zscaler.com/blogs/security-research/unraveling-raspberry-robin-s-layers-analyzing-obfuscation-techniques-and\r\nPage 10 of 18\n\nUpon execution, it adds the  ProgramData directory in the Windows Defender’s exclusion list and generates a random\r\nlowercase-alphabetic string ranging in size from 3 to 9 characters. The file’s extension is randomly chosen from the list\r\nbelow.\r\nlog\r\ntmp\r\npol\r\nedb\r\nsdb\r\njrs\r\nchk\r\nxml\r\ncsv\r\ncmtx\r\netl\r\ndit\r\npat\r\njdb\r\ndat\r\nThen, the Raspberry Robin file is moved to a new directory using the previously generated string as a filename. Similarly,\r\nthe directory created uses the same attributes of the  ProgramData  directory and has a randomly generated lowercase-alphabetic name ranging between 4 and 7 characters in length. Furthermore, the file moved has its alternate stream\r\nname  Zone.Identifier:$DATA  stripped and the  Modified  timestamp changed to the current system time.\r\nRaspberry Robin uses the registry key  SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnceEx  for adding persistence on\r\nthe compromised host. The created key and value names are random lowercase-alphabetic strings ranging in size from 3 to 7\r\ncharacters\r\nIt is crucial to highlight that Raspberry Robin checks if any of the following conditions are met:\r\nThe process does not have administrator privileges.\r\nThe process name  avp.exe (part of Kaspersky’s Antivirus product) is present on the compromised host.\r\nIf any of the above is true, Raspberry Robin changes the following aspects of its behavior.\r\nUses the registry key RunOnce (under  HKEY_CURRENT_USER ), instead of  RunOnceEx .\r\nThe file location does not change and uses its current file path for persistence.\r\nLastly, depending on certain conditions, Raspberry Robin uses a different command-line (shown in the table below) for the\r\npersistence registry key.\r\nRequirements Command-Line\r\nThe process does not have administrator privileges.\r\nThe process name  avp.exe (part of Kaspersky’s Antivirus\r\nproduct) is present on the compromised host.\r\nA file path parameter has been passed.\r\nThe process is running under a SysWOW64 environment.\r\nRUNDLL32.EXE SHELL32.DLL,Control_RunDLL\r\n“filepath”\r\nThe process does not have administrator privileges.\r\nThe process name  avp.exe (part of Kaspersky’s Antivirus\r\nproduct) is present on the compromised host.\r\nA file path parameter has been passed.\r\nThe process is not running under a SysWOW64\r\nenvironment (runs on a 32-bit operating system).\r\nCONTROL.EXE “filepath”\r\nhttps://www.zscaler.com/blogs/security-research/unraveling-raspberry-robin-s-layers-analyzing-obfuscation-techniques-and\r\nPage 11 of 18\n\nRequirements Command-Line\r\nThe process does not have administrator privileges.\r\nThe process name  avp.exe (part of Kaspersky’s Antivirus\r\nproduct) is present on the compromised host.\r\nA file path parameter has not been passed.\r\nThe process is not running under a SysWOW64\r\nenvironment (runs on a 32-bit operating system).\r\nRUNDLL32 shell32 ShellExec_RunDLL\r\n“filepath”\r\nThe process has administrator privileges.\r\nThe process name  avp.exe (part of Kaspersky’s Antivirus\r\nproduct) is not present on the compromised host.\r\nA file path parameter has been passed.\r\nIf the process is running under a SysWOW64 environment.\r\nshell32.dll|Control_RunDLL|”filepath”\r\nThe process has administrator privileges.\r\nThe process name  avp.exe (part of Kaspersky’s Antivirus\r\nproduct) is not present on the compromised host.\r\nA file path parameter has been passed.\r\nThe process is not running under a SysWOW64\r\nenvironment (runs on a 32-bit operating system).\r\nSHELL32|ShellExec_RunDLL|regsvr32 /I\r\n“filepath”\r\nTable 3:  Raspberry Robin persistence command-line.\r\nAnother interesting feature is the use of the Windows Encrypted File System (EFS) in case of having administrator\r\nprivileges, but failing to add persistence on the compromised system. In this case, Raspberry Robin sets the value for the\r\nregistry key  Software\\Microsoft\\Windows NT\\CurrentVersion\\EFS\\CurrentKeys\\NumBackupAttempts to 3 and encrypts the\r\nRaspberry Robin binary file. Since this operation invokes the  efsui.exe process, Raspberry Robin attempts (10 times in\r\ntotal) to terminate it.\r\nNetwork propagation\r\nOne of the features of Raspberry Robin is to propagate itself and compromise Windows devices on the same network.\r\nRDP propagation\r\nAt first, Raspberry Robin uses the Windows API  GetSystemMetrics with parameters  SM_REMOTESESSION\r\nand  SM_REMOTECONTROL in order to determine if the compromised host is remotely controlled with an Remote Desktop\r\nControl (RDP) session. In the event of an unsuccessful return, Raspberry Robin retrieves the local session ID by reading the\r\nvalue of the registry key  GlassSessionId and compares it with the session ID of the current process. If these two values\r\nare equal then the propagation process stops. \r\nNext, Raspberry Robin constructs a file path using the prefix  \\\\tsclient\\c along with the current file path of Raspberry\r\nRobin and searches for target directories in the  users directory. A target directory must meet certain criteria such as:\r\nNot be the public directory.\r\nNot be a hidden or an operating system directory.\r\nFor each directory that is discovered, the Raspberry Robin file is copied into the target directory with a randomly generated\r\nfilename with the extension  .cpl under the default Windows path  \\start menu\\programs\\startup\\ of the selected user. \r\nIf the operation above fails, Raspberry Robin verifies that the current user has administrator privileges and starts to iterate all\r\nnetwork drives from  c up to  z . If any of them exist, it creates a symbolic path to  C:\\\\ and copies the file of Raspberry\r\nRobin using the same method as described earlier.\r\nhttps://www.zscaler.com/blogs/security-research/unraveling-raspberry-robin-s-layers-analyzing-obfuscation-techniques-and\r\nPage 12 of 18\n\nSMB propagation\r\nRaspberry Robin uses two legitimate and publicly available tools for replicating itself, PsExec and PAExec, along with the\r\nWindows built-in utility IExpress.\r\nNotably, PsExec and PAExec are downloaded from their official websites and are not embedded in Raspberry Robin. Before\r\nproceeding with their download and usage, Raspberry Robin ensures that the current user is part of the domain’s\r\nadministrator group. Otherwise, the execution does not proceed.\r\nFurthermore, Raspberry Robin stores PsExec (or PAExec in case of a download failure) in the Windows temporary folder\r\nand adds the path to the Windows Defender exclusion list. Additionally, Raspberry Robin creates a Self Extraction Directive\r\n(SED) file (shown below) and saves it as a text file, with a randomly generated filename, in the Windows temporary\r\ndirectory. The placeholders of the SED file specify the following properties.\r\nPlaceholder %1 - The filename of the executable file that will be created. For this case, the file has a randomly\r\ngenerated name.\r\nPlaceholder %2 - Path of the file to execute after the package extraction phase. This is the filename of the Raspberry\r\nRobin file.\r\nPlaceholder %3 - Path to the Raspberry Robin file.  \r\n[oFhqZaHHe]\r\n%3=\r\n[VerSiOn]\r\nsEdVErsION=3\r\nclAsS=IExpRess\r\n[DpgHCcDmWR]\r\nOfHqZAHhE=\r\n[OptIONS]\r\nsOURceFIlES=DPghCCdMWr\r\ntargEtNaMe=\"%1\"\r\nAPpLAUNcHeD=rEGSVR32 -S \"%2\"\r\nuSeLongFIlenaME=1\r\nPoStINSTaLlCMD=\r\nreBoOtmoDe=0\r\nRaspberry Robin executes the formatted SED file with the IExpress command  iexpress.exe /n /q sed_filepath to\r\ngenerate the payload. Lastly, it creates a list of internal IPs and enumerates all Windows devices in the domain. The\r\ninformation collected is then written in a text file and passed to PsExec/PAExec when executing them. \r\nIn general, Raspberry Robin uses the following commands to execute the generated payload on other Windows devices\r\nconnected to the network:\r\nfilepath_to_psexec_paexec @network_info_list.txt -accepteula -c -d -s -r random_remote_service_name\r\niexpress_payload_path  - Executes the IExpress payload on all hosts included in the provided list file.\r\n \r\nfilepath_to_psexec_paexec \\\\* -c -d -s -r random_remote_service_name iexpress_payload_path - Executes\r\nthe IExpress payload on all available hosts in the network domain.\r\nDepending on the selected tool (PsExec or PAExec), the commands might differ in their parameters. For example, to avoid\r\nnotifying the user, the parameter  -accepteula is used for PAExec while, in the case of PsExec, Raspberry Robin modifies\r\nthe registry key  EulaAccepted  to  true .\r\nIt is noteworthy to mention that, in case administrator privileges are available, Raspberry Robin adds a list of additional\r\nexclusions and rules, as shown in the table below.\r\nExclusion Description Exclusion Rule\r\nWindows Defender Process exclusion IExpress file path ( iexpress.exe ).\r\nhttps://www.zscaler.com/blogs/security-research/unraveling-raspberry-robin-s-layers-analyzing-obfuscation-techniques-and\r\nPage 13 of 18\n\nWindows Defender Process exclusion Filepath of the downloaded PsExec/PAExec.\r\nWindows firewall rule to enable ICMP and to\r\nensure that PsExec/PExec will work\r\nproperly. \r\nnetsh.exe advfirewall firewall add rule name=\"ICMP Allow\r\nincoming V4 echo request\" protocol=icmpv4:8,any dir=in\r\naction=allow\r\nWindows firewall rule to allow discovery and\r\nsharing between network hosts.\r\nnetsh.exe advfirewall firewall set rule group=\"File and\r\nPrinter Sharing\" new enable=Yes\r\nTable 4: Raspberry Robin exclusion rules list.\r\nAll files that were created in the Windows temporary directory during the execution of the operations above, are removed. \r\nLocal privilege escalation\r\nOne of the interesting features of Raspberry Robin is that it goes to a great extent to elevate its local privileges by using\r\nUAC-bypass methods and local privilege escalation exploits.\r\nUAC bypass methods\r\nRaspberry Robin includes the following UAC-bypass methods, which are copied from public sources:\r\nUAC elevation by using the COM interface ICMLuaUtil (invoked on Windows 8.1 and prior versions only).\r\nUAC elevation by using the COM interface IElevatedFactoryServer.\r\nUAC elevation by using SSPI datagram contexts. \r\nUAC elevation by modifying the registry value at  shell\\open\\command  of certain classes (shown in the table below)\r\nat  HKEY_CURRENT_USER\\Software\\Classes .\r\nAttempts to elevate its privileges by using the Windows API  ShellExecuteEx  with the verb  runas . This creates a\r\npopup window, requesting from the user to accept an elevated operation.\r\nThe UAC-bypass targeted registry classes are shown in the table below:\r\nRegistry Key Class Name Executable Name\r\nLauncher.SystemSettings slui\r\nFolder sdclt\r\nms-settings computerdefaults\r\nmscfile compmgmtlauncher\r\nms-settings fodhelper\r\nmscfile eventvwr\r\nTable 5: Raspberry Robin UAC-bypass targeted registry classes.\r\nhttps://www.zscaler.com/blogs/security-research/unraveling-raspberry-robin-s-layers-analyzing-obfuscation-techniques-and\r\nPage 14 of 18\n\nAs in other cases, Raspberry Robin performs a series of verifications and checks that affect the elevation method selection\r\nprocess:\r\nChecks if the flag  DbgElevationEnabled is set in the member  SharedDataFlags  of\r\nthe  KUSER_SHARED_DATA  structure. This flag is used to determine if UAC is enabled and, as a result, Raspberry Robin\r\ndoes not use any elevation method if disabled. The same rule applies if the process already has administrator\r\nprivileges.\r\nReads values of registry keys  ConsentPromptBehaviorUser/ConsentPromptBehaviorAdmin  to verify if the user’s\r\nconsent is required to perform an operation that requires elevation. In case of failure to read any of them, Raspberry\r\nRobin assumes that the user’s consent is required. \r\nRetrieves the time of the user’s last input event and checks if this event occurred within the last hour.\r\nEnsures that the process is not at a high integrity level.\r\nChecks for the presence of process  avp.exe (Kaspersky Antivirus) and for the loaded DLLs  aswhook  (AVG\r\nAntivirus) and  atcuf32 (BitDefender Antivirus). Currently, the detection of any of these causes Raspberry Robin to\r\nskip the first UAC elevation method.\r\nThe malicious file is executed using the legitimate Windows\r\napplication  control.exe  or  runlegacycplelevated.exe  (depending on the Windows version) along with the file path of\r\nRaspberry Robin with junk data appended to it. For example:\r\ncontrol.exe xgdtezukspcyil rximygvdjhgmhg “file_path”\r\nANALYST NOTE: There are indications in the binary’s code that instead of using control.exe/runlegacycplelevated.exe ,\r\nRaspberry Robin might use rundll32 along with the parameter advpack.dll RegisterOCX followed by the target file\r\npath. The part of this code is currently unreachable based on our analysis.\r\nExploits\r\nHistorically, Raspberry Robin has used a different set of exploits. At the time of publishing this blog, these are CVE-2024-\r\n26229 and CVE-2021-31969. Their payloads are decrypted at runtime using RC4 and the choice for which exploit to use\r\ndepends on the Windows version of the compromised host.\r\nRaspberry Robin uses the Donut loader to load and execute its exploits. Unlike other components, neither the Donut loader\r\nnor the exploits have any obfuscation applied to them, most likely due to the fact that the binary's target architecture is x64.\r\nThe code of the exploits is injected into the target process  cleanmgr.exe  with the parameter  /sageset by using\r\nthe KernelCallbackTable injection method. Because the injected payload is x64, Raspberry Robin uses the Windows API\r\nfunctions  NtWow64ReadVirtualMemory64 ,  NtWow64WriteVirtualMemory64 , and  NtWow64QueryInformationProcess64 .\r\nNetwork communication\r\nThe main objective of Raspberry Robin is to download and execute a payload on the compromised host. However, to reach\r\nthis stage, there are several tasks that need to be completed first before requesting the payload.\r\nThe first step is to verify that the host can connect to the TOR network. This is achieved by decrypting a list of legitimate\r\nonion domains (version 3) and attempting to connect to one of them (randomly chosen). It is important to note that since the\r\nnetwork communication is over the TOR network, Raspberry Robin has its own TOR client embedded in its code. \r\nNext, Raspberry Robin creates three file mapping objects, encrypts the onion URL using RC4, and copies into one of them\r\nthe following structure.\r\nstruct mapped_data\r\n{\r\n char flag; // Indicates if multiple attempts (up to 2) should be made to contact the specified onion URL and also affect\r\n char success; // Set to true if communication with the onion domain was successful.\r\n uint16_t empty_padding;\r\n uint32_t host_external_ip_address; // Obtained after parsing and reading the response’s HTTP header “X-Your-Address-Is”\r\n uint64_t elapsed_timestamp; // Obtained after sending a request and doing the operation server_time - system_time.\r\n size_t sizeof_payload_data; // Used for both incoming and outgoing data.\r\n unsigned char *payload_data;\r\n};\r\nhttps://www.zscaler.com/blogs/security-research/unraveling-raspberry-robin-s-layers-analyzing-obfuscation-techniques-and\r\nPage 15 of 18\n\nThe member  host_external_ip_address  has an important role in the behavior of Raspberry Robin. This is because the\r\nTOR module does not proceed if the external TOR IP address belongs to any of the following subnets.\r\n127.0.0.0/8\r\n10.0.0.0/8\r\n224.0.0.0/4\r\n240.0.0.0/4\r\n172.16.0.0/12\r\n192.168.0.0/16\r\nMoreover, the external IP address is RC4 encrypted and written in one of the remaining two memory mappings, which are\r\nnot used at any other point during the execution. The RC4 key is 4 bytes long and is derived from the  Cookie  value\r\nof  KUSER_SHARED_DATA .\r\nThe calculated elapsed timestamp is added to the local timestamp and the resulting output is compared with the hardcoded\r\ntermination timestamp described earlier.\r\nThe RC4 key for the encryption of the packet data is derived from the mulberry PRNG algorithm with the  Cookie value\r\nof  KUSER_SHARED_DATA  structure as a seed. Similarly, the names of the mapping objects are generated in the same way as\r\nthe RC4 key and therefore the injected TOR module can access this information independently.\r\nNext, Raspberry Robin proceeds with the code injection in one of the processes from the list below.\r\nrundll32.exe\r\ndllhost.exe\r\nregsvr32.exe\r\nhh.exe\r\nThe process created has its parent process identifier (PPID) replaced with the PID of  explorer.exe and its command-line\r\ngenerated based on the name of the selected process. For example, the format of the command-line for the target\r\nprocess  hh.exe is  process_filepath random_generated_string.chm .\r\nThe code injection method that Raspberry Robin chooses depends on the presence of the module  aswhook.dll  (component\r\nof AVG Antivirus). If this module is present, then Raspberry Robin patches the entry point of the target process using a\r\ncombination of Windows API functions  ZwProtectVirtualMemory ,  ZwWriteVirtualMemory , and  NtResumeThread .\r\nOtherwise, it uses the APC code injection technique with the Windows API function  NtQueueApcThreadEx2 (instead\r\nof  ZwQueueApcThreadEx ) if the Windows build version is higher than 19603. As a last step, a number of random bytes are\r\nadded at the start of the mapped memory area of the TOR module loader.\r\nANALYST NOTE: It is common practice for Raspberry Robin to check for the build number of Windows to verify the support\r\nof new low-level APIs to avoid any detection alerts. For example, to use  NtMapViewOfSectionEx instead\r\nof  NtMapViewOfSection .\r\nAnother important observation is the use of  Return-oriented Program (ROP) during the code injection process. Raspberry\r\nRobin collects the number of available address-candidates in the  NTDLL  module, chooses one at random, and uses it.\r\nAn  NTDLL  address is selected only if the following conditions are met.\r\nThe first byte of the address must be  0xc3 ( RET assembly instruction).\r\nThe previous two bytes must be smaller than  0x5f and not equal to  0x5c ( pop esp ) respectively.\r\nIn case of failure to find a candidate address, the entry point of the injected TOR module is used instead.\r\nThe injected module loader is similar to the previous execution layers. Therefore, the loader has the same decompression\r\n(modified aPLib) and decryption (RC4 and bitwise XOR-operations) algorithms, as well as the same anti-analysis methods\r\nof the core layer.\r\nFollowing a successful TOR connectivity check, Raspberry Robin constructs a packet that includes the following\r\ninformation from the compromised host:\r\nExternal IP address of the compromised host.\r\nEmbedded hardcoded string  AFF123 (this value has been the same across all samples).\r\nhttps://www.zscaler.com/blogs/security-research/unraveling-raspberry-robin-s-layers-analyzing-obfuscation-techniques-and\r\nPage 16 of 18\n\nA 2-byte value derived from the CRC64-checksum value of the PE headers of the initially executed PE file, after\r\nmodifying them.\r\nVolume serial number (8 bytes long, retrieved from the Windows structure  NTFS_VOLUME_DATA_BUFFER ).\r\nCreation timestamp of the directory  Documents and Settings (in LDAP format).\r\nNumber of active processors.\r\nBoolean value indicating whether the process is running under WOW64.\r\nWindows versioning information.\r\nBoolean values to indicate if the process has administrator privileges on a local and domain level.\r\nSystem time (in LDAP format) and locale information.\r\nUsername, hostname, NETBIOS domain name, DNS domain name, and logon server name.\r\nJava version (if available).\r\nCPU name.\r\nProcess’s filepath (including the parent process, for example the path of  explorer.exe ). Special UTF-16-LE\r\ncharacters are encoded in their hex format representation. For example, the backslash character is encoded\r\nas  \\x005C .\r\nProduct ID and serial number of the physical drive.\r\nMAC addresses.\r\nList of installed antivirus products (including the  ProductState  value, which represents the operational status).\r\nDisplay monitor information (e.g., device name).\r\nList of running process names.\r\nDesktop screenshot (in Base64 format) and width/height of the display monitor.\r\nTo avoid issues with a large data size, Raspberry Robin sets a maximum length of 131,072 bytes. This limit has a critical\r\nrole when a desktop screenshot is taken. In case the screenshot’s data size makes the total network packet size exceed the\r\nmaximum limit, the screenshot is not included in the packet.\r\nThe 2-byte calculated value is of a particular interest. This value is calculated by reading the PE headers of the initial\r\nexecutable file (in the event that a filepath parameter is not included, this value is set to 5) and setting specific headers to\r\nzero (the size of the headers must not be over 256 bytes and the file must be larger than 65,536 bytes). The names of these\r\nPE headers are mentioned below:\r\nSecurity Directory RVA\r\nTimestamp\r\nSize of Security Directory\r\nCheckSum\r\nAlso, depending on the number of PE sections and the raw size/virtual-address of the first section, the header information\r\n( IMAGE_SECTION_HEADER ) of the first section might be set to zero.\r\nThen, Raspberry Robin calculates the CRC-64 checksum of the modified PE headers and bitwise-XORs the output with the\r\nlower part of the PE timestamp followed by a hard-coded constant value. If the value of the output is higher than 1,000, then\r\nRaspberry Robin changes the value to 4. \r\nANALYST NOTE: There are certain conditions, which can skip the process above and set a hardcoded value instead. For\r\ninstance, the value is set to 1 if the session ID of the process is different than zero and the checksum of the value of the\r\nenvironmental variable  userdomain does not match an (unknown) output.\r\nHaving collected all the information above, Raspberry Robin generates 8 random bytes and appends them to a hardcoded 8\r\nbyte value that acts as a salt and uses this value as an RC4 key to encrypt the data. The randomly generated part of the key is\r\nprepended to the packet after the encryption since the C2 server requires it. Furthermore, it generates random padding that is\r\nappended at the end of the RC4 encrypted data (the size of the random data is randomly chosen up to 2,048 bytes). \r\nAs the final step in the encryption process, a checksum value of the data is calculated (CRC-64) and appended. Raspberry\r\nRobin encrypts the packet produced using AES-CTR with a randomly generated initialization vector (IV) using the mulberry\r\nalgorithm and encodes the encrypted output using Base64. The layout of the header for the final packet is provided below.\r\n#pragma pack(push, 1)\r\nstruct host_info_packet_header\r\n{\r\nhttps://www.zscaler.com/blogs/security-research/unraveling-raspberry-robin-s-layers-analyzing-obfuscation-techniques-and\r\nPage 17 of 18\n\nunsigned char aes_iv[16];\r\n uint64_t crc64_checksum;\r\n size_t sizeof_data;\r\n unsigned char* data;\r\n};\r\nThe Base64 output is appended as a URI to an onion domain (version 3) and a request is sent using the TOR module (in the\r\nsame way as described above).\r\nANALYST NOTE: It is important to point out that the CNCs of Raspberry Robin are not decrypted all at once. Instead,\r\nRaspberry Robin decrypts only a randomly-chosen one. One more interesting observation is the incorrect size of the onion\r\ndomains, which are short by one character. This is an intentional choice by the developers. The character  d is added at the\r\nend of the onion domain by the TOR module.\r\nAfter sending the request, the C2 server of Raspberry Robin replies with a payload that is mapped directly into the current\r\nprocess and executed in a new thread.\r\nHowever, before proceeding with its execution, Raspberry Robin parses the downloaded payload and prepends the following\r\ndata:\r\nA hard-coded byte-array of 144 bytes with the first sixteen bytes being the sizes of the embedded members of the\r\ndata.\r\nThe formatted string  AFF123_file_checksum , where  file_checksum is the calculated checksum value based on the\r\ninitial executed file (the third item in the host’s information list above).\r\nMoreover, Raspberry Robin creates a registry key (host-based name)\r\nat  SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall , which indicates that the payload has been downloaded.\r\nSource: https://www.zscaler.com/blogs/security-research/unraveling-raspberry-robin-s-layers-analyzing-obfuscation-techniques-and\r\nhttps://www.zscaler.com/blogs/security-research/unraveling-raspberry-robin-s-layers-analyzing-obfuscation-techniques-and\r\nPage 18 of 18",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://www.zscaler.com/blogs/security-research/unraveling-raspberry-robin-s-layers-analyzing-obfuscation-techniques-and"
	],
	"report_names": [
		"unraveling-raspberry-robin-s-layers-analyzing-obfuscation-techniques-and"
	],
	"threat_actors": [],
	"ts_created_at": 1775439160,
	"ts_updated_at": 1775791304,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/9b6cb528642f13f221d5248308993741f92ae23a.pdf",
		"text": "https://archive.orkl.eu/9b6cb528642f13f221d5248308993741f92ae23a.txt",
		"img": "https://archive.orkl.eu/9b6cb528642f13f221d5248308993741f92ae23a.jpg"
	}
}