{"id":18799,"date":"2022-04-19T06:40:05","date_gmt":"2022-04-19T14:40:05","guid":{"rendered":"http:\/\/www.palada.net\/index.php\/2022\/04\/19\/news-12532\/"},"modified":"2022-04-19T06:40:05","modified_gmt":"2022-04-19T14:40:05","slug":"news-12532","status":"publish","type":"post","link":"http:\/\/www.palada.net\/index.php\/2022\/04\/19\/news-12532\/","title":{"rendered":"Using Emulation Against Anti-Reverse Engineering Techniques"},"content":{"rendered":"<div class=\"aem-Grid aem-Grid--12 aem-Grid--default--12\">\n<div class=\"raw-import aem-GridColumn aem-GridColumn--default--12\">\n<div class=\"text-container\"><\/div>\n<\/p><\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p><b>Affected Platforms:<\/b> Windows<\/p>\n<h2>Introduction<\/h2>\n<p>The life of a malware reverse-engineer is not always easy. You might think that it is all fun and games, but in reality, it is bits and assembly. And as it is true for the whole security industry, it is a cat and mouse game with malware developers. As we continuously expose their <a href=\"https:\/\/www.fortinet.com\/resources\/cyberglossary\/malware?utm_source=blog&amp;utm_campaign=malware\">malware<\/a>, which leads us to learn more about the attackers and develop countermeasures, they keep trying to implement new ways of slowing down analysts and reverse engineering. In a recent <a href=\"https:\/\/www.fortinet.com\/blog\/threat-research\/looking-inside-pandoras-box\">blog,<\/a> we analyzed the Pandora ransomware and discussed that it is filled with anti-reverse-engineering techniques, and has multiple layers of code obfuscation.<\/p>\n<p>In this blog post, instead of talking about what we discovered in the Pandora ransomware, I would like to discuss <a>how we did that.<\/a>\u00a0More specifically, we will fight the function call obfuscation and string encryption in this sample, using emulation. We will implement an IDAPython script using the flare-emu framework to turn the disassembly in IDA Pro more readable. This will be a great help in the static analysis of the sample.<\/p>\n<h2>Challenges in Pandora<\/h2>\n<p>For the detailed list of challenges we faced while reversing Pandora, read our <a href=\"https:\/\/www.fortinet.com\/blog\/threat-research\/looking-inside-pandoras-box\">analysis blog<\/a>. In this post I will discuss two specific anti-reverse-engineering techniques that we\u2019ve seen in Pandora:<\/p>\n<p>\u00a0 \u00a0&#8211;\u00a0 \u00a0 Function call obfuscation with opaque predicates\u00a0<\/p>\n<p>\u00a0 \u00a0&#8211;\u00a0 \u00a0 Encrypted strings<\/p>\n<p>First, let\u2019s discuss what these challenges are exactly.<\/p>\n<h3><b>Function Call Obfuscation with Opaque Predicates<\/b><\/h3>\n<p>Figure 1 shows what a simple function call looks like in the Pandora ransomware after it was unpacked.<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn aem-GridColumn--default--5 aem-GridColumn--offset--default--3\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/Using-emulation-against-anti-reverse-engineering-techniques\/_jcr_content\/root\/responsivegrid\/image.img.png\/1650339493814\/graphic-01.png\" alt=\"Screenshot of Standard function call in Pandora ransomware\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 1 &#8211; Standard function call in Pandora<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>We can see that the address of the function that is being called is calculated in runtime. <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">cs:qword_7FF6B6FF9AB8 <\/span><\/span>seems to be the base address of some kind of function address table. Then we use hardcoded values to find the right function pointer in that table and that is what we load into <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">rax<\/span><\/span> before calling it. An <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">opaque predicate<\/span><\/span> generally means an expression in the program whose outcome is known to the programmer, but it still needs to be evaluated in runtime. It is used in many different ways as an obfuscation and anti-analysis technique. In this case, the value that goes in <span style=\"font-family: &quot;Courier New&quot;;\">rax\u00a0<\/span>is fixed, but because it still has to be calculated in runtime it disrupts static-analysis tools.<\/p>\n<p>If we use Figure 1 as an example, the address in rax is calculated like this:<\/p>\n<p><span style=\"font-size: 9.0pt;\"><span style=\"font-family: &quot;Courier New&quot;;\">rax = *(*address_table_base + 0x260BB2E4) + 0xFFFFFFFFAAF7CABC)<\/span><\/span><\/p>\n<p>or in decimal:<\/p>\n<p><span style=\"font-size: 9.0pt;\"><span style=\"font-family: &quot;Courier New&quot;;\">rax = *(*address_table_base + 638300900) &#8211; 1426601284)<\/span><\/span><\/p>\n<p>The trivial solution for such a problem is to run the malware in a debugger and get the address from there. But in this sample all function calls were like this (except those in the statically linked libraries). That means that we would have needed to break at every function call in the debugger just to have the slightest idea of what is happening in the malware. This called for automation.<\/p>\n<h3>Encrypted Strings<\/h3>\n<p>Another challenge of this particular ransomware sample was that all the interesting strings were encrypted. There were a lot of plain text strings in the binary (shown in Figure 2), but they were mostly Windows API function names and the strings in the embedded libraries. None of the strings that would help us understand what the malware is doing are available in plain text. This is very common in modern malware, thus the solution to this challenge could be used against a wide variety of malware.<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn aem-GridColumn--default--6 aem-GridColumn--offset--default--3\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/Using-emulation-against-anti-reverse-engineering-techniques\/_jcr_content\/root\/responsivegrid\/image_331524208.img.png\/1649868723333\/picture2.png\" alt=\"Screenshot of Strings in the Pandora sample\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 2 &#8211; Strings in the Pandora sample<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>Usually when one encounters malware with encrypted strings, there are two approaches:<\/p>\n<p>&#8211;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Use a dynamic approach, such as debugging or emulation, and use the malware\u2019s own string decryption functions to do the work.<\/p>\n<p>&#8211;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Understand the decryption function in such detail that one can reimplement it in a simple script. This is usually the way to go when the encryption is a simple one-byte XOR.<\/p>\n<p>In the case of Pandora, there is not one, but at least 14 different string decryption functions, so reimplementing the decryption algorithm might not always be feasible.<\/p>\n<h2>Emulation<\/h2>\n<p>Emulation allows us to pretend that the code is running on a CPU, but instead of running on a real CPU, the emulation software runs the code. Emulation is usually very slow compared to real execution. However, it allows us full control over what we want to run and a very high level of interaction with the emulated code. With an emulator, for instance, we can emulate just one function of the malware (or even just a couple of lines of code) and evaluate the state of the program at every instruction. A big advantage of emulation in this case is that we can do it directly in IDA Pro.<\/p>\n<h3><b>flare-emu<\/b><\/h3>\n<p><a href=\"https:\/\/github.com\/mandiant\/flare-emu\">flare-emu<\/a>\u00a0is an emulation framework created by the FLARE team at Mandiant. It builds on the well-known emulation engine called\u00a0<a href=\"https:\/\/www.unicorn-engine.org\/\">Unicorn Engine<\/a>\u00a0and IDAPython. One could use the Unicorn Engine directly but <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">flare-emu<\/span><\/span> hides some of its complexities. Essentially, one can define what (which part of the code) one wants to emulate and define callback functions for specific hooks that will be called when the emulation reaches that hook. A good example is the\u00a0<span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">callHook\u00a0<\/span><\/span>parameter, which accepts a callback function that will be called every time a CALL instruction is about to be emulated. In this callback function we can implement whatever we want to do in that situation, i.e., dump registers, change data, skip call, etc. <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">flare-emu<\/span><\/span> turned out to be very straightforward and relatively easy to use (which does not mean that I did not need to look into its source code to figure out a few things).<\/p>\n<h2>Solving the Challenges<\/h2>\n<p>After this extensive introduction, let\u2019s finally\u00a0write some code\u00a0to solve these challenges with an IDAPython script.<\/p>\n<h3><b>Function Call Obfuscation<\/b><\/h3>\n<p>Figure 3 shows again the problem we are trying to solve first. This is the first function call in the <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">main()<\/span><\/span>function in the unpacked part of Pandora\u2019s code. At this point we can be fairly sure that if we emulate the <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">main()<\/span><\/span>function and check <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">rax<\/span><\/span><span style=\"font-size: 11.0pt;\"><span style=\"font-family: Calibri , sans-serif;\">\u2019s\u00a0<\/span><\/span>value before it is called then we get the right result. When we are already there, we could read out the arguments of the function call as well and add all this information to the assembly code as a comment in IDA Pro.<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn aem-GridColumn--default--5 aem-GridColumn--offset--default--3\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/Using-emulation-against-anti-reverse-engineering-techniques\/_jcr_content\/root\/responsivegrid\/image_407055320.img.png\/1649976515536\/figure-3.png\" alt=\"Screenshot of Function call obfuscation\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 3 &#8211; Function call obfuscation<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>Let\u2019s start to put together our IDAPython script. Figure 4 shows how we can initialize the emulation. When we launch the script, it should emulate the function in which the cursor stands at the moment in IDA (returned by <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">get_screen_ea()<\/span><\/span>).<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn aem-GridColumn--default--5 aem-GridColumn--offset--default--3\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/Using-emulation-against-anti-reverse-engineering-techniques\/_jcr_content\/root\/responsivegrid\/image_1318859396.img.png\/1649869142794\/picture4.png\" alt=\"Screenshot of Initialize the emulation\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 4 &#8211; Initialize the emulation<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>To initialize flare-emu, we just need to instantiate an <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">EmuHelper<\/span><\/span><span style=\"font-size: 11.0pt;\"><span style=\"font-family: Calibri , sans-serif;\">. <\/span><\/span>Flare-emu offers different ways to run our emulation. We use the <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">emulateRange()<\/span><\/span> function, which is used to specify a memory range we want to emulate. We set the start address to the beginning of the function and the end address can be omitted (None in python) which means that the emulation will run until a return type instruction is reached. Note that the <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">iterateAllPaths()<\/span><\/span>\u00a0instead of the <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">emulateRange()<\/span><\/span> should also work, however that caused problems due to another obfuscation technique in Pandora, which is not in the scope of this post. But in a less complex malware <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">iterateAllPaths()<\/span><\/span>could be a better option.<\/p>\n<p>When one of <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">flare-emu<\/span><\/span>\u2019s emulation functions is called (<span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">emulateRange()<\/span><\/span>in this case), then the emulation starts. The framework allows us to provide additional details for the emulation, such as processor state with registers and stack, or data for the callback functions, but we don\u2019t need those at this point.<\/p>\n<p><span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">emulateRange()<\/span><\/span>allows us to define callback functions for different hooks:<\/p>\n<p>&#8211;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<b>instruction hook<\/b>: called before the emulation of every instruction. I used this to color every instruction that was emulated in IDA to visualize the coverage of the emulation.<\/p>\n<p>&#8211;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<b>call hook<\/b>: called whenever a CALL type of instruction will be emulated. Note that the called function is not emulated by default.<\/p>\n<p>&#8211;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<b>memory access hook<\/b>: called whenever memory is accessed for reading or writing.<\/p>\n<p>For our current task we only need the <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">callHook<\/span><\/span>. As you can see in line 9 in Figure 4, we already passed the call_hook function name as the\u00a0<span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">callHook\u00a0<\/span><\/span>parameter (might not be the cleverest naming). Next, we need to define the <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">callHook<\/span><\/span> function, which can be seen in Figure 5.<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn aem-GridColumn--default--8 aem-GridColumn--offset--default--2\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/Using-emulation-against-anti-reverse-engineering-techniques\/_jcr_content\/root\/responsivegrid\/image_1537580719.img.png\/1649869402580\/picture5.png\" alt=\"Screenshot of First implementation of call_hook ()\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 5 &#8211; First implementation of call_hook ()<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>We created the <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">call_hook()<\/span><\/span> function, that will be called by the emulator every time before a CALL instruction is emulated. In its current state, this function will log that it was executed, then uses the <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">analysisHelper<\/span><\/span> to check whether the operand in the current CALL instruction is a register or not. If not, then we can return because only the register case is interesting for us. Then we recover the register\u2019s name (<span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">operand_name<\/span><\/span>) and its value (<span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">operand_name<\/span><\/span>) and log them for now. If we run the script against the main function, then we get the results in Figure 6. Note that due to the numerous other evil obfuscations in the Pandora code, this simple script won\u2019t be able to emulate the whole function. But this can be done by extending the script.<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn aem-GridColumn--offset--default--4 aem-GridColumn--default--4\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/Using-emulation-against-anti-reverse-engineering-techniques\/_jcr_content\/root\/responsivegrid\/image_1140100058.img.png\/1649869527486\/picture6.png\" alt=\"Screenshot of Results of the first test\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 6 &#8211; Results of the first test<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>The emulation found three CALL instructions and printed the values of the operand registers. If we think about it, we have mostly solved the problem of function call obfuscation, because we now know which addresses are called by the different CALL instructions. Now we just need to add this to the disassembly in IDA. These are the things we want to do in IDA whenever we resolve a CALL instruction:<\/p>\n<p>&#8211;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Add a comment with the address of the function that is being called<\/p>\n<p>&#8211;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Add a comment with the arguments for that function call<\/p>\n<p>&#8211;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Add a cross-reference in IDA to the function that is called<\/p>\n<p>Figure 7 shows the updated code.<\/p>\n<p>\u00a0<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn aem-GridColumn--default--8 aem-GridColumn--offset--default--2\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/Using-emulation-against-anti-reverse-engineering-techniques\/_jcr_content\/root\/responsivegrid\/image_1829083705.img.png\/1649869600548\/picture7.png\" alt=\"Screenshot of Adding comment and cross-reference\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 7 &#8211; Adding comment and cross-reference<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>When creating the comment we use a nice feature from <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">flare-emu<\/span><\/span>. It allows us to get the function parameters in an architecture-independent way. This malware is <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">x86_64<\/span><\/span> so we could just take <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">rcx<\/span><\/span>, <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">rdx<\/span><\/span>, <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">r8<\/span><\/span>, <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">r9<\/span><\/span>, and the stack, but this way we don\u2019t have to deal with that. One of the arguments the call hook gets is the <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">arguments\u00a0<\/span><\/span>variable and this will contain the values <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">flare-emu<\/span><\/span> thinks are the parameters of this function call. Of course, without analyzing the called function, we won\u2019t know how many parameters are expected so we will just print all of them.<\/p>\n<p>At the end (line 23) we add an IDA cross-reference, which will be a great help further along in our analysis. If we run this code again on the <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">main<\/span><\/span> function, we get the result in Figure 8.<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn aem-GridColumn--default--5 aem-GridColumn--offset--default--3\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/Using-emulation-against-anti-reverse-engineering-techniques\/_jcr_content\/root\/responsivegrid\/image_834857146.img.png\/1649976575990\/figure-8.png\" alt=\"Screenshots of Results of the function call resolution\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 8 &#8211; Results of the function call resolution<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<h3><b>Encrypted String<\/b><\/h3>\n<p>Now that we have the first problem out of the way, and have an emulation framework to work with, we can move onto our second challenge, decrypting the strings. To be able to know which function to emulate to get the strings decrypted, our only requirement is that we need to know which functions are decryption functions. As always, reverse engineering is an iterative process. Once we run the script we wrote on the <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">main<\/span><\/span> function, then we can start to analyze the called functions. So how do we figure out if a function is a decryption function? (Spoiler: <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">0x7ff6b6f971e0\u00a0<\/span><\/span>points to a decryption function.)<\/p>\n<p>A)\u00a0\u00a0\u00a0 We see it in IDA. Without diving deep in the function at <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">0x7ff6b6f971e0<\/span><\/span>, we can see in the graph view (Figure 10) that it is fairly simple and has some loops.<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn aem-GridColumn--default--8 aem-GridColumn--offset--default--2\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/Using-emulation-against-anti-reverse-engineering-techniques\/_jcr_content\/root\/responsivegrid\/image_1721799558.img.png\/1649869932379\/picture9.png\" alt=\"Screenshot of Graph view at the function at 0x7ff6b6f971e0\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 9. &#8211; Graph view at the function at 0x7ff6b6f971e0<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>If we scroll through the code, we find the basic block in Figure 10, where we see that it iterates through some value and XORs it. This indicates that it might be an XOR-based encoding\/encryption.<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn aem-GridColumn--default--6 aem-GridColumn--offset--default--3\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/Using-emulation-against-anti-reverse-engineering-techniques\/_jcr_content\/root\/responsivegrid\/image_930724321.img.png\/1649870002683\/picture10.png\" alt=\"Screenshot of XOR indicates decoding\/decryption\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 10 &#8211; XOR indicates decoding\/decryption<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>B)\u00a0\u00a0\u00a0 We see it in a debugger. Parallel to our static analysis, we of course can also debug the malware (in a safe environment). In the debugger when we see a function that gets some addresses as an input and returns a string, that could mean that it is a decryption function. Figure 11 shows when the function at <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">0x7ff6b6f971e0<\/span><\/span> returns and indeed it returns the string \u201c<span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">ThisIsMutexa<\/span><\/span>\u201d in <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">rcx<\/span><\/span>.<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn aem-GridColumn--default--10 aem-GridColumn--offset--default--1\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/Using-emulation-against-anti-reverse-engineering-techniques\/_jcr_content\/root\/responsivegrid\/image_1007988109.img.png\/1649870115771\/picture11.png\" alt=\"Screenshot of The decrypted string appears in rcx\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 11 &#8211; The decrypted string appears in rcx<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>Once we know that a function is a decryption function, we can rename it accordingly (we used <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">mw_decrypt_str()<\/span><\/span>). Interestingly, Pandora uses multiple decryption functions, which we discovered slowly as we dived deeper into the code. At the end we identified 14 different decryption functions, however most of them looked very similar to Figure 9, which allowed us to quickly see if a function is just another decryption function.<\/p>\n<p>Once we know (some) of the decryption functions, we can improve our IDAPython script to emulate the function call whenever we see that a decryption function is called. This is actually very similar to one of the examples in <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">flare-emu<\/span><\/span>\u2019s documentation, which shows how well such code can often be reused.<\/p>\n<p>Figure 12 shows the updated <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">call_hook()<\/span><\/span> function. Starting from line 23, we first check whether the function at the address we are calling has a name that contains the string <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">mw_decrypt_str<\/span><\/span>. This is how we decide whether the called function is a decryption function. This is not a very scientific method, but we want to reverse malware, not get a PhD.<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn aem-GridColumn--default--8 aem-GridColumn--offset--default--2\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/Using-emulation-against-anti-reverse-engineering-techniques\/_jcr_content\/root\/responsivegrid\/image_117015332.img.png\/1649870245938\/picture12.png\" alt=\"Screenshot of Adding decryption to the call_hook()\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 12 &#8211; Adding decryption to the call_hook()<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>If it is a decryption function, then we call the <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">decrypt()<\/span><\/span>function in our script. This will return the decrypted plain text string. Then we create a comment that will include the decrypted string as well.<\/p>\n<p>How the decryption is emulated can be seen in Figure 13. We create a new <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">EmuHelper<\/span><\/span> instance and when starting <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">emulateRange<\/span><\/span>, we use the function name (<span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">fname<\/span><\/span>) to get the function\u2019s address as the start address. We also pass the first four elements of the <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">argv<\/span><\/span> array as the argument registers. At the end we return the value in <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">argv[0],<\/span><\/span> \u200b\u200b\u200b\u200b\u200b\u200b\u200bwhich should contain the address of the decrypted string.<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn aem-GridColumn--default--8 aem-GridColumn--offset--default--2\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/Using-emulation-against-anti-reverse-engineering-techniques\/_jcr_content\/root\/responsivegrid\/image_599324337.img.png\/1649870380744\/picture13.png\" alt=\"Screenshot of Emulating the decryption\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 13 &#8211; Emulating the decryption<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>After running the script in IDA, the results are shown in Figure 12. The decrypted string was <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">ThisIsMutexa<\/span><\/span>, which was added to the comment and logged in the output.<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn--default--none aem-GridColumn aem-GridColumn--default--8 aem-GridColumn--offset--default--2\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/Using-emulation-against-anti-reverse-engineering-techniques\/_jcr_content\/root\/responsivegrid\/image_54538146.img.png\/1649870458279\/picture14.png\" alt=\"Screenshot of String decryption is successful\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 14 &#8211; String decryption is successful<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>Now we can automatically decrypt strings. As we progress with the analysis of the code and more decryption functions are discovered, we can just rerun the script on the functions that call these decryption functions to recover the plain text strings.<\/p>\n<h2>Conclusion<\/h2>\n<p>The Pandora ransomware is packed with obfuscation and anti-reverse-engineering techniques. In this post we looked at two of these: function call obfuscation and string encryption. We used the <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">flare-emu<\/span><\/span> emulation framework to write an IDAPython script to resolve the addresses and arguments of the function calls as well as emulate the decryption functions to recover the strings as plain text. The final script can be developed further to deal with the other anti-reverse-engineering challenges discussed in the deep dive <a href=\"https:\/\/www.fortinet.com\/blog\/threat-research\/looking-inside-pandoras-box\">analysis<\/a> of the Pandora ransomware.<\/p>\n<h2>Fortinet Protection<\/h2>\n<p>The analyzed Pandora ransomware sample is detected by the following (AV) signature:<\/p>\n<p>W64\/Filecoder.EGYTYFD!tr.ransom<\/p>\n<p>FortiEDR also detects and mitigates execution of Pandora ransomware through the combination of behavioral analysis, and integration with machine learning and threat intelligence feeds. Execution of the Pandora sample analyzed as part of this blog triggers seven rules resulting in nine security events. Triggered rules were a result of pre-execution analysis and post-execution behaviors. These security events can be observed below in Figure 15.<\/p>\n<p>\u00a0<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-image aem-GridColumn aem-GridColumn--default--12\">               <noscript data-cmp-image=\"{&#34;smartImages&#34;:[],&#34;smartSizes&#34;:[],&#34;lazyEnabled&#34;:true}\">             <img decoding=\"async\" src=\"\/blog\/threat-research\/Using-emulation-against-anti-reverse-engineering-techniques\/_jcr_content\/root\/responsivegrid\/image_1805415483.img.png\/1649870570376\/picture15.png\" alt=\"Screenshot of FortiEDR security events generated following execution of Pandora ransomware sample. Note that during this execution, FortiEDR was set to only log events rather than mitigate, to properly demonstrate detections post-execution.\"\/>         <\/noscript>          <span class=\"cmp-image--title\">Figure 15 &#8211; FortiEDR security events generated following execution of Pandora ransomware sample. Note that during this execution, FortiEDR was set to only log events rather than mitigate, to properly demonstrate detections post-execution.<\/span>         <\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p>Pre-execution detections included: identifying the malicious file (hash based), detection of a suspicious packer, and presence of writeable code. Post-execution detections included: detection of each file encryption attempt, detection of encrypted file rename attempt, dropping of the ransom note, and attempts to access SMB shares.<\/p>\n<p>In Protect mode, FortiEDR will detect and mitigate detected behavior. In the case of Pandora, this will prevent execution of the ransomware, mitigating malicious activity before it occurs, and will prevent subsequent file encryption attempts if the adversary is able to execute the sample. The post-exploitation detections are not dependent on signature, meaning they will effectively mitigate this activity for newer Pandora variants even with no prior knowledge of the samples.<\/p>\n<h2>IOCs<\/h2>\n<p>Mutex: <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">ThisIsMutexa<\/span><\/span><br \/> Ransom note: <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">Restore_My_Files.txt<\/span><\/span><br \/> SHA256 hash of hardcoded public key: <span style=\"font-family: &quot;Courier New&quot;;\"><span style=\"font-size: 9.0pt;\">7b2c21eea03a370737d2fe7c108a3ed822be848cce07da2ddc66a30bc558af6b<\/span><\/span><br \/> SHA256 hash of sample: <span style=\"font-family: &quot;Courier New&quot;;\">5b56c5d86347e164c6e571c86dbf5b1535eae6b979fede6ed66b01e79ea33b7b<\/span><\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<h2>ATT&amp;CK TTPs<\/h2>\n<p>\u00a0<\/p>\n<\/p><\/div>\n<div class=\"cmp cmp-text aem-GridColumn aem-GridColumn--default--12\">\n<p><i>Learn more about Fortinet\u2019s\u00a0<a href=\"https:\/\/www.fortinet.com\/fortiguard\/labs?utm_source=blog&amp;utm_campaign=fortiguard-labs\">FortiGuard Labs<\/a>\u00a0threat research and intelligence organization and the FortiGuard Security Subscriptions and Services\u00a0<a href=\"https:\/\/www.fortinet.com\/fortiguard\/labs?tab=security-bundles&amp;utm_source=blog&amp;utm_campaign=security-bundles\">portfolio<\/a>.<\/i><\/p>\n<\/p><\/div>\n<div class=\"raw-import aem-GridColumn aem-GridColumn--default--12\">\n<div class=\"text-container\">\n<div id=\"om-b2dxtopzidsdt3fkzfsv-holder\"><\/div>\n<\/div><\/div>\n<\/p><\/div>\n<p><a href=\"https:\/\/www.fortinet.com\/blog\/threat-research\/Using-emulation-against-anti-reverse-engineering-techniques\" target=\"bwo\" >http:\/\/feeds.feedburner.com\/fortinet\/blog\/threat-research<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p><img decoding=\"async\" src=\"\/blog\/threat-research\/Using-emulation-against-anti-reverse-engineering-techniques\/_jcr_content\/root\/responsivegrid\/image.img.png\/1650339493814\/graphic-01.png\"\/><br \/>In this blog post, the FortiGuard Labs team reviews how to use emulation against anti-reverse engineering techniques using the Pandora ransomware as an example. Learn more.<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"colormag_page_container_layout":"default_layout","colormag_page_sidebar_layout":"default_layout","footnotes":""},"categories":[10424,10378],"tags":[],"class_list":["post-18799","post","type-post","status-publish","format-standard","hentry","category-fortinet","category-security"],"_links":{"self":[{"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/posts\/18799","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/comments?post=18799"}],"version-history":[{"count":0,"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/posts\/18799\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/media?parent=18799"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/categories?post=18799"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/tags?post=18799"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}