{"id":874,"date":"2018-09-10T09:10:50","date_gmt":"2018-09-10T17:10:50","guid":{"rendered":"https:\/\/www.pnfsoftware.com\/blog\/?p=874"},"modified":"2018-12-19T13:33:01","modified_gmt":"2018-12-19T21:33:01","slug":"dynamic-jni-detection-plugin","status":"publish","type":"post","link":"https:\/\/www.pnfsoftware.com\/blog\/dynamic-jni-detection-plugin\/","title":{"rendered":"Dynamic JNI Detection Plugin"},"content":{"rendered":"<p><em>Update (Nov 29): the plugin was open-sourced on <a href=\"https:\/\/github.com\/pnfsoftware\/jnihelper\">our GitHub repository<\/a>. JEB 3.0.7+ is required to load and run it.<\/em><\/p>\n<p>Java applications can call native methods stored in dynamic libraries via the <em>Java Native Interface<\/em> (JNI) framework. Android apps can do the same: developers can use the NDK to write their own <em>.so<\/em> library to use and distribute.<\/p>\n<p>In this post, we briefly present how the binding mechanisms work, allowing a piece of bytecode to invoke native code routines.<\/p>\n<h2>Named Convention Method<\/h2>\n<p>The easiest way to call native method is as such:<\/p>\n<p>In Java, class <strong>com.example.hellojni.HelloJni<\/strong>:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/09\/cfefab35babeaa54a376df5c77f9a048.png\" \/><\/p>\n<p>In C:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/09\/0757d99435fe6eac997ed8e161ecfa0b.png\" \/><\/p>\n<p>The native method name adheres to the standard <a href=\"https:\/\/docs.oracle.com\/javase\/7\/docs\/technotes\/guides\/jni\/spec\/design.html#wp615\">JNI naming convention<\/a>, allowing automatic resolution and binding.<\/p>\n<p>The corresponding Dalvik bytecode is:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/09\/e0e056b1f029661688004f0fd2888cea.png\" \/><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/09\/70d061ea33a87a65217c4d4d8328bc66.png\" \/><\/p>\n<p>and here are the the corresponding ARM\u00a0instructions:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/09\/1149475387bee1f8a99c89d2b463ddd4.png\" \/><\/p>\n<p>JEB automatically binds those methods together, to allow easy debugging from bytecode to native code.<\/p>\n<p>However, there is another way to bind native code to Java.<\/p>\n<h2>Dynamic JNI Method<\/h2>\n<p>One can decide to bind any function to Java without adhering to the naming convention, by using the JNIEnv-&gt;<a href=\"https:\/\/docs.oracle.com\/javase\/7\/docs\/technotes\/guides\/jni\/spec\/functions.html#wp5833\">RegisterNatives<\/a> method.<\/p>\n<p>For example, the following line of code dynamically binds the Java method add(II)I to the native method add():<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/09\/21e020254939e41b0d5de723f0004398.png\" \/><\/p>\n<p>Due to its dynamic nature, statically resolving those bindings can prove difficult in practice, e.g. if names were removed or mangled, or if the code is obfuscated. Therefore, not all calls to RegisterNatives may be found and\/or successfully processed.<\/p>\n<p>However, <em>JEB 3.0-beta.2<\/em>\u00a0(to\u00a0 be released this week) ships with an <a href=\"https:\/\/www.pnfsoftware.com\/jeb\/apidoc\/reference\/com\/pnfsoftware\/jeb\/core\/IEnginesPlugin.html\">EnginesPlugin<\/a> to heuristically detect &#8211; some of &#8211; these methods, and perform binding &#8211; and of course, you will also be able to debug into them.<\/p>\n<figure style=\"width: 1034px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/09\/7ab34d881404a54b762b4a93a12a572a.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/09\/7ab34d881404a54b762b4a93a12a572a.png\" alt=\"\" width=\"1034\" height=\"622\" \/><\/a><figcaption class=\"wp-caption-text\">Execute the plugin via the File, Plugins menu<\/figcaption><\/figure>\n<p>Once run, it will :<\/p>\n<ul>\n<li>annotate the dex code with the target addresses:<\/li>\n<\/ul>\n<p><a href=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/09\/ecf1ad360958e139f89c974030a13c9a.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/09\/ecf1ad360958e139f89c974030a13c9a.png\" alt=\"\" width=\"870\" height=\"214\" \/><\/a><\/p>\n<ul>\n<li>rename targets (prefixing names with\u00a0<em>__jni_<\/em>) :<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/09\/782bc19dafc07f77650e53b90d96b228.png\" \/><\/p>\n<ul>\n<li>enable you to seamlessly debug into them (jump from <em>Java<\/em> to this <em>JNI<\/em> method)<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/09\/b05889104708cb62c16ad0d6eea951e9.png\" \/><\/p>\n<p>&nbsp;<\/p>\n<h2>Heuristics<\/h2>\n<p>As of this writing, the plugin uses several heuristics, implemented for ARM and ARM64 (Aarch64):<\/p>\n<ul>\n<li>The first is the simplest one:\u00a0the <em>JNIEnv-&gt;RegisterNatives<\/em> method is commonly called from the standard JNI initialization function\u00a0<a href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/technotes\/guides\/jni\/spec\/invocation.html#JNJI_OnLoad\"><em>JNI_OnLoad<\/em><\/a>, so JEB searches for this method and attempt to find calls to RegisterNatives.<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/09\/9f2014268b1be3cc3cdbb929845f696e.png\" \/><\/p>\n<p>Once the &#8216;<em>BL RegisterNatives<\/em>&#8216; is found, JEB uses the\u00a0decompiler to create an IR representation of the block, and determines the values of R2 and R3 (X2 and X3 on Aarch64). R3 indicates the number of native methods to register, R2 is a pointer to the array of JNI native methods (structure with a pointer to method name, a pointer to method signature and a pointer to the native function bound):<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/09\/a3992db130d75c65fc4fa89da1c145ea.png\" \/><\/p>\n<p>Even if accurate, this method does not work when a Branch is issued via a register (<em>BL R4<\/em>) or method name is hidden.<\/p>\n<ul>\n<li>The second heuristic is based on method name. First, in Dalvik, we search for all invocations to native methods. Then, for each method found, we search in binaries if there is a String reference matching the method name. (This heuristic is dangerous but yields decent results. A future plugin update may allow users to disable it.)<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/09\/b1b62f770e7af6e8d3d0a67896eab27e.png\" \/><\/p>\n<p>If found, the plugin looks at cross references of this String and checks if it looks like the expected JNI structure.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.pnfsoftware.com\/blog\/wp-content\/uploads\/2018\/09\/c85a274c1f43706d4eaff0736e725792.png\" \/><\/p>\n<ul>\n<li>The third and last heuristic is the same as the previous one, but based on arguments. Since names can be shortened, they may not be interpreted as String, and thus not referenced, whereas it is easier to find argument signatures.<\/li>\n<\/ul>\n<p>These three heuristics only work when methods are defined as a static array variable. Dynamic variables would need some emulation of the <em>JNI_OnLoad<\/em> method to be resolved.<\/p>\n<p>As you can see, detection is currently based on heuristics, so obfuscated methods may be missing. Feel free to tweak and improve the plugin, it is available on <a href=\"https:\/\/github.com\/pnfsoftware\/jnihelper\">our GitHub repository<\/a>. As usual, feel free to reach out to us (email, Twitter, Slack) if you have questions or suggestions.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Update (Nov 29): the plugin was open-sourced on our GitHub repository. JEB 3.0.7+ is required to load and run it. Java applications can call native methods stored in dynamic libraries via the Java Native Interface (JNI) framework. Android apps can do the same: developers can use the NDK to write their own .so library to &hellip; <a href=\"https:\/\/www.pnfsoftware.com\/blog\/dynamic-jni-detection-plugin\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Dynamic JNI Detection Plugin<\/span><\/a><\/p>\n","protected":false},"author":5,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[15,14,18,13],"tags":[],"class_list":["post-874","post","type-post","status-publish","format-standard","hentry","category-android","category-debugging","category-jeb3","category-native-code"],"_links":{"self":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/posts\/874","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\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/comments?post=874"}],"version-history":[{"count":0,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/posts\/874\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/media?parent=874"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/categories?post=874"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pnfsoftware.com\/blog\/wp-json\/wp\/v2\/tags?post=874"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}