{
	"id": "57ff8887-93aa-41b1-8fc1-27b407386863",
	"created_at": "2026-04-06T15:53:21.360158Z",
	"updated_at": "2026-04-10T13:12:28.945502Z",
	"deleted_at": null,
	"sha1_hash": "05be21807dcb0d03b9f6ebab924d51f852c1ab95",
	"title": "Decrypting APT33’s Dropshot Malware with Radare2 and Cutter – Part 2",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 184124,
	"plain_text": "Decrypting APT33’s Dropshot Malware with Radare2 and Cutter –\r\nPart 2\r\nBy Itay Cohen\r\nPublished: 2018-06-18 · Archived: 2026-04-06 15:36:01 UTC\r\n Prologue\r\nPreviously, in the first part of this article, we used Cutter, a GUI for radare2, to statically analyze APT33’s\r\nDropshot malware. We also used radare2’s Python scripting capabilities in order to decrypt encrypted strings in\r\nDropshot. If you didn’t read the first part yet, I suggest you do it now.\r\nToday’s article will be shorter, now that we are familiar with cutter and r2pipe, we can quickly analyze another\r\ninteresting component of Dropshot — an encrypted resource that includes Dropshot’s actual payload. So without\r\nfurther ado, let’s start.\r\nDownloading and installing Cutter\r\nCutter is available for all platforms (Linux, OS X, Windows). You can download the latest release here. If you are\r\nusing Linux, the fastest way to use Cutter is to use the AppImage file.\r\nIf you want to use the newest version available, with new features and bug fixes, you should build Cutter from\r\nsource by yourself. It isn’t a complicated task and it is the version I use.\r\nFirst, you must clone the repository:\r\ngit clone --recurse-submodules https://github.com/radareorg/cutter\r\ncd cutter\r\nBuilding on Linux:\r\n./build.sh\r\nBuilding on Windows:\r\nprepare_r2.bat\r\nbuild.bat\r\nIf any of those do not work, check the more detailed instruction page here\r\nhttps://www.megabeets.net/decrypting-dropshot-with-radare2-and-cutter-part-2/\r\nPage 1 of 12\n\nDropshot \\ StoneDrill\r\nAs in the last part, we’ll analyze Dropshot, which is also known by the name StoneDrill. It is a wiper malware\r\nassociated with the APT33 group which targeted mostly organizations in Saudi Arabia. Dropshot is a sophisticated\r\nmalware sample, that employed advanced anti-emulation techniques and has a lot of interesting functionalities.\r\nThe malware is most likely related to the infamous Shamoon malware. Dropshot was analyzed thoroughly by\r\nKaspersky and later on by FireEye. In this article, we’ll focus on decrypting the encrypted resource of Dropshot\r\nwhich contains the actual payload of the malware.\r\nThe Dropshot sample can be downloaded from here (password: infected). I suggest you star (★) the repository to\r\nget updates on more radare2 tutorials 🙂\r\nPlease, be careful when using this sample. It is a real malware, and more than that, a wiper! Use with\r\ncaution!\r\nSince we’ll analyze Dropshot statically, you can use a Linux machine, as I did.\r\nGetting Started\r\nAssuming you went through the first part of the article, you are already familiar with Cutter and r2pipe. Moreover,\r\nyou should already have a basic clue of how Dropshot behaves. Open the Dropshot sample in Cutter, execute in\r\nJupyter the r2pipe script we wrote and seek to the `main` function using the “Functions” widget or the upper\r\nsearch bar.\r\nA function we analyzed in the previous article | Click to enlarge\r\nmain ()\r\nThe role of the main()  function in a program shouldn’t be new to you since it is one of the fundamental concepts\r\nof programming. Using the Graph mode, we’ll go thorugh main ‘s flow in order to find our target – the resource\r\ndecryption routine. We can see that a function at 0x403b30  is being called at the first block of main .\r\nDouble-clicking this line will take us to the graph of fcn.00403b30 , a rather big function. Going through this\r\nfunction, we’ll see some non-sense Windows API calls with invalid arguments. When describing Dropshot, I said\r\nthat it uses anti-emulation heavily – this function, for example, performs anti-emulation.\r\nhttps://www.megabeets.net/decrypting-dropshot-with-radare2-and-cutter-part-2/\r\nPage 2 of 12\n\nClick to enlarge\r\nAnti-Emulation\r\nAnti-emulation techniques are used to fool the emulators of anti-malware products. The emulators are one of the\r\nmost important components of many security products. Among others, they are used to analyze the behavior of\r\nmalware, unpack samples and to analyze shellcode. It is doing this by emulating the program’s workflow by\r\nmimicking the target architecture’s instruction set, as well as the running environment, and dozens or even\r\nhundreds of popular API functions. All this is done in order to make a malware ‘think’ it has been executed in a\r\nreal environment by a victim user.\r\nThe emulator engine is mimicking the API or the system calls that are offered by the actual operating systems.\r\nUsually, it will implement popular API functions from libraries such as user32.dll, kernel32.dll, and ntdll.dll. Most\r\nof the times this will be a dummy implementation where the fake functions won’t really do anything except\r\nreturning a successful return value.\r\nhttps://www.megabeets.net/decrypting-dropshot-with-radare2-and-cutter-part-2/\r\nPage 3 of 12\n\nBy using different anti-emulation techniques, malware authors are trying to fool a generic or even a specific\r\nemulator. The most common technique, which is also implemented in Dropshot’s  fcn.00403b30 , is the use of\r\nuncommon or undocumented API calls. This technique can be improved by using incorrect arguments (like\r\nNULL) to a certain API function which should cause an Access Violation exception in a real environment.\r\nIn our case, Dropshot is calling some esoteric functions as well as passing non-sense arguments to different API\r\nfunctions.\r\nMore information about emulation and anti-emulation mechanisms are available in the following, highly\r\nrecommended, book: \r\nNow that we know all this, we can rename this function from fcn.00403b30  to a more meaningful name. I used\r\n“AntiEmulation” but you can choose whatever name you want, as long as it is meaningful to you. Clicking the call\r\ninstruction and then pressing Shift+N will open the Rename dialog box. Right-clicking the row and choosing\r\n“Rename” will do the job as well.\r\nAfter main  is calling to the AntiEmulation function, we are facing a branch. Here’s the assembly, copied from\r\nCutter’s Disassembly widget:\r\n| 0x004041a6 call AntiEmulation\r\n| 0x004041ab mov eax, 1\r\n| 0x004041b0 test eax, eax\r\n| ,=\u003c 0x004041b2 je 0x40429d\r\n| | 0x004041b8 push 4\r\nAs you can see, the code would never branch to 0x40429d  since this test eax, eax  followed by je ...  is\r\nbasically checking whether eax  equals 0. One instruction before, the program moved the value 1 to eax , thus\r\n0x40429d would be The Road Not Taken.\r\nWe’ll skip the next block which is responsible for creating temporary files and take a look at the block starting\r\nat  0x4041f9 . In this block, we’ll see that Dropshot is creating a modeless Dialog box using\r\nCreateDialogParamA  with the following parameters:  CreateDialogParamA(0, 0x410, 0, DialogFunc, 0); .\r\nThe DialogPrc callback which is passed to  CreateDialogParamA is recognized by radare2 and shown by Cutter as\r\nfcn.DialogFunc . This function contains the main logic of the dropper and this is the function that we’ll focus on.\r\nLater in this block, ShowWindow  is being called in order to “show” the window. Obviously, this is a dummy\r\nwindow which would never be shown since the malware author doesn’t want any artifact to be shown to the\r\nvictim. ShowWindow will trigger the execution of fcn.DialogFunc .\r\nDouble-clikcing on  fcn.DialogFunc  will take us to the function itself. We can see that it is performing several\r\ncomparisons for the messages it receives and then is calling to a very interesting function fcn.00403240 .\r\nHandling  the Resources\r\nhttps://www.megabeets.net/decrypting-dropshot-with-radare2-and-cutter-part-2/\r\nPage 4 of 12\n\nThe first block of fcn.00403240  is pretty straightforward. Dropshot is getting a handle to itself using\r\nGetModuleHandleA . Then, by using FindResourceA , it is locating a resource with a dummy type 0x67 (Decimal:\r\n111) and a name 0x6e (Decimal: 110). Finally, it is loading a resource with this name using LoadResource .\r\nUsing Cutter, we can see the content of this resource. Simply go to the Resources widget and locate the resource\r\nwith the name “110”.\r\nAs you can see in the screenshot above, the size of the resource is 28 Bytes and its Lang is Farsi which might\r\nhint us about the threat actor behind Dropshot.\r\nDouble-clicking the resource will take us to the resource’s address. Let’s click on the Hexdump widget to see its\r\ndata. In the hexdump we can see that this resource contains the following bytes: 01 00 00 00 00 00 00 00 01 00\r\n00 00 00 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 . Those of you who are familiar with radare2 may use\r\nthe Console widget in the bottom left to do this quickly with px :\r\nThis resource will be used later but we won’t be getting into it since it is out of the scope of this post.\r\nAfter loading the resource, in the next block we can see the start of a loop:\r\nThis loop is checking if local_2ch  equals to 0x270f (Decimal: 9999) and if yes it exits from the loop. Inside\r\nthis loop, there will be another loop of 999 iterations. So basically, this is how this nested loop looks like:\r\nfor ( i = 0; i \u003c 9999; ++i )\r\n {\r\n for ( j = 0; j \u003c 999; ++j )\r\n {\r\n dummy_code;\r\n }\r\n }\r\nThis is just another anti-emulation\\analysis technique which is basically doing nothing. This is another example of\r\nthe heavy use of anti-emulation by Dropshot.\r\nAfter this loop, the right branch is taken and this is an interesting one.\r\nClick to enlarge\r\nAt first, VirutalAlloc  in the size of 512 bytes is being called. Next, fcn.00401560  is called with 3 arguments.\r\nLet’s enter this function and see what’s in there:\r\nClick to enlarge\r\nhttps://www.megabeets.net/decrypting-dropshot-with-radare2-and-cutter-part-2/\r\nPage 5 of 12\n\nHey! Look who’s back! We can see the 2 functions we analyzed in the previous article:\r\ndecryption_function  and load_ntdll_or_kernel32 . That’s great! Also, you can notice the comment on  call\r\ndecryption_function  which is telling us that the decrypted string is GetModuleFileNameW . This comment is the\r\nresult of the r2pipe script we wrote.\r\nIn this function,  GetModuleFileNameW will be decrypted, then Kernel32.dll will be loaded and\r\nGetProcAddress  will be called to get the address of  GetModuleFileNameW  and then it will move it to\r\n[0x41dc04] . Later in this function,  [0x41dc04] will be called.\r\nBasically, this function is wrapper around  GetModuleFileNameW , something which is common in Dropshot’s\r\ncode. Let’s rename this function to w_GetModuleFileNameW where “w_” stands for “wrapper”. Of course, you can\r\nchoose whatever naming convention you prefer.\r\nRight after the call to  w_GetModuleFileNameW , Dropshot is using VirtualAlloc to allocate 20 (0x14) bytes, then\r\nthere is a call to fcn.00401a40  which is a function quite similar to memset , it is given with 3 arguments\r\n(address, value and size), just like memset and it is responsible to fill the range from address  to\r\naddress+size  with the given value . Usually, along the program, this function is used to fill an allocated buffer\r\nwith zeroes. This is quite strange to me, since VirtualAlloc is already “initializes the memory it allocates to zero”.\r\nLet’s name this function to memset_  using Shift+N or via right click and move on.\r\nRight after the program is zeroing-out the allocated memory, we see a call to another function –\r\n  fcn.00401c90 . We can see 3 arguments which are being passed to it, 0x14, 0x66, and 0x68. Since sometimes we\r\nprefer to see decimal numbers and not hex, let’s use another useful trick of Cutter. Right-click on any of these hex\r\nnumbers and choose “Set Immediate Base to…” and then select “Decimal”.\r\nNow we can see that the values which are being passed to fcn.00401c90  are 20, 102 and 104. Looks familiar?\r\n20 was the size of the buffer that was just allocated. 102 and 104 remind us the Resource name and type that used\r\nbefore (110 and 111). Are we dealing with resources here? Let’s see.\r\nMoving to the Resources widget again, we can see that there’s indeed a resource named “102” which “104” is its\r\ntype. And yes, it is 19B long, close enough 😉\r\nfcn.00401c90 is one of the key functions involved in the dropper functionality of Dropshot. The thing is, that this\r\nfunction is rather big and quite complicated when you don’t know how to look at it. We’ll get back to it in one\r\nminute but before that, I want to show you an approach I use while reverse engineering some pieces of code and\r\nwhile facing a chain of calls to functions which are probably related to each other.\r\nFirst, we saw that 20 bytes were allocated by  VirtualAlloc and the pointer to the allocated memory was moved\r\nto [local_ch] . Right after that, memset_  was called in order to zero-out 20 bytes at [local_ch] , i.e to zero-out\r\nthe allocated buffer. Immediately after, fcn.00401c90  was called and 3 arguments were passed to it – 104, 102\r\nand our beloved 20. We know that 102 is a name of a resource and its size is almost 20. We don’t know yet what\r\nthis function is doing but we know that its return value( eax ) is being passed along with 2 more arguments to\r\nanother function, fcn.00401a80 . The other arguments are, you guessed right, 20 and the allocated buffer. A quick\r\nlook at fcn.00401a80 , which is a really tiny function, will reveal us that this function is copying a buffer to the\r\nhttps://www.megabeets.net/decrypting-dropshot-with-radare2-and-cutter-part-2/\r\nPage 6 of 12\n\nallocated memory. This function is quite similar to memcpy so we’ll rename it to  memcpy_ . So now we can do an\r\neducated guess and say that  fcn.00401c90 is reading a resource to a buffer and returns a pointer to it.\r\nUsing this approach, we can understand (or at least guess) a complicated function without even analyzing it. Just\r\nby looking at a programs chain of function calls, we can build the puzzle and save us important time.\r\nThat said, we’ll still give this function a quick analysis because we want to be sure that we guessed right, and\r\nmore importantly — because this is an interesting function.\r\nResource Parser\r\nThe next part is where things are getting more complicated. We’ll start by going over fcn.00401c90  pretty fast\r\nso try to follow. Also, you may want to make sure you fasten yourself since we are going on a rollercoaster ride\r\nthrough the PE structure.\r\nTake a look at the first block of this function. You’ll see one call  and a lot of mov , add  and calculation of\r\noffsets. This is how a typical PE parsing looks like.\r\n/ (fcn) fcn.00401c90 468\r\n| fcn.00401c90 (int arg_8h, int arg_ch, int arg_10h);\r\n| 0x00401c90 push ebp\r\n| 0x00401c91 mov ebp, esp\r\n| 0x00401c93 sub esp, 0x44\r\n| 0x00401c96 mov dword [local_40h], 0\r\n| 0x00401c9d push 0\r\n| 0x00401c9f call GetModuleHandleW\r\n| 0x00401ca5 mov dword [local_34h], eax\r\n| 0x00401ca8 mov eax, dword [local_34h]\r\n| 0x00401cab mov dword [local_20h], eax\r\n| 0x00401cae mov ecx, dword [local_20h]\r\n| 0x00401cb1 mov dword [local_24h], ecx\r\n| 0x00401cb4 mov edx, dword [local_24h]\r\n| 0x00401cb7 mov eax, dword [edx + 0x3c]\r\n| 0x00401cba add eax, dword [local_24h]\r\n| 0x00401cbd mov dword [local_38h], eax\r\n| 0x00401cc0 mov ecx, dword [local_38h]\r\n| 0x00401cc3 add ecx, 0x18\r\n| 0x00401cc6 mov dword [local_3ch], ecx\r\n| 0x00401cc9 mov edx, dword [local_3ch]\r\n| 0x00401ccc add edx, 0x60\r\n| 0x00401ccf mov dword [local_28h], edx\r\n| 0x00401cd2 mov eax, 8\r\n| 0x00401cd7 shl eax, 1\r\n| 0x00401cd9 mov ecx, dword [local_28h]\r\n| 0x00401cdc mov edx, dword [ecx + eax]\r\n| 0x00401cdf mov dword [local_44h], edx\r\nhttps://www.megabeets.net/decrypting-dropshot-with-radare2-and-cutter-part-2/\r\nPage 7 of 12\n\n| 0x00401ce2 mov eax, 8\r\n| 0x00401ce7 shl eax, 1\r\n| 0x00401ce9 mov ecx, dword [local_28h]\r\n| 0x00401cec mov edx, dword [local_20h]\r\n| 0x00401cef add edx, dword [ecx + eax]\r\n| 0x00401cf2 mov dword [local_10h], edx\r\n| 0x00401cf5 mov eax, dword [local_10h]\r\n| 0x00401cf8 mov dword [local_4h], eax\r\n| 0x00401cfb mov ecx, dword [local_4h]\r\n| 0x00401cfe movzx edx, word [ecx + 0xe]\r\n| 0x00401d02 mov eax, dword [local_4h]\r\n| 0x00401d05 movzx ecx, word [eax + 0xc]\r\n| 0x00401d09 add edx, ecx\r\n| 0x00401d0b mov dword [local_ch], edx\r\n| 0x00401d0e mov dword [local_14h], 0\r\n| ,=\u003c 0x00401d15 jmp 0x401d20\r\n...\r\n...\r\nAt first, a handle to the current process is received using GetModuleHandleW . Then, the handle ( eax ) is being\r\nmoved to a variety of local variables. First, it is being moved to [local_34h]  at 0x00401ca5 . Then you can see\r\neax  moved to [local_20h]  which is later being moved to [local_24h]  using ecx .\r\nSo basically we have a bunch of local variables that currently hold the handle  hmodule . We can rename all three\r\nvariables to [hmodule_x]  so it’ll be easier to keep track of all the reference to hmodule . To rename flags you\r\ncan use the Console widget and just execute afvn old_name new_name . For example, I executed: afvn\r\nlocal_34h hmodule_1; afvn local_20h hmodule_2;afvn local_24h hmodule_3 .\r\nGetModuleHandle  returns a handle to a mapped module, this basically means that our hmodule s point to our\r\nbinary’s base address. In line 0x00401cb4  we can see that [hmodule_3]  is moved to edx , then the value at\r\n[edx + 0x3c]  is being moved to eax and [hmodule_3] is added to it at 0x00401cba . Finally, eax  is moved\r\nto [local_38h] . To put it simply, we can use the following pseudo-code:\r\n[local_38h] = (BYTE*)hmodule + *(hmodule + 0x3c)\r\nSo what’s in this address? Use your favorite binary structure viewer to find out. In this example, I’ll use PEview\r\nbut you can use any other program you prefer – including the binary structure parsing feature of radare2, if you’re\r\nalready a radare2 pro (see pf? ).\r\nOpen Dropshot in PEview and inspect the DOS Header:\r\nAs you can see, in offset 0x3c  there is a pointer (0x108) to the offset to the new EXE Header which is\r\nbasically the IMAGE_NT_HEADER. Awesome! So [local_38h]  holds the address of the NT Header. Let’s\r\nrename it to NT_HEADER and move on.\r\nhttps://www.megabeets.net/decrypting-dropshot-with-radare2-and-cutter-part-2/\r\nPage 8 of 12\n\nAt address 0x00401cc0  we can see that NT_HEADER is moved to ecx  and then the program is adding 0x18\r\nto  ecx . Last, the value in ecx  is moved to [local_3ch] . Just as before, let’s open again our PE parser and\r\ncheck what is in NT_HEADER + 0x18 . Adding 0x18 to 0x108 will give us 0x120. Let’s see what is in this offset:\r\nClick to enlarge\r\nNice! 0x120 is the offset of the IMAGE_OPTIONAL_HEADER as can be seen in the image above. Let’s rename\r\nlocal_3ch  to OPTIONAL_HEADER . To cut a long story short, Dropshot is then parsing the\r\nIMAGE_DATA_DIRECTORY structure (OPTIONAL_HEADER + 0x60), the RESOURCE_TABLE, and last it\r\niterates through the different resources and compares the resource type and the resource name to the function’s\r\narguments. Finally, it uses memcpy_  to copy the content of the required resource to a variable and returns this\r\nvariable.\r\nNow we can rename the function to get_resource  and the arguments to the corresponding meaning of them by\r\nexecuting afvn arg_8h arg_rsrc_type; afvn arg_ch arg_rsrc_name; afvn arg_10h arg_dwsize .\r\nNow that we are sure about what this function does, we can see where else it is referenced. Right-click on the\r\nfunction and choosing “Show X-Refs” (or simply pressing ‘x’) will take us to the X-Refs window. We can see that\r\nget_resource  is being called from two locations. One ( 0x0040336d ) is already familiar to us, it is called to get\r\nresource “102”. The second call (at 0x00403439 ), a few instructions later, is new to us — it is called to get the\r\ncontent of another resource, named “101” (0x65).\r\nRemember the screenshot of the Resources widget from before? We can see there the resource named “101”. What\r\nmakes “101” so interesting is that it is much bigger than the other — its size is 69.6 KB! This is Dropshot’s\r\npayload. By going to the Resources widget and double-clicking “101” will take us to the resource’s offset in the\r\nbinary. In the Hexdump widget, we can see that the content of this resource makes no sense and has a really high\r\nentropy (7.8 out of the maximum 8):\r\nClick to enlarge\r\nThis data is compressed/encrypted somehow so we need to decrypt it. Let’s continue our analysis to find out how.\r\nHow To Decrypt The Resource\r\nIn order to decrypt the resource, we should follow the program’s flow to see how and where the payload is being\r\nused. Right after get_resource  is being called with “101” and “103”, the resource is copied to [local_20h]\r\nusing memcpy_ (at 0x00403446 ). Let’s call it compressed_payload . The compressed buffer is then passed to\r\nfcn.00401e70  which is a function that performs dummy math calculations on the resource’s data. Probably\r\nanother Anti-Emulation technique or simply a way to waste our time. I’ll rename it to dummy_math . Next,\r\ncompressed_payload is being passed to fcn.00401ef0  along with another buffer [local_54h] .\r\nhttps://www.megabeets.net/decrypting-dropshot-with-radare2-and-cutter-part-2/\r\nPage 9 of 12\n\nThe analysis of this function is out of the scope of this article but this function is responsible to decompress a\r\nbuffer using zlib and put the decompressed buffer in [local_54h] . You can see, for example, that\r\nfcn.00401ef0  is calling to fcn.004072f0  which contains strings like “unknown compression method” and\r\n“invalid window size” which can be found in the file inflate.c in the zlib repository. I renamed  fcn.00401ef0  to\r\nzlib_decompress  and local_54h  to decompressed_payload .\r\nI’ll tell you now that simply a decompression of the buffer isn’t enough since there’s still another simple\r\ndecryption to do. Straight after the decompressing, we can see more of the Anti-Emulation which we are already\r\nfamiliar with. Finally, our decompressed buffer is being passed to fcn.00402620 . This function is responsible for\r\nthe last decryption of the resource and then it performs a notorious technique known as “Process Hollowing” or\r\n“RunPE” in order to execute the decrypted payload.\r\nSo how  fcn.00402620  decrypts the decompressed payload? Simply, it uses ror 3  to rotate-right each byte in\r\nthe decompressed buffer. 3 stands for the number of bits to rotate.\r\nThe rest of this function is interesting as well but it has nothing to do with decrypting the resource so I’ll leave it\r\nto you.\r\nTo sum things up, and before we adding the logic for the resource decryption inside the script we wrote in the\r\nprevious article – let’s sketch how the decryption function should look like. It should be something like this:\r\nrsrc_101 = get_resource(\"101\")\r\ndecompressed_payload = decompress(rsrc_101)\r\ndecrypted_payload = []\r\nfor b in decompressed_payload:\r\n decrypted_payload.append(ror3(b))\r\nScripting time! Decrypting the resource\r\nScripting radare2 is really easy thanks to r2pipe. It is the best programming interface for radare2.\r\nThe r2pipe APIs are based on a single r2 primitive found behind  r_core_cmd_str()  which is a\r\nfunction that accepts a string parameter describing the r2 command to run and returns a string with the\r\nresult.\r\nr2pipe supports many programming languages including Python, NodeJS, Rust, C, and others.\r\nLuckily, Cutter is coming with the python bindings of  r2pipe  integrated into its Jupyter component. We’ll write\r\nan r2pipe script that will do the following:\r\nSave the compressed resource into a variable\r\nhttps://www.megabeets.net/decrypting-dropshot-with-radare2-and-cutter-part-2/\r\nPage 10 of 12\n\nDecompress the resource using zlib\r\nPerform ror3 on each byte in the decompressed payload\r\nSave the decrypted resource to a file\r\nJust as in the previous part, let’s go to the Jupyter widget and open the script we wrote when decrypted the strings\r\n(part1).\r\nThe first thing to do is to read the content of the encrypted and compressed resource to a file:\r\nrsrcs = cutter.cmdj('iRj')\r\nrsrc_101 = {}\r\n# Locate resource 101 and dump it to an array\r\nfor rsrc in rsrcs:\r\n if rsrc['name'] == 101:\r\n rsrc_101 = cutter.cmdj(\"pxj %d @ %d\" %\r\n (rsrc['size'], rsrc['vaddr']))\r\niR  was used to get the list of resources and their offsets in the file. Next, we iterate through the\r\ndifferent resources untill we find a resource named “101”. Last, using px  we are reading the\r\nresource’s bytes into a varibale. We appended j  to the commands in order to get their output as JSON.\r\nNext, we want to decompress the buffer using zlib. Python is coming with “zlib” library by default which is great\r\nnews for us. Add import zlib  to the top of the script and use this code to decompress the buffer:\r\n# Decompress the zlibbed array\r\ndecompressed_data = zlib.decompress(bytes(rsrc_101))\r\nNow that our buffer is decompressed in decompressed_data , all we left to do is to perform right rotation on the\r\ndata and save it to a file.\r\nDefine the following ror lambda:\r\ndef ror(val, r_bits, max_bits): return \\\r\n ((val \u0026 (2**max_bits-1)) \u003e\u003e r_bits % max_bits) | \\\r\n (val \u003c\u003c (max_bits-(r_bits % max_bits)) \u0026 (2**max_bits-1))\r\nAnd use it in your code like this:\r\ndecrypted_payload = []\r\n# Decrypt the payload\r\nfor b in decompressed_data:\r\n decrypted_payload.append((ror(b, 3, 8)))\r\nhttps://www.megabeets.net/decrypting-dropshot-with-radare2-and-cutter-part-2/\r\nPage 11 of 12\n\nLast, save it to a file:\r\n# Write the payload (a PE binary) to a file\r\nopen(r'./decrypted_rsrc.bin', 'wb').write(bytearray(decrypted_payload))\r\nNow let’s combine the script from the previous article to the one we created now and test it in Jupyter. The\r\ncombined script should first decode the encrypted scripts, and then it should decrypt the resource and save it to the\r\ndisk.\r\nThe final script can be found here.\r\nCopy it and paste it into your Jupyter notebook. You can also execute your version of the code to see if you got it\r\nright by yourself.\r\nSeems like our script was executed successfully and “Saved the PE to ./decrypted_rsrc.bin”. Great!\r\nThe last thing we want to do is to open  decrypted_rsrc.bin in a new instance of Cutter in order to verify that\r\nthis is indeed a PE file and that we didn’t corrupt the file in some way.\r\nClick to enlarge\r\nAwesome! Cutter recognized the file as PE and seems like the code is correctly interpreted. This binary we just\r\ndecrypted and saved is the Wiper module of Dropshot – a quite interesting piece of malware on its own. This\r\nmodule, just as its dropper, is using heavy anti-emulation and similar technique to decrypt its strings. You can give\r\nit a try and analyze it on your own using Cutter, radare2, and r2pipe. Good Luck!\r\nEpilogue\r\nHere comes to an end the second and the last part of this series about decrypting Dropshot with Cutter and r2pipe.\r\nWe got familiar with Cutter, radare2 GUI, and wrote a decryption script in r2pipe’s Python binding. We also\r\nanalyzed some components of APT33’s Dropshot, an advanced malware.\r\nAs always, please post comments to this post or message me privately if something is wrong, not accurate, needs\r\nfurther explanation or you simply don’t get it. Don’t hesitate to share your thoughts with me.\r\nSubscribe on the left if you want to get the next articles straight in your inbox.\r\nSource: https://www.megabeets.net/decrypting-dropshot-with-radare2-and-cutter-part-2/\r\nhttps://www.megabeets.net/decrypting-dropshot-with-radare2-and-cutter-part-2/\r\nPage 12 of 12",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia",
		"ETDA"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://www.megabeets.net/decrypting-dropshot-with-radare2-and-cutter-part-2/"
	],
	"report_names": [
		"decrypting-dropshot-with-radare2-and-cutter-part-2"
	],
	"threat_actors": [
		{
			"id": "a63c994f-d7d6-4850-a881-730635798b90",
			"created_at": "2025-08-07T02:03:24.788883Z",
			"updated_at": "2026-04-10T02:00:03.785146Z",
			"deleted_at": null,
			"main_name": "COBALT TRINITY",
			"aliases": [
				"APT33 ",
				"Elfin ",
				"HOLMIUM ",
				"MAGNALIUM ",
				"Peach Sandstorm ",
				"Refined Kitten ",
				"TA451 "
			],
			"source_name": "Secureworks:COBALT TRINITY",
			"tools": [
				"AutoCore",
				"Cadlotcorg",
				"Dello RAT",
				"FalseFont",
				"Imminent Monitor",
				"KDALogger",
				"Koadic",
				"NanoCore",
				"NetWire",
				"POWERTON",
				"PoshC2",
				"Poylog",
				"PupyRAT",
				"Schoolbag"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "e5ff825b-0456-4013-b90a-971b93def74a",
			"created_at": "2022-10-25T15:50:23.824058Z",
			"updated_at": "2026-04-10T02:00:05.377261Z",
			"deleted_at": null,
			"main_name": "APT33",
			"aliases": [
				"APT33",
				"HOLMIUM",
				"Elfin",
				"Peach Sandstorm"
			],
			"source_name": "MITRE:APT33",
			"tools": [
				"PowerSploit",
				"AutoIt backdoor",
				"PoshC2",
				"Mimikatz",
				"NanoCore",
				"DEADWOOD",
				"StoneDrill",
				"POWERTON",
				"LaZagne",
				"TURNEDUP",
				"NETWIRE",
				"Pupy",
				"ftp"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "b23e717c-0b27-47e0-b3c8-4defe6dd857f",
			"created_at": "2023-01-06T13:46:38.367369Z",
			"updated_at": "2026-04-10T02:00:02.945356Z",
			"deleted_at": null,
			"main_name": "APT33",
			"aliases": [
				"Elfin",
				"MAGNALLIUM",
				"HOLMIUM",
				"COBALT TRINITY",
				"G0064",
				"ATK35",
				"Peach Sandstorm",
				"TA451",
				"APT 33",
				"Refined Kitten"
			],
			"source_name": "MISPGALAXY:APT33",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		}
	],
	"ts_created_at": 1775490801,
	"ts_updated_at": 1775826748,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/05be21807dcb0d03b9f6ebab924d51f852c1ab95.pdf",
		"text": "https://archive.orkl.eu/05be21807dcb0d03b9f6ebab924d51f852c1ab95.txt",
		"img": "https://archive.orkl.eu/05be21807dcb0d03b9f6ebab924d51f852c1ab95.jpg"
	}
}