Reprogram running software, from the app down to the kernel.

Frida is a dynamic instrumentation toolkit. It puts your code inside live processes and operating system kernels, where you can hook any function, trace private code, and change behavior while the target keeps running. No source code, no rebuild, no restart.

Get started Read the docs

User mode
Windows, macOS, GNU/Linux, iOS, watchOS, tvOS, Android, FreeBSD, QNX, and PlayStation 5.
Kernel mode
Windows NT from XP through 11, Windows 9x/ME, XNU, and Linux, in virtual machines or on physical hardware.
Bare metal
Microcontrollers and custom kernels, over a debug stub.

Four ways in.

Pick the vantage point the target allows. Everything above it, from the scripting API to frida-trace and Luma, stays the same.

Injected

frida-core

Attach to a running process, or spawn one with your hooks in place before its first instruction. frida-core does the injecting, from inside your own tool on the machine you are on. On a remote device it runs headless as frida-server, and frida-portal fronts a whole fleet the same way. How injection works.

As a library

frida-gadget

No root or jailbreak? Frida injects Gadget into a debuggable iOS or Android app for you. Elsewhere, preload it, load it from your own test runner, or repackage an app with it when you want custom tweaks baked in. It waits for you to connect, or runs scripts on its own. About Gadget.

In the kernel

frida-barebone-agent

Load the Barebone agent into the operating system kernel, as a driver or through a debugger. Instrument the kernel itself and every process above it, from one session, with nothing left for the process to detect. Meet Barebone.

On bare metal

GDB remote stub

A microcontroller, a bootloader, or a kernel with no room for an agent: point Barebone at its GDB remote stub and your script runs on the host instead. Memory reads become stub reads, and Interceptor callbacks become breakpoints. Hand it a NativePointer and it places an inline hook in the target's memory, usually code you built with RustModule.

Get up and running in seconds.

One pip install gives you frida-trace, the REPL, frida-ps and friends. Here frida-trace spawns curl, hooks SSL_write, and a two-line edit to the generated handler shows each request before it is encrypted.

Frida 17.25.2 on Linux x86_64. A few status lines are trimmed; nothing else is edited.

Quick-start guide

Terminal

~ $ pip install frida-tools
~ $ frida-trace -f /usr/bin/curl -i SSL_write -- --http1.1 -s -o /dev/null https://frida.re
Instrumenting...
SSL_write: Auto-generated handler at "…/__handlers__/libssl.so.3/SSL_write.js"
Started tracing 1 function. Web UI available at http://localhost:38595/
           /* TID 0xb43a5 */
   126 ms  SSL_write(ssl=0x55d7c85d5220, buf=0x55d7c85de900, num=0x48)
Process terminated
# Edit SSL_write.js so onEnter logs the plaintext instead:
#   const n = args[2].toInt32();
#   log(JSON.stringify(args[1].readUtf8String(n)));
~ $ frida-trace -f /usr/bin/curl -i SSL_write -- --http1.1 -s -o /dev/null https://frida.re
SSL_write: Loaded handler at "…/__handlers__/libssl.so.3/SSL_write.js"
Started tracing 1 function. Web UI available at http://localhost:41553/
           /* TID 0xb4408 */
    39 ms  "GET / HTTP/1.1\r\nHost: frida.re\r\nUser-Agent: curl/8.23.0\r\nAccept: */*\r\n\r\n"
Process terminated

Down to the kernel.

Barebone is Frida's bare-metal backend. Its agent is written in Rust around the same GumJS engine that runs inside user processes, so the API you already know now works against a kernel. Where there is no kernel to host it, the same API works over a debug stub alone.

Getting it in

Through a GDB remote stub
QEMU, VirtualBox, Parallels, and the Android emulator all expose one. So does a hardware debugger, which puts a physical device's kernel in reach over JTAG or SWD.
As a driver
On Linux and Android, insmod frida-agent.ko. On macOS, load the agent as a kernel extension. Then ask frida-core for the barebone device, from the CLI or the API: add_barebone_device() on the DeviceManager takes options, and FRIDA_BAREBONE_CONFIG points the default device at a JSON config. Only tools on another machine need a frida-server --device=barebone in between.
Or with no kernel at all
Point Barebone at the target's GDB remote stub and your script runs on the host. readU32() becomes a stub read, Interceptor with JavaScript callbacks becomes a software or hardware breakpoint, and Interceptor with a NativePointer becomes an inline hook in the target's memory, typically code built with RustModule, the Barebone runtime's counterpart to CModule.

What you get

Kernel and user mode, together
Enumerate processes, attach, spawn with instrumentation in place, hook functions, query the kernel's BTF types, and watch kernel modules come and go. From the kernel, the agent injects into user processes itself.
Invisible from inside the process
The kernel half cloaks the user-mode agent's threads and memory mappings. Runtime application self-protection looking from inside the process finds nothing to see.
Light on memory
User-mode agents map the same physical pages the kernel agent already uses. Each instrumented process allocates only its own writable portion.
From the command line

The same tools, pointed at a kernel instead of a process.

# Kernel running under QEMU with its GDB stub on? That is the default: 127.0.0.1:3333.
~ $ frida-ps -D barebone
# Loaded frida-agent.ko or the kext instead? Point the default device at it.
~ $ FRIDA_BAREBONE_CONFIG=barebone.json frida-ps -D barebone
# Attach to the kernel, or to any process, with frida, frida-trace, or Luma.
# Scripts see kernel modules, kallsyms, and BTF types alongside the usual Gum APIs.
# Tools on another machine? Run frida-server --device=barebone there and connect as usual.

Agents shipped with every release: frida-barebone-agent-{linux-arm64, linux-arm, linux-x86_64, linux-x86, xnu-arm64, xnu-kext-arm64e, winnt-x86_64, winnt-x86, winnt-arm64, win9x-x86}. The kext is the loadable kernel extension for macOS. The Linux kernel module is built against your exact kernel from the GumJS devkit, so it is not a prebuilt download.

JavaScript first, not JavaScript only.

Most people start with a few lines of JavaScript because the edit, save, see loop takes seconds. The rest of the stack speaks whatever you do, on the host and inside the target.

Interceptor.attach(Module.getGlobalExportByName('recvfrom'), {
  onEnter(args) {
    this.fd = args[0].toInt32();
  },
  onLeave(retval) {
    console.log(`recvfrom(fd=${this.fd}) => ${retval.toInt32()}`);
  }
});

The agent side

This runs inside the target, in a process or in a kernel, on QuickJS or V8. Write it in TypeScript if you like, with autocompletion from the bundled type definitions. Hot paths can drop into C with CModule.

JavaScript API reference

Debug the build you already shipped.

Logging has blind spots, and you find them in the field. Instead of redeploying a special build just to see more, build a tool on Frida that attaches to the software your customers are already running.

Prefer a GUI?

Luma is the official Frida app: a native workspace with persistent sessions, a live REPL, frida-trace with a built-in handler editor, and real-time collaboration.

Explore Luma →

Luma's Tracer: a handler for open() in the built-in editor, the hook list beside it, and the event stream of traced calls from Telegram below

Free

Frida is and will always be free software (free as in freedom). We want to empower the next generation of developer tools, and help other free software developers achieve interoperability through reverse engineering.

Battle-tested

NowSecure uses Frida to do fast, deep analysis of mobile apps at scale, and a comprehensive test suite runs on every change.

Scales down

Build only what you need. The same core fits embedded systems, with a footprint you control feature by feature.

In the open

Over a decade of releases, with detailed notes for every one, and a community that ships fixes upstream.