Using Frida on Android without root”. In this tutorial we propose a new technique without modifying the Dalvik Bytecode (i.e. In the default mode, Frida needs in a first step to inject an agent in the targeted application so that it is in the memory space of the process. On Android and Linux such injection is done with Some kind of injection require privileges. For example, we can’t use Such injection could be done with: Environment variables: Using In an open-source target, use the linker to link with frida-gadget. … For more information about Frida gadget, here is the documentation: frida-gadget One less known injection technique but quite old is based on modifying the ELF format. It has been well explained by Mayhem in Phrack [1] and LIEF provides a user-friendly API [2] to do it. To summarize, executable formats include libraries that are linked with executable. We can have list of linked libraries with Here 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 [3]. The idea is to add Adding such dependencies is as simple as: To explain the process, we will inject frida gadget in the Telegram application. It’s an interesting target because: It contains only one native library so the library should be loaded early. It shows the reliability of LIEF to modify ELF files It’s a real app Regarding the environment, we will use the version As explained above, the injection is just a call to the Prior to the injection After From the documentation, Frida gadget enables to use a configuration file to parametrize the interaction: Listing: Interaction is the same as frida-server Script: Direct interaction with a JS script for which the path is specified in the configuration ScriptDirectory: Same as Script but for multiple applications and multiple scripts Listing interaction would require The Frida payload will be located in Use of configuration file must follow two requirements: File must have the same name as the gadget library name (e.g. The configuration file must be located in the same directory as the gadget library The second requirement means that after the installation on the device, the gadget library will look for the config file in the When installing an application, the Android package manager will copy files from the It starts with the prefix It ends with the suffix It’s Frida is aware of these requirements as illustrated in listing below. Hence we can simply add the suffix Finally, the With Once: The injection done in The gadget library and its configuration placed in the The application resigned We can install the repackaged APK The Frida script myscript.js Lastly, we can run the telegram application and observe the Android logs: With this tutorial we demonstrated how format instrumentation and dynamic instrumentation can be combined. Here is a quick summary of advantages/disadvantages of this technique Doesn’t require rooted device Doesn’t depend of frida-server Can be used to bypass some anti-frida Doesn’t modify Require to add files in the APK Require that the application have at least one native library Hope that the library is loaded early in the application Notes APIclasses.dex
).Frida Gadget¶
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
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.LD_PRELOAD
, DYLD_INSERT_LIBRARIES
…dlopen
Frida & LIEF¶
ldd
or readelf
(Unix) or with elf_reader.py (Linux, Windows, OSX):$ python ./elf_reader.py -d /bin/ls
== Dynamic entries ==
|Tag | Value | Info |
|NEEDED | 0x1 | libcap.so.2 |
|NEEDED | 0x80 | libc.so.6 |
/bin/ls
has two dependencies:libcap.so.2
libc.so.6
frida-agent.so
as a dependency of native libraries embedded in the APK.import lief
libnative = lief.parse("libnative.so")
libnative.add_library("libgadget.so") # Injection!
libnative.write("libnative.so")
Telegram¶
4.8.4-12207
of Telegram (February 18, 2018) on an Android 6.0.1 device with an AArch64 architecture (Samsung Galaxy S6)Injection with LIEF¶
lief.ELF.Binary.add_library()
on the libtmessages.28.so
library.libtmessages.28.so
is linked against the following libraries$ readelf -d ./libtmessages.28.so|grep NEEDED
0x0000000000000001 (NEEDED) Shared library: [libjnigraphics.so]
0x0000000000000001 (NEEDED) Shared library: [liblog.so]
0x0000000000000001 (NEEDED) Shared library: [libz.so]
0x0000000000000001 (NEEDED) Shared library: [libOpenSLES.so]
0x0000000000000001 (NEEDED) Shared library: [libEGL.so]
0x0000000000000001 (NEEDED) Shared library: [libGLESv2.so]
0x0000000000000001 (NEEDED) Shared library: [libdl.so]
0x0000000000000001 (NEEDED) Shared library: [libstdc++.so]
0x0000000000000001 (NEEDED) Shared library: [libm.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so]
telegram.add_library("libgadget.so")
we have the new dependency at the first position:$ readelf -d ./libtmessages.28.so|grep NEEDED
0x0000000000000001 (NEEDED) Shared library: [libgadget.so]
0x0000000000000001 (NEEDED) Shared library: [libjnigraphics.so]
0x0000000000000001 (NEEDED) Shared library: [liblog.so]
0x0000000000000001 (NEEDED) Shared library: [libz.so]
0x0000000000000001 (NEEDED) Shared library: [libOpenSLES.so]
0x0000000000000001 (NEEDED) Shared library: [libEGL.so]
0x0000000000000001 (NEEDED) Shared library: [libGLESv2.so]
0x0000000000000001 (NEEDED) Shared library: [libdl.so]
0x0000000000000001 (NEEDED) Shared library: [libstdc++.so]
0x0000000000000001 (NEEDED) Shared library: [libm.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so]
Configuration of Frida Gadget¶
android.permission.INTERNET
permission. We can add such permission by modifying the manifest. Instead, we will use the Script interaction which does not require permission./data/local/tmp/myscript.js
file. The gadget configuration associated with context is given below{
"interaction": {
"type": "script",
"path": "/data/local/tmp/myscript.js",
"on_change": "reload"
}
}
libgadget.so
and libgadget.conf
)/data/app/org.telegram.messenger-1/lib
directory.lib/
directory of the APK only if [4]:lib
.so
gdbserver
.so
to libgadget.conf
#if ANDROID
if (!FileUtils.test (config_path, FileTest.EXISTS)) {
var ext_index = config_path.last_index_of_char ('.');
if (ext_index != -1) {
config_path = config_path[0:ext_index] + ".config.so";
} else {
config_path = config_path + ".config.so";
}
}
#endif
lib
directory of the new Telegram .apk
has the following structure:$ tree lib
.
└── arm64-v8a
├── libgadget.config.so
├── libgadget.so
└── libtmessages.28.so
libtmessages.28.so
linked with libgadget.so
$ readelf -d ./arm64-v8a/libtmessages.28.so
0x0000000000000001 (NEEDED) Shared library: [libgadget.so]
...
Run¶
libtmessages.28.so
/lib/ABI
directorynew.apk
and push myscript.js
in /data/local/tmp
:$ adb shell install new.apk
$ adb push myscript.js /data/local/tmp
$ adb shell chmod 777 /data/local/tmp/myscript.js
myscript.js
used in this tutorial is just a call to the Android log function:'use strict';
console.log("Waiting for Java..");
Java.perform(function () {
var Log = Java.use("android.util.Log");
Log.v("frida-lief", "Have fun!");
});
$ adb logcat -s "frida-lief:V"
--------- beginning of system
--------- beginning of main
03-24 17:23:51.908 10243 10243 V frida-lief: Have Fun!
Conclusion¶
AndroidManifest.xml
and DEX file(s)