{"id":7249,"date":"2017-04-06T02:40:56","date_gmt":"2017-04-06T10:40:56","guid":{"rendered":"http:\/\/www.palada.net\/index.php\/2017\/04\/06\/news-1040\/"},"modified":"2017-04-06T02:40:56","modified_gmt":"2017-04-06T10:40:56","slug":"news-1040","status":"publish","type":"post","link":"http:\/\/www.palada.net\/index.php\/2017\/04\/06\/news-1040\/","title":{"rendered":"How to repair a DEX file, in which some key methods are erased with NOPs"},"content":{"rendered":"<p><strong>Credit to Author: Kai Lu| Date: Wed, 05 Apr 2017 03:33:38 -0700<\/strong><\/p>\n<div class=\"entry\">\n<p>During the process of analyzing android malware, we usually meet some APK samples which hide or encrypt their main logic code.&nbsp; Only at some point does the actual code exist in the memory, so we need to find the right time to extract it.&nbsp; In this blog, I present a case study on how to repair a DEX file in which some key methods are erased with NOPs and decrypted dynamically when ready to be executed.<\/p>\n<p><span style=\"color:#FF0000;\"><em>Note: All the following analysis is based on android-4.4.2_r1(KOT49H).<\/em><\/span><\/p>\n<p>Let&rsquo;s start our journey!<\/p>\n<p>First, I open the classes.dex file in some decompiling tools, as shown below.<\/p>\n<p align=\"center\"><img decoding=\"async\" alt=\"Figure 1.  The decompiling result in some tools\" src=\"https:\/\/d3gpjj9d20n0p3.cloudfront.net\/ngblog\/uploads\/files\/repairDEX001.png\" style=\"width: 837px; height: 677px;\" \/><\/p>\n<p align=\"center\">Figure 1.&nbsp; The decompiling result in some tools<\/p>\n<p>From Figure 1, we can see the code in each method is erased. Next, we first use 010 Editor to parse the dex file, as follows.<\/p>\n<p align=\"center\"><img decoding=\"async\" alt=\"Figure 2.\u00a0 010 Editor fails to parse the Dex file\" src=\"https:\/\/d3gpjj9d20n0p3.cloudfront.net\/ngblog\/uploads\/files\/repairDEX003.png\" style=\"width: 1203px; height: 341px;\" \/><\/p>\n<p align=\"center\">Figure 2.&nbsp; 010 Editor fails to parse the Dex file<\/p>\n<p>The parsing of the classes.dex file in 010 Editor fails. This should be caused because some fields inside the DEX file have been modified. These modified fields may be some offset fields that mark the offsets inside the file. If the value of offset is beyond the size of the DEX file, it causes the parsing failure.<\/p>\n<p>The length of the DEX file is 0x2B2DD8.<\/p>\n<p>I developed a program with C++ to parse the DEX file to check for abnormal fields. Some output is shown below.<\/p>\n<p><img decoding=\"async\" alt=\"Figure 3. Output of parsing Dex file with a C++ program\" src=\"https:\/\/d3gpjj9d20n0p3.cloudfront.net\/ngblog\/uploads\/files\/repairDEX005.png\" style=\"width: 963px; height: 375px;\" \/><\/p>\n<p align=\"center\">Figure 3. Output of parsing Dex file with a C++ program<\/p>\n<p>We can see the value of field &ldquo;debugInfoOff&rdquo; is abnormal in struct DexCode, which is larger than file size 0x2b2dd8. In this sample, these abnormal debugInfoOff fields are from 0x3ffff30 to 0x4000000.<\/p>\n<p align=\"center\"><img decoding=\"async\" alt=\"Figure 4. The definition of struct DexCode\" src=\"https:\/\/d3gpjj9d20n0p3.cloudfront.net\/ngblog\/uploads\/files\/repairDEX007.png\" style=\"width: 648px; height: 227px;\" \/><\/p>\n<p align=\"center\">Figure 4. The definition of struct DexCode<\/p>\n<p>In order to parse the DEX file correctly in 010 Editor, I repaired the debugInfoOff field. &nbsp;I use the method &ldquo;OnCreate&rdquo; in class MainActivity as an example to show the parsing of the repaired DEX file in 010 Editor.<\/p>\n<p><img decoding=\"async\" alt=\"Figure 5. The parsing of DEX file after repairing the debugInfoOff field\" src=\"https:\/\/d3gpjj9d20n0p3.cloudfront.net\/ngblog\/uploads\/files\/repairDEX009.png\" style=\"width: 1430px; height: 265px;\" \/><\/p>\n<p align=\"center\">Figure 5. The parsing of DEX file after repairing the debugInfoOff field<\/p>\n<p>I next modified the debugInfoOff field to zero. The insns_size is the length of instructions in code. One instruction has two bytes, so the length of the code is 0x74.&nbsp;&nbsp; The method code starts with bytecode |0E 00|, the rest of instructions are NOPs. The bytecode |0E 00 | represents return-void. &nbsp;<\/p>\n<p>The question is, how to get the actual bytecodes in the method?&nbsp; Based on my analysis, some key methods are extracted and erased with NOPs. Before a method is ready to be executed, the program could decrypt these bytecodes in the method, and after being executed the decrypted bytecodes will be restored with the original NOPs bytecodes.&nbsp;&nbsp;<\/p>\n<p>In Dalvik VM, a principle is that when only one method is being executed the bytecodes in it must be correct. In other words, if one method is still not executed, it&rsquo;s possibl that its bytecode could be incorrect.&nbsp; So the sample just takes advantage of this principle to implement a dynamical decryption method before one method is ready to be executed.<\/p>\n<p>Next, I looked into how to decrypt a method dynamically before the method is ready to be executed. Through some reverse engineering and analysis, I found that the program can hook the method <a name=\"dvmResolveClass\"><\/a><a href=\"http:\/\/androidxref.com\/4.4.2_r2\/xref\/dalvik\/vm\/oo\/Resolve.cpp#63\">dvmResolveClass<\/a> inside dalvik VM. When a method in a class is executed, the loading of the class must be completed. The method dvmResolveClass is invoked when loading a class. &nbsp;&nbsp;<\/p>\n<p>Following are the ARM instructions of the method dvmResolveClass in IDA Pro.<\/p>\n<p align=\"center\"><img decoding=\"async\" alt=\"Figure 6.\u00a0 The correct ARM instructions of dvmResolveClass in IDA Pro\" src=\"https:\/\/d3gpjj9d20n0p3.cloudfront.net\/ngblog\/uploads\/files\/repairDEX011.png\" style=\"width: 994px; height: 539px;\" \/><\/p>\n<p align=\"center\">Figure 6.&nbsp; The correct ARM instructions of <a href=\"http:\/\/androidxref.com\/4.4.2_r2\/xref\/dalvik\/vm\/oo\/Resolve.cpp#63\">dvmResolveClass<\/a> in IDA Pro<\/p>\n<p>Next, I continued to look into the hooked dvmResolveClass when dynamically debugging in IDA Pro.<\/p>\n<p align=\"center\"><img decoding=\"async\" alt=\"Figure 7. Hooked dvmResolveClass\" src=\"https:\/\/d3gpjj9d20n0p3.cloudfront.net\/ngblog\/uploads\/files\/repairDEX013.png\" style=\"width: 1023px; height: 187px;\" \/><\/p>\n<p align=\"center\">Figure 7. Hooked dvmResolveClass<\/p>\n<p>When the arm instruction is executed the program will jump to sub_75485310. The following is the execution flow of sub_75485310:<\/p>\n<p align=\"center\"><img decoding=\"async\" alt=\"Figure 8.\u00a0 The execution flow of sub_75485310\" src=\"https:\/\/d3gpjj9d20n0p3.cloudfront.net\/ngblog\/uploads\/files\/repairDEX015.png\" style=\"width: 1139px; height: 641px;\" \/><\/p>\n<p align=\"center\">Figure 8.&nbsp; The execution flow of sub_75485310<\/p>\n<p>The ARM instruction &ldquo;BLX R3&rdquo; is to execute the actual method dvmResolveClass. Then the program executes the instruction at address 0x75938000. At address 0x75938014 the program will then jump to 0x414E468A to enter into the scope of the actual method dvmResolveClass.<\/p>\n<p align=\"center\">&nbsp;<img decoding=\"async\" alt=\"Figure 9. The execution flow of 0x75938000\" src=\"https:\/\/d3gpjj9d20n0p3.cloudfront.net\/ngblog\/uploads\/files\/repairDEX017.png\" style=\"width: 879px; height: 256px;\" \/><\/p>\n<p align=\"center\">Figure 9. The execution flow of 0x75938000<\/p>\n<p align=\"center\"><img decoding=\"async\" alt=\"Figure 10. Return to the scope of actual method dvmResolveClass\" src=\"https:\/\/d3gpjj9d20n0p3.cloudfront.net\/ngblog\/uploads\/files\/repairDEX019.png\" style=\"width: 935px; height: 504px;\" \/><\/p>\n<p align=\"center\">Figure 10. Return to the scope of actual method dvmResolveClass<\/p>\n<p>Now that the program hooks the method dvmResolveClass, and at this time the correct bytecodes of the method have been in the memory. The pointer insns in struct Method stores these actual bytecodes.&nbsp; The definition of struct Method is shown below:<\/p>\n<p align=\"center\"><img decoding=\"async\" alt=\"Figure 11. The definition of struct Method\" src=\"https:\/\/d3gpjj9d20n0p3.cloudfront.net\/ngblog\/uploads\/files\/repairDEX021.png\" style=\"width: 821px; height: 487px;\" \/><\/p>\n<p align=\"center\">Figure 11. The definition of struct Method<\/p>\n<p>Next, we get these actual bytecodes through modifying the source code in method dvmResolveClass.<\/p>\n<p>The following are some added key codes.<\/p>\n<p align=\"center\"><img decoding=\"async\" alt=\"Figure 12. The key code added in dvmResolveClass to get actual bytecodes\" src=\"https:\/\/d3gpjj9d20n0p3.cloudfront.net\/ngblog\/uploads\/files\/repairDEX023.png\" style=\"width: 1477px; height: 686px;\" \/><\/p>\n<p align=\"center\">Figure 12. The key code added in <a href=\"http:\/\/androidxref.com\/4.4.2_r2\/xref\/dalvik\/vm\/oo\/Resolve.cpp#63\">dvmResolveClass<\/a> to get actual bytecodes<\/p>\n<p>We then saved these actual bytecodes in a local file.<\/p>\n<p align=\"center\"><img decoding=\"async\" alt=\"Figure 13. The saved file includes actual bytecodes\" src=\"https:\/\/d3gpjj9d20n0p3.cloudfront.net\/ngblog\/uploads\/files\/repairDEX025.png\" style=\"width: 888px; height: 620px;\" \/><\/p>\n<p align=\"center\">Figure 13. The saved file includes actual bytecodes<\/p>\n<p>Finally, combining the output of Figure 3 and this saved file, I developed a python script to patch the original classes.dex file, and the repaired classes.dex is shown below.<\/p>\n<p align=\"center\"><img decoding=\"async\" alt=\"Figure 14.\u00a0 Compare the repaired dex file with original dex file\" src=\"https:\/\/d3gpjj9d20n0p3.cloudfront.net\/ngblog\/uploads\/files\/repairDEX027.png\" style=\"width: 864px; height: 608px;\" \/><\/p>\n<p align=\"center\">Figure 14.&nbsp; Compare the repaired dex file with original dex file<\/p>\n<p align=\"center\"><img decoding=\"async\" alt=\"Figure 15.\u00a0 Decompiling the repaired dex file in dex decompiling tool\" src=\"https:\/\/d3gpjj9d20n0p3.cloudfront.net\/ngblog\/uploads\/files\/repairDEX029.png\" style=\"width: 819px; height: 594px;\" \/><\/p>\n<p align=\"center\">Figure 15.&nbsp; Decompiling the repaired dex file in dex decompiling tool<\/p>\n<p>Comparing Figure 1 and Figure 15, we can see that these actual smali instructions have been restored.<\/p>\n<p>Because the android system is open-sourced, we can understand the implementation of the dalvik VM well through reading source codes from AOSP.&nbsp; You can modify the source code inside dalvik VM and develop your own tool to repair different kinds of hardened DEX files.<\/p>\n<\/div<br \/><a href=\"http:\/\/blog.fortinet.com\/2017\/04\/05\/how-to-repair-a-dex-file-in-which-some-key-methods-are-erased-with-nops\" target=\"bwo\" >https:\/\/blog.fortinet.com\/feed<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p><img decoding=\"async\" src=\"https:\/\/d3gpjj9d20n0p3.cloudfront.net\/ngblog\/uploads\/files\/repairDEX001.png\"\/><\/p>\n<p><strong>Credit to Author: Kai Lu| Date: Wed, 05 Apr 2017 03:33:38 -0700<\/strong><\/p>\n<p>During the process of analyzing android malware, we usually meet some APK samples which hide or encrypt their main logic code.\u00a0 Only at some point does the actual code exist in the memory, so we need to find the right time to extract it.\u00a0 In this blog, I present a case study on how to repair a DEX file in which some key methods are erased with NOPs and decrypted dynamically when ready to be executed.    Note: All the following analysis is based on android-4.4.2_r1(KOT49H).    Let\u2019s start our journey!    First, I open the classes.dex&#8230;<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"closed","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-7249","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\/7249","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=7249"}],"version-history":[{"count":0,"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/posts\/7249\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/media?parent=7249"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/categories?post=7249"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/tags?post=7249"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}