{"id":4573,"date":"2023-04-13T09:06:24","date_gmt":"2023-04-13T17:06:24","guid":{"rendered":"https:\/\/www.pnfsoftware.com\/blog\/?p=4573"},"modified":"2023-04-13T09:06:26","modified_gmt":"2023-04-13T17:06:26","slug":"recovering-jni-registered-natives","status":"publish","type":"post","link":"https:\/\/www.pnfsoftware.com\/blog\/recovering-jni-registered-natives\/","title":{"rendered":"Recovering JNI registered natives, recovering protected string constants"},"content":{"rendered":"\n<p>This is part 2 of the blog that introduced the <a href=\"https:\/\/www.pnfsoftware.com\/blog\/android-jni-and-native-code-emulation\/\">major addition that shipped with JEB Pro 4.29<\/a>: the ability for the dex decompiler to call into the native analysis pipeline, the generic decompiler and native code emulator.<\/p>\n\n\n\n<p>Today, we demo how to use two plugins shipping with <strong>JEB 4.30<\/strong>, making use of the emulators to recover information protected by a native code library found in several APKs, <strong>libpairipcore.so<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Recovering statically registered native routines<\/h3>\n\n\n\n<p>The first plugin can be used to discover native routines registered via JNI&#8217;s <code>RegisterNatives<\/code>. As a reminder, when calling a native method from Java, the JNI will see if exported routines with <a href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/technotes\/guides\/jni\/spec\/design.html#resolving_native_method_names\">specific names derived from the Java method signature<\/a> exist in the process. Alternatively, bindings between a Java native method and its actual body can be done with <a href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/technotes\/guides\/jni\/spec\/functions.html#RegisterNatives\">RegisterNatives<\/a>. Typically, this is achieved in <code>JNI_OnLoad<\/code>, the primary entry-point. However, it does not need to; other techniques exist to further obfuscate the target call site of a Java native method, such as unregistration\/re-registration, the obfuscation of <code>JNI_OnLoad<\/code>, etc. More information can be found <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/manual\/android-debugging\/#java-to-native-code-transitions\">here<\/a>.<\/p>\n\n\n\n<p>In its current state, the plugin will attempt to emulate a SO library&#8217;s <code>JNI_OnLoad<\/code> on its own, without the context of the app process it would normally run on. The advantage is that the plugin is useable on libraries recovered without their container app (APK or else). The drawback is that it may fail in complex cases, since the full app context is not available to this plugin. (Note that the second plugin does not suffer this limitation).<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-3.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"747\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-3-1024x747.png\" alt=\"\" class=\"wp-image-4580\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-3-1024x747.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-3-300x219.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-3-768x561.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-3-1536x1121.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-3.png 1944w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Open an APK or Elf SO file(s), run the &#8220;Recover statically-registered natives (Android)&#8221; plugin.<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-4.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"507\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-4-1024x507.png\" alt=\"\" class=\"wp-image-4581\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-4-1024x507.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-4-300x148.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-4-768x380.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-4-1536x760.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-4.png 1971w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Set optional name filters or architecture filters as needed.<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-5.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"130\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-5-1024x130.png\" alt=\"\" class=\"wp-image-4582\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-5-1024x130.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-5-300x38.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-5-768x97.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-5-1536x195.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-5-2048x260.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">The results will be visible in the log. In this case, it looks like the aarch64 library <strong>libpairipcore.so<\/strong> registered one method for <strong>com.pairip.VMRunner.executeVM<\/strong>, and mapped it to a routine at 0x5F180.<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Recovering constants removed from the Dex<\/h3>\n\n\n\n<p>The second plugin makes use of an <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/apidoc\/reference\/com\/pnfsoftware\/jeb\/core\/units\/code\/android\/IEmulatedAndroid.html\">IEmulatedAndroid<\/a> object to simulate an execution environment and execute code that may be restoring static string constants removed from the Dex by code protection systems.<\/p>\n\n\n\n<p>We can imagine that the code protection pass works as such:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-6.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"588\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-6-1024x588.png\" alt=\"\" class=\"wp-image-4583\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-6-1024x588.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-6-300x172.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-6-768x441.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-6-1536x882.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-6.png 1704w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">String constants are being removed during a protection pass.<\/figcaption><\/figure>\n\n\n\n<p>The implementation details of <code>restore()<\/code> are not relevant to this blog entry. In the case of that particular app, it involves calling into a highly obfuscated native library called <strong>libpairipcore.so<\/strong>.<\/p>\n\n\n\n<p>The plugin requires a full APK. It will emulate a static method selected by the user and let them know about the constants that were restored.<\/p>\n\n\n\n<p>The plugin workflow is as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-7.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"189\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-7-1024x189.png\" alt=\"\" class=\"wp-image-4584\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-7-1024x189.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-7-300x55.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-7-768x142.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-7-1536x284.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-7-2048x378.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">After loading an APK, the plugin may let the user know that the code was protected.<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-8.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"585\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-8-1024x585.png\" alt=\"\" class=\"wp-image-4585\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-8-1024x585.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-8-300x172.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-8-768x439.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-8-1536x878.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-8.png 1826w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Execute the &#8220;Recover removed Dex constants&#8221; plugin.<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-9.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"539\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-9-1024x539.png\" alt=\"\" class=\"wp-image-4586\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-9-1024x539.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-9-300x158.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-9-768x405.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-9-1536x809.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-9-2048x1079.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">The user will be asked to input the no-arg static method that should be simulated. If a suitable one is found, it may be pre-populated by the plugin.<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-10.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"433\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-10-1024x433.png\" alt=\"\" class=\"wp-image-4587\" srcset=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-10-1024x433.png 1024w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-10-300x127.png 300w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-10-768x325.png 768w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-10-1536x650.png 1536w, https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2023\/04\/image-10-2048x866.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">The execution can be lengthy, from several seconds to several minutes. Recovered strings are registered as fields comments as well as decompiler events in the relevant dexdec unit of  your project.<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Conclusion<\/h3>\n\n\n\n<p>That&#8217;s it for today. Make sure to update to JEB Pro 4.30 if you want to use those plugins.<\/p>\n\n\n\n<p>I would encourage power-users to explore the JEB&#8217;s API, in particular <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/apidoc\/reference\/com\/pnfsoftware\/jeb\/core\/units\/code\/android\/ir\/IDState.html\">IDState<\/a>, <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/apidoc\/reference\/com\/pnfsoftware\/jeb\/core\/units\/code\/asm\/decompiler\/ir\/EState.html\">EState<\/a>\/<a href=\"https:\/\/www.pnfsoftware.com\/jeb\/apidoc\/reference\/com\/pnfsoftware\/jeb\/core\/units\/code\/asm\/decompiler\/ir\/emulator\/EEmulator.html\">EEmulator<\/a> and <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/apidoc\/reference\/com\/pnfsoftware\/jeb\/core\/units\/code\/android\/IEmulatedAndroid.html\">IEmulatedAndroid<\/a>, if they want to experiment or work on code that requires specific hooks (dex hooks, jvm sandbox hooks, native emu hooks, native memory hooks &#8211; refer to the <code>registerXxxHooks<\/code> methods in <code>IDState<\/code>) for the emulators to operate properly.<\/p>\n\n\n\n<p>Until next time &#8212; Nicolas.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is part 2 of the blog that introduced the major addition that shipped with JEB Pro 4.29: the ability for the dex decompiler to call into the native analysis pipeline, the generic decompiler and native code emulator. Today, we demo how to use two plugins shipping with JEB 4.30, making use of the emulators &hellip; <a href=\"https:\/\/www.pnfsoftware.com\/blog\/recovering-jni-registered-natives\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Recovering JNI registered natives, recovering protected string constants<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[15,22,13,5],"tags":[],"class_list":["post-4573","post","type-post","status-publish","format-standard","hentry","category-android","category-jeb4","category-native-code","category-obfuscation"],"_links":{"self":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/posts\/4573","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/comments?post=4573"}],"version-history":[{"count":0,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/posts\/4573\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/media?parent=4573"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/categories?post=4573"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/tags?post=4573"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}