For mobile app analysis, using a rooted device with Magisk and Frida has become my bread and butter. I’m aware that emulators exist (which I also use) but solutions, such as Android Studio or Genymotion fail to offer the same level of performance as a physical device.

I decided to buy a second-hand Google Pixel 3a on Amazon. I made the choice to buy a Google device because it’s pure Android, and the firmware images are readily available.

Magisk

Magisk is a suite of open source software for customizing Android devices. It provides users the ability to execute system commands on production devices and even extend features through modules.

Frida

Frida is a dynamic code instrumentation toolkit that allows you inject JavaScript code into native apps on Windows, macOS, GNU/Linux, iOS and Android. I find using Frida for bypassing Certificate Pinning works really well.

Attaching to an already running process with Frida while MagiskHide is enabled works fine. There are three ways (I am not covering patched APKs):

  • Attach by the process ID e.g. frida -U -l hook.js -p <PID>
  • Attach by the process name e.g. frida -U -l hook.js -n 'app name'
  • Attach by unique app name e.g. frida -U -l hook.js com.example.app

Having the ability to load Frida into a process early is important for bypassing anti-debugging, anti-analysis or anti-root techniques. Most bankings apps typically force the app to crash or exit when they detect a rooted device.

Problem

MagiskHide and Spawning

Magisk provides a feature called MagiskHide, which hides certain root artifacts from detection methods used by apps. However, when it’s enabled it is not possible to spawn or launch a process using Frida (with the -f option).

e.g. frida -U -l hook.js -f com.example.app --no-pause

The output will show an error:

Failed to spawn: unable to access zygote while preparing for app launch; try disabling Magisk Hide in case it is active

Reason

The short answer is both Frida and Magisk require Zygote module to spawn processes. A better explaination by a user on Stackoverflow:

For people wondering why this is needed, Magisk Hide ptraces the zygote module in order to intercept calls, which locks out other apps from doing so, and zygote is needed by Frida to spawn apps and do early hooking. – gmlime

Solution

Disable MagiskHide

The obvious one is to temporarily disable MagiskHide. You can quickly disable it through the command-line using adb. Run adb shell -c magiskhide disable (note: using -c because adb shell root does not work on production builds).

Run a Script

Another way is to create a script to automatically start an app using built-in Android utilities, then quickly attach to that process with Frida. This method is not fool proof but does provide decent results. You can use utilities like adb shell am start or adb shell monkey to spawn a process.

I personally like to use the latter because you don’t need to specify an Activity Name, only the app itself. Below is a simple script I wrote which spawns an app using monkey, gets the PID of the process, and then finally attaches to it using the local Frida client:

#!/bin/bash

run_proc=$(adb shell monkey -p $1 1)
get_pid=$(adb shell ps | grep -i $1 | awk '{printf $2}')

if [[ -z "$get_pid" ]];
then
    echo "Didn't find PID :("
else
    echo "Attaching to process.."
    frida -U -l $2 -p $get_pid
fi

Here is an example of the script launching Adidas’s Confirmed app:

alt text

To use this script you need the following:

  • A Frida-server running on the mobile device
  • A Frida client on your local machine
  • A device connected via USB
  • A hook.js file to load

Resources

There were a few users on Github also experiencing the same issue here and here. Somebody suggest to temporarily disable MagiskHide, spawn an app using Frida and re-enable it again. However, this didn’t work for me and caused my device to crash and reboot.