Frida

Frida

Frida is the dynamic instrumentation toolkit I use on almost every mobile engagement. This is a working reference for installation, attaching to processes, writing hooks, and the patterns I reach for most.

Apr 22, 2026
Updated Apr 8, 2026
2 min read

What Frida Is

Frida injects a JavaScript engine into a target process and gives you a bridge to call into the target's runtime. You can read and write memory, hook functions, replace return values, dump arguments, and trace anything that runs.

It works on Android, iOS, Linux, macOS, Windows, and QNX. On mobile, it is the single most useful tool I own.

Installation

# Host side
pip install frida-tools

# Verify
frida --version

For Android, push the matching frida-server binary to the device:

# Find the right version for your frida-tools install
frida --version
# Download from https://github.com/frida/frida/releases

# Push and run
adb push frida-server-16.x.x-android-arm64 /data/local/tmp/frida-server
adb shell "chmod 755 /data/local/tmp/frida-server"
adb shell "su -c /data/local/tmp/frida-server &"

For iOS, install Frida from the frida.re repo in Sileo or Cydia. It runs as a launch daemon automatically.

Attaching to a Process

# List running processes on the connected device
frida-ps -U

# List installed apps (USB-connected)
frida-ps -Uai

# Attach to a running process by name
frida -U -n com.target.app

# Spawn and attach (best for catching early init)
frida -U -f com.target.app --no-pause

The -U flag means USB. Use -R for remote (Frida over network) or omit for local processes.

The Basics of a Hook

Frida scripts are JavaScript. The Java bridge gives you access to Android classes, the ObjC bridge gives you Objective-C classes on iOS, and Interceptor works on raw native functions.

Android, hook a Java method

Java.perform(function () {
  var Activity = Java.use('com.target.app.MainActivity');

  Activity.checkLicense.implementation = function () {
    console.log('[+] checkLicense called, returning true');
    return true;
  };
});

Run with:

frida -U -f com.target.app -l hook.js --no-pause

iOS, hook an Objective-C method

if (ObjC.available) {
  var LoginVC = ObjC.classes.LoginViewController;
  Interceptor.attach(LoginVC['- isJailbroken'].implementation, {
    onLeave: function (retval) {
      console.log('[+] isJailbroken called, forcing false');
      retval.replace(0);
    }
  });
}

Native function hook (works anywhere)

Interceptor.attach(Module.getExportByName('libc.so', 'open'), {
  onEnter: function (args) {
    this.path = args[0].readUtf8String();
  },
  onLeave: function (retval) {
    console.log('[open] ' + this.path + ' = ' + retval);
  }
});

Patterns I Use Constantly

Dump all method calls on a class

Java.perform(function () {
  var TargetClass = Java.use('com.target.app.crypto.CryptoHelper');
  var methods = TargetClass.class.getDeclaredMethods();

  methods.forEach(function (m) {
    var name = m.getName();
    try {
      TargetClass[name].overloads.forEach(function (overload) {
        overload.implementation = function () {
          console.log('[->] ' + name + '(' + JSON.stringify(arguments) + ')');
          var ret = overload.apply(this, arguments);
          console.log('[<-] ' + name + ' returned ' + ret);
          return ret;
        };
      });
    } catch (e) {}
  });
});

Dump strings going through a function

Java.perform(function () {
  var String = Java.use('java.lang.String');
  String.$init.overload('[B').implementation = function (bytes) {
    var s = this.$init(bytes);
    console.log('[String] ' + s);
    return s;
  };
});

Bypass a root check by name

Java.perform(function () {
  var RootBeer = Java.use('com.scottyab.rootbeer.RootBeer');
  RootBeer.isRooted.implementation = function () {
    return false;
  };
});

Find the right class when you do not know its name

Java.perform(function () {
  Java.enumerateLoadedClasses({
    onMatch: function (name) {
      if (name.toLowerCase().includes('login')) {
        console.log(name);
      }
    },
    onComplete: function () {}
  });
});

Useful CLI Tools

CommandWhat it does
frida-ps -UaiList installed apps on USB device
frida-trace -U -i "open*" com.target.appAuto-generate trace handlers for matching functions
frida-trace -U -j "com.target.app.crypto.*!*" com.target.appTrace all Java methods in a package
frida-ls-devicesShow connected devices
frida-kill -U <pid>Kill a process
frida-discover -U -n com.target.appFind functions worth tracing

Writing Reusable Scripts

For anything beyond a one-off, I use the frida-compile workflow with TypeScript. It gives you proper modules, types, and IDE support.

npm install -g frida-compile
frida-compile agent/index.ts -o dist/agent.js -w

Then load the compiled script:

frida -U -f com.target.app -l dist/agent.js --no-pause

When Frida Is Overkill

Sometimes Objection is enough, it ships pre-built scripts for the common cases (root bypass, SSL pinning, IPC enumeration). I reach for raw Frida when the target has custom protections or I need to hook something Objection does not cover.

Last updated on