Frida on non-rooted Android devices

Title

Frida is a dynamic instrumentation toolkit for developers, reverse-engineers, and security researchers.

Frida allows:

  • Injection of your own scripts into black box processes.
  • Hook any function.
  • Spy on crypto APIs or trace private application code.
  • Disable SSL Pinning and root checkers.

Frida is one of the best tools to use during an application penetration testing.


Why install Frida in a non-rooted Android device?

The most frequent installation of Frida is described here and consists in running a Frida server in the rooted device as a process:

$ adb root # might be required
$ adb push frida-server /data/local/tmp/ 
$ adb shell "chmod 755 /data/local/tmp/frida-server"
$ adb shell "/data/local/tmp/frida-server &"

Then a conection with the Frida client is done and the instrumentation begins.

frida-ps -U

  PID NAME
 1590 com.facebook.katana
13194 com.facebook.katana:providers
12326 com.facebook.orca
13282 com.twitter.android

The injection is done with ptrace by attaching or spawning a process and then injecting the agent. Once the agent is injected, it communicates with its server through a pipe. ptrace can’t be used as a normal user. To address this constraint, Frida provides another mode of operation called embedded. In this mode the user is responsible to inject the frida-gadget library.

Moreover, there are some situations that is not possible to have a rooted phone but still you need to use Frida.

I suggest two methods to inject the Frida Gadget:

  1. Using LIEF to inject Frida Gadget in the libraries of the APK
  2. Using Objection and modifying the Dalvik bytecode

Using LIEF to inject Frida Gadget in the libraries of the APK

Executable formats include libraries that are linked with executable. In the loading phase of the executable, the loader iterates over these libraries and map them in the memory space of the process. Once mapped it calls its constructor. The idea is to add frida-agent.so as a dependency of native libraries embedded in the APK.

Based of the awesome job of Romain Thomas @rh0main, I have write a small script to automate the ELF gadget injection with LIEF. It can be downloaded here:

The script does the following:

  • 1 Unzips the APK passed as input.
  • 2 Asks for the architecture of the Android device. There are two options: The architecture is known, then the gadget is injected only for that architecture. The architecture is unknow, then the gadget is injected in all architectures.
  • 3 Asks for the library to be injected, then downloads the last gadget from Frida repository and injects it.
  • 4 Removes the old signature.
  • 5 Generates the APK with the name my_app.apk

Requirements

Python 3.6 

pip install https://github.com/lief-project/packages/raw/lief-master-latest/pylief-0.9.0.dev.zip
pip install xtract

Usage

python frida_lief_injection.py



[+] Enter the path of your APK: original.apk
[+] Unzip the original.apk in /tmp/tmpknzr8dx4_lief_frida
[+] Select the architecture of your system: 
If you don't know run: adb shell getprop ro.product.cpu.abi

1) armeabi
2) arm64-v8a
3) x86
4) armeabi-v7a
5) x86_64
6) I don't know. Inject frida-gadget for all architectures (slower)

> 4

[+] In with library do you want to inject?: 
 
1) libshinobicharts-android.so
2) libmodpng.so
3) libpl_droidsonroids_gif.so
4) libmodft2.so
5) libjniPdfium.so
6) libmodpdfium.so

[+] Enter the number of the desired library: 
> 1
[+] Downloading and extracting frida gadget for: armeabi-v7a
[+] Injecting libgdgt.so into armeabi-v7a/libshinobicharts-android.so

[*] Removing old signature
[+] APK Building...
[+] SUCCESS!! Your new apk is : my_app.apk. Now you should sign it.

Signing the APK

Generation of the keystore:

keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000

Signing:

jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore my_app.apk alias_name

Frida Injection

The first error is because Frida needs to be executed when the app is opened and the library loaded. If we inject in a library that is used under some circumstances, those circumstances must be followed to activate the Frida gadget.

If the APK is decompiled or the temporary directory that the script generates is analyzed, the ELF injection could be observer with readelf:

root@kali:/tmp/tmp9fqng8xe_lief_frida/lib/armeabi-v7a# ls
libgdgt.so  libtmessages.30.so
root@kali:/tmp/tmp9fqng8xe_lief_frida/lib/armeabi-v7a# readelf -d libtmessages.30.so | grep NEEDED
 0x00000001 (NEEDED)                     Shared library: [libgdgt.so]
 0x00000001 (NEEDED)                     Shared library: [libjnigraphics.so]
 0x00000001 (NEEDED)                     Shared library: [liblog.so]
 0x00000001 (NEEDED)                     Shared library: [libz.so]
 0x00000001 (NEEDED)                     Shared library: [libEGL.so]
 0x00000001 (NEEDED)                     Shared library: [libGLESv2.so]
 0x00000001 (NEEDED)                     Shared library: [libandroid.so]
 0x00000001 (NEEDED)                     Shared library: [libOpenSLES.so]
 0x00000001 (NEEDED)                     Shared library: [libdl.so]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so]
 0x00000001 (NEEDED)                     Shared library: [libm.so]
 0x00000001 (NEEDED)                     Shared library: [libc.so]
root@kali:/tmp/tmp9fqng8xe_lief_frida/lib/armeabi-v7a# 

Reading depedencies of libtmessages.30.so, libgdgt.so is the first loaded and corresponds to the Frida Gadget.


Using Objection and modifying the Dalvik bytecode

Objection is a runtime mobile exploration toolkit, powered by Frida. It was built with the aim of helping assess mobile applications and their security posture without the need for a jailbroken or rooted mobile device.

Objection includes a module called patchapk that does the following:

  • 1 Detects the architecure of the Android device using ADB.
  • 2 Unzips the APK passed as input.
  • 3 Check if the App has android.permission.INTERNET, if not it rewrites AndroidManifest.xml.
  • 4 Get the first activity launched from the AndroidManifest.xml.
  • 5 Injects the frida gadget in the constructor.
    const-string v0, "frida-gadget"
    invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
    
  • 6 Copies Frida gadget to libs path.
  • 7 Rebuild the APK and signs it.

After the new APK is installed, the Frida gadget is injected and Objection can start the instrumentation:


Considerations:

  • Some applications performs integrity checks and these methods will not work.

  • Both methods need android.permission.INTERNET in AndroidManifest.xml. If this is not in the manifest, add it and rebuild the APK.

  • For method 1. Using LIEF to inject Frida Gadget in the libraries of the APK, the App must use at least one library.


References: