Exploration of Native Modules on Android with Frida

Exploration of Native Modules on Android with Frida

In this blog, we will demonstrate the Use of Frida for instrumentation of Native Modules in Android Application while doing android Application Pentesting. also explain the Frida Android Apis. We will show you some examples that highlight what Frida can do.
In our Previous Blog, you are already familiar with Frida, if you didn’t familiar with Frida please go through the previous blog. Getting started with Frida on Android Apps

Prerequisites

Before starting with Exploration_of_Native_Modules_on_Android, it is assumed that the reader has prior knowledge of Frida, and also has a basic understanding of NDK(Native development kit). It would help to better Understanding of API calls and build your own custom tools while exploring/enumerating Application native modules.

Introduction

Mobile security testing of Android applications includes code reviews to understand how the application logic and flow works and identify potential security vulnerabilities. If the app was developed in Java, decompiling the app means reversing the compilation process to extract the Java source code from the binary compiled code. but If native Libraries are used in the application then It is not possible to decompile and retrieve the source code of a compiled C/C++ native library.
In such a case Frida is a very useful tool. It allows the penetration tester to inject their code (JavaScript) inside a program.

let’s Have A Basic Overview About Some Basic Terms of Native Library Implementation in Android.

What is Android NDK?

The NDK (Native Development Kit) is a tool that allows you to program in C/C++ for Android devices. It’s intended to integrate with the SDK (it’s described as a “companion tool”) and used only for performance-critical portions of a project.
The source code is compiled directly into machine code for the CPU (and not into an intermediate language, as with Java) then developerscano get the best performance.
So, whenever you want to make some high-performance applications for great speed or want to use some preexisting code written in some native language then you can use C or C++

What if you want to use both Java/Kotlin and native language in your application? This is the most used case. Is it possible to use Java code from C++ and vice-versa? How will the Java code communicate with the native code? The communication is done by JNI. What is this JNI?

What is JNI ?

  • JNI or Java Native Interface is the interface between your Java/Kotlin and the C/C++ code.
  • To be able to call native libraries from Java code, a framework named Java Native Interface (JNI) is used. Using this interface, C/C++ functions are mapped as methods and
    primitive data types are converted between Java and C/C++.
  • For this to work, special syntax is needed for JNI to recognize which method in which class a native function should correspond to.
  • To mark a function as native in Java, a special keyword called native is used to define a method.
  • Java or Kotlin Code uses JNI to communicate with the C or C++ code.

Now we have basic understanding about the NDk,JNI , and their compilation process in android. Lets Proceed to the Enumeration and Hooking Part of Native Libraries .

Finding native libraries

  • First of all, we must understand if the app actually uses any native functions, therefore we need to locate these native libraries.
  • A native library is a .so file, where “so” stands for Shared Object, which is essentially a compiled C file. On Android, we can have two types of native library: system (for example libc.so) and custom application ones (for example myApp.so). Custom libs for the apps in their respective app directories (_/data/data/package_name/lib/).
  • Or You can check the Application specific library by extracting the application in their repective directories .

imgae-2

![](https://payatu.com/static/images/remoteblogs/amit/exploration_of_native_modules_on_android_with_frida/Pasted image 20210708141118.png)

Having identified native libraries are being used, the next step consists of inspecting the Java class code to understand where and when these native libraries are actually loaded by the app. This task can be done by searching for the Java method: System.loadLibrary().

![](https://payatu.com/static/images/remoteblogs/amit/exploration_of_native_modules_on_android_with_frida/Pasted image 20210708141601.png)

Finding Native Functions

we need to identify the actual C functions implemented in these native libraries. These are invoked directly within the app and are the link between C and Java. This link is defined by the JNI (Java Native Interface), which requires these functions to be declared within a Java class file by using the keyword “native” and then wrapped inside a normal Java method.

  • Decalration of native function in Java class file

![](https://payatu.com/static/images/remoteblogs/amit/exploration_of_native_modules_on_android_with_frida/Pasted image 20210708142128.png)

  • Actual Native functions In Native Library

![](https://payatu.com/static/images/remoteblogs/amit/exploration_of_native_modules_on_android_with_frida/Pasted image 20210713163902.png)

So far we have learned to find native libraries and native functions in android application . Lets Enumerate /Inspect native functions dynamically Using Frida

Dynamic Exploration Using Frida

Using frida-trace

frida-trace is a tool for dynamically Monitoring/tracing Method calls. It is useful for debugging method calls on every event in mobile application.

Code-Snippets:

  • Tracing all Functions Calls In native Library
frida-trace -U -I "libnative-lib*" com.example.nativrproject

this command shows usage to trace any function for a given library, specified by the “the -I”

![](https://payatu.com/static/images/remoteblogs/amit/exploration_of_native_modules_on_android_with_frida/Pasted image 20210713172917.png)

  • Tracing JNI functions in Native Library
frida-trace -U -i “Java_*” [package_name]

This command shows usage to trace all JNI function.

![](https://payatu.com/static/images/remoteblogs/amit/exploration_of_native_modules_on_android_with_frida/Pasted image 20210713173021.png)

TO know more about frida-trace :
Usages

frida-trace --help

Using Frida Apis

Process.enumerateModules:

This will return an array of Module objects that have been loaded at runtime by the spawned app process

Basically this Frida API enumerate all Native library that is loaded at runtime of application

A Frida Module object has the following properties (similar to a Java class variable):

  • name: representing the name of the module as a string
  • base: representing the base, initial address (in a hexadecimal representation) of that module currently loaded in memory
  • size: representing how big the module is in bytes
  • path: representing the full filesystem path as a string

Code-Snippet:

var process = Process.enumerateModules()

console.log(process.length)

var i =0;

for(i=0;i<process.length;i++){

console.log(JSON.stringify(process[i]))

}
  • OR you can simply check by Process.enumerateModules()
Spawn the application :-> frida -U com.example.nativrproject

Entered into the shell :> Process.enumerateModules()

![](https://payatu.com/static/images/remoteblogs/amit/exploration_of_native_modules_on_android_with_frida/Pasted image 20210714125034.png)

Process.enumerateExports:

This Returns an array of objects representing Exports, these are then represented as text with JSON.stringify().

An Export object has the following properties:

  • type: representing what the export is, it can be either a function or a variable
  • name: representing the name of this function/variable
  • address: representing the current memory address of this specific function/variable

This API Will return all exported functions,variable of given module.

Code-Snippet

  • Enumerate all functions & Variable of the Given Module
var process = Process.enumerateModules()

console.log(process.length)

var i =0;

for(i=0;i<process.length;i++){

if(process[i].path.indexOf('libnative-lib')!=-1)

{

console.log(JSON.stringify(process[i])+"n")

var exports = process[i].enumerateExports()

for(var j =0;j<exports.length;j++){

console.log(JSON.stringify(exports[j]))

}}}
  • Enumerate all The JNI Functions In Given module
var process = Process.enumerateModules()

//console.log(process.length)

var i =0;

for(i=0;i<process.length;i++){

if(process[i].path.indexOf('libnative-lib')!=-1)

{

//console.log(JSON.stringify(process[i])+"n")

var exports = process[i].enumerateExports()

for(var j =0;j<exports.length;j++){

//console.log(JSON.stringify(exports[j]))

if(exports[j].name.indexOf('Java_')!=-1)

{

console.log(JSON.stringify(exports[j])+"n")

} } } }

_The script can only enumerate the modules loaded at its execution.
Using the memory base address and the size of library, monitor the memory to extract useful values
We can only enumerate modules from above Frida Apis . but cant’t hook in specific method in android application.so For solving these issues frida provides a powerful API Interceptor.
By Using Interceptor we can intercept calls of a Specific target function while the app is running.

interceptor.attach

Interceptor.attach(target, callbacks[, data]): intercept calls to function at target. This is a NativePointer specifying the address of the function you would like to intercept calls to.

target is required input of this API is a pointer indicating the current memory address of the target function. Therefore, either we provide the actual address , or we use Module.getExportbyName().

Frida takes care of this detail for you if you get the address from a Frida API (for example Module.getExportByName()).

Module.getExportByName() : which will return a pointer to the function given as input. if a specified function is not found then this will return an error.

![](https://payatu.com/static/images/remoteblogs/amit/exploration_of_native_modules_on_android_with_frida/Pasted image 20210714131623.png)

The callbacks argument is an object containing one or more of:

  • callback function given one argument args that can be used to read or write arguments as an array of NativePointer objects.
  • onLeave(retval): callback function given one argument retval that is a NativePointer-derived object containing the raw return value.
  • retval.replace(ptr("0x1234")) to replace with a pointer

Code-Snippets

Interceptor.attach(Module.findExportByName('libnative-lib.so','Java_com_example_nativrproject_MainActivity_stringFromJNI'),{
onEnter: function(args)
{

    console.log("enterd" )

},
 onLeave: function (retval) {

    //changing return value !!!!

            console.log("leaving")
       }

})

In above code Snippet:

  • Module.findExportByName(‘libnative-lib.so’,’Java_com_example_nativrproject_MainActivity_stringFromJNI)’ – Return Pointor to function Java_com_example_nativrproject_MainActivity_stringFromJNI
    • The callbacks for onEnter and onLeave that will be executed when and if the function is ever used by the running app.

![](https://payatu.com/static/images/remoteblogs/amit/exploration_of_native_modules_on_android_with_frida/Pasted image 20210714132605.png)

Brief Demonstration of Native Function Hooking!!!

Lets take an example :

  • android native code
#include <jni.h>
#include <string>

extern "C" JNIEXPORT jint JNICALL
Java_com_example_nativrproject_MainActivity_add( JNIEnv *env, jclass abcd, jint x, jint y) {

    //return an integer
    return x *y;
}
  • JAVA Code

Application with above code print 3*4 =12 in logs. Lets hook the application jni function and check whats paramteres are passing . we are here only to hook and enumerate Native functions not Java functions.

Interceptor.attach(Module.findExportByName('libnative-lib.so','Java_com_example_nativrproject_MainActivity_add'),{

onEnter(args){

     console.log('Context information:');

    // Save arguments for processing in onLeave.

    console.log("first parameter" +args[2].toInt32());
    console.log("second parameter"+ args[3].toInt32());

},

onLeave(result)
{

console.log('----------')
    // Show argument 1 (buf), saved during onEnter.
            console.log("result" + result);

            //const dstAddr = Java.vm.getEnv().newStringUtf("1234");

    const numBytes = result.toInt32();
      console.log('Result   : ' + numBytes);
  }

});

Code-snippets for Native Code Manipulation

Interceptor.attach(Module.findExportByName('libnative-lib.so','Java_com_example_nativrproject_MainActivity_stringFromJNI'),{

onEnter: function(args)
{

    console.log("enterd" )

},
 onLeave: function (retval) {

    //changing return value !!!!

            const dstAddr = Java.vm.getEnv().newStringUtf("1234");
            console.log(dstAddr)
            retval.replace(dstAddr);
        }

})

References

About Payatu

Payatu is a Research Focused, CERT-In impaneled Cybersecurity Consulting company specializing in security assessments of IoT product ecosystem, Web application & Network with a proven track record of securing applications and infrastructure for customers across 20+ countries.

Get in touch with us. Click on the get started button below.

Subscribe to our Newsletter
Subscription Form
DOWNLOAD THE EBOOK

Fill in your details and get your copy of the ebook in few seconds

Ebook Download
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download ICS Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Cloud Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download IoT Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Code Review Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Red Team Assessment Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download AI/ML Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download DevSecOps Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Product Security Assessment Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download AI/ML Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download IoT Sample Report

Let’s make cyberspace secure together!

Requirements

Connect Now Form

What our clients are saying!

Trusted by