Frida 10.0 Released

This time we’re kicking it up a notch. We’re bringing you stability improvements and state of the art JavaScript support.

Let’s talk about the stability improvements first. We fixed a heap corruption affecting all Linux users. This one was particularly hard to track down, but rr saved the day. The other issue was a crash on unload in the Duktape runtime, affecting all OSes.

Dependencies were also upgraded, so as of Frida 10.0.0 you can now enjoy V8 6.0.124, released just days ago. We also upgraded Duktape to the latest 2.1.x. The Duktape upgrade resulted in slight changes to the bytecode semantics, which meant we had to break our API slightly. Instead of specifying a script’s name at load time, it is now specified when compiling it to bytecode, as this metadata is now included in the bytecode. This makes a lot more sense, so it was a welcome change.

Beside V8 and Duktape we’re also using the latest GLib, Vala compiler, etc. These upgrades also included JSON-GLib, which recently ditched autotools in favor of Meson. This is excellent news, as we’re also planning on moving to Meson down the road, so we’ve now done the necessary groundwork for making this happen.

So that’s about it. This upgrade should not require any changes to existing code – unless of course you are among the few using the bytecode API.

Enjoy!

Frida 9.0 Released

Some big changes this time. We now use our Duktape-based JavaScript runtime by default on all platforms, iOS app launching no longer piggybacks on Cydia Substrate, and we are bringing some massive performance improvements. That, and some bugfixes.

Let’s talk about Duktape first. Frida’s first JS runtime was based on V8, and I’m really happy about that choice. It is however quite obvious that there are use-cases where it is a bad fit.

Some systems, e.g. iOS, don’t allow RWX memory1, and V8 won’t run without that. Another example is resource-constrained embedded systems where there just isn’t enough memory. And, as reported by users from time to time, some processes decide to configure their threads to have tiny stacks. V8 is however quite stack-hungry, so if you hook a function called by any of those threads, it won’t necessarily be able to enter V8, and your hooks appear to be ignored2.

Another aspect is that V8 is way more expensive than Duktape for the native ⇔ JS transitions, so if your Frida agent is all about API hooks, and your hooks are really small, you might actually be better off with Duktape. Garbage collection is also more predictable with Duktape, which is good for hooking time-sensitive code.

That said, if your agent is heavy on JavaScript, V8 will be way faster. It also comes with native ES6 support, although this isn’t too big a deal since non-trivial agents should be using frida-compile, which compiles your code to ES5.

So the V8 runtime is not going away, and it will remain a first-class citizen. The only thing that’s changing is that we pick Duktape by default, so that you are guaranteed to get the same runtime on all platforms, with a high probability that it’s going to work.

However, if your use-case is JS-heavy, all you have to do is call Session#enable_jit() before the first script is created, and V8 will be used. For our CLI tools you may pass –enable-jit to get the same effect.

That was Duktape. What’s the story about app launching and Substrate, then? Well, up until now our iOS app launching was piggybacking on Substrate. This was a pragmatic solution in order to avoid going into interoperability scenarios where Frida and Substrate would both hook posix_spawn() in launchd and xpcproxy, and step on each other.

It was however on my long-term TODO to fix this, as it added a lot of complexity in other areas. E.g. an out-of-band callback mechanism so our Substrate plugin could talk back to us at load time, having to manage temporary files, etc. In addition to that, it meant we were depending on a closed source third-party component, even though it was a soft-dependency only needed for iOS app launching. But still, it was the only part of Frida that indirectly required permanent modifications to the running system, and we really want to avoid that.

Let’s have a look at how the new app launching works. Imagine that you ran this on your host machine that’s got a jailbroken iOS device connected to it over USB:

$ frida-trace -U -f com.atebits.Tweetie2 -i open

We’re telling it to launch Twitter’s iOS app and trace functions named open. As a side-note, if you’re curious about the details, frida-trace is written in Python and is less than 900 lines of code, so it might be a good way to learn more about building your own tools on top of Frida. Or perhaps you’d like to improve frida-trace? Even better!

The first part that it does is that it gets hold of the first USB device and launches the Twitter app there. This boils down to:

import frida

device = frida.get_usb_device()
pid = device.spawn(["com.atebits.Tweetie2"])

What now happens behind the scenes is this:

  1. We inject our launchd.js agent into launchd (if not done already).
  2. Call the agent’s RPC-exported prepareForLaunch() giving it the identifier of the app we’re about to launch.
  3. Call SBSLaunchApplicationWithIdentifierAndLaunchOptions() so SpringBoard launches the app.
  4. Our launchd.js agent then intercept launchd’s __posix_spawn() and adds POSIX_SPAWN_START_SUSPENDED, and signals back the identifier and PID. This is the /usr/libexec/xpcproxy helper that will perform an exec()-style transition to become the app.
  5. We then inject our xpcproxy.js agent into this so it can hook __posix_spawn() and add POSIX_SPAWN_START_SUSPENDED just like our launchd agent did. This one will however also have POSIX_SPAWN_SETEXEC, so that means it will replace itself with the app to be launched.
  6. We resume() the xpcproxy process and wait for the exec to happen and the process to be suspended.

At this point we let the device.spawn() return with the PID of the app that was just launched. The app’s process has been created, and the main thread is suspended at dyld’s entrypoint. frida-trace will then want to attach to it so it can load its agent that hooks open. So it goes ahead and does something similar to this:

session = device.attach(pid)
script = session.create_script("""
Interceptor.attach(Module.findExportByName(null, 'open'), {
  onEnter: function () {
    console.log('open()');
  }
});
""")
script.load()

Now that it has applied the instrumentation, it will ask Frida to resume the process so the main thread can call main() and have some fun:

device.resume(pid)

Note that I did skip over a few details here, as the attach() operation is actually a bit more complicated due to how uninitialized the process is, but you can read more about that here.

Finally, let’s talk about footprint and performance. First, let’s examine how much disk space is required when Frida is installed on an iOS device and is in a fully operational state:

That’s the 64-bit version, which is only 1.87 MB xz-compressed. The 32-bit version is obviously even smaller. Quite a few optimizations at play here:

  • We used to write the frida-helper binary out to a temporary file and spawn it. The meat of the frida-helper program is now statically linked into frida-server, and its entitlements have been boosted along with it. This binary is only necessary when Frida is used as a plugin in an unknown process, i.e. where we cannot make any guarantees about entitlements and code-signing. In the frida-server case, however, it is able to guarantee that all such constraints are met.
  • The library that we inject into processes to be instrumented, frida-agent.dylib, is no longer written out to a temporary file. We use our own out-of-process dynamic linker to map it from frida-server’s memory and directly into the address space of the target process. These mappings are made copy-on-write, so that means it is as memory-efficient as the old dlopen() approach was.
  • V8 was disabled for the iOS binaries as it’s only really usable on old jailbreaks where the kernel is patched to allow RWX pages. (If V8 is important to your use-case, you can build it like this: make server-ios FRIDA_DIET=no)
  • The iOS package has been split into two, “Frida” for 64-bit devices, and “Frida for 32-bit devices” for old devices.
  • Getting rid of the Substrate dependency for iOS app launching also meant we got rid of FridaLoader.dylib. This is however a very minor improvement.

Alright, so that’s disk footprint. How about memory usage?

Nice. How about performance? Let’s have a look:

Note that these measurements include the time spent communicating from the macOS host to the iOS device over USB.

Enjoy!

1 Except if the process has an entitlement, although that’s limited to just one region.

2: It is technically possible to work around this by having a per-thread side-stack that we switch to before calling into V8. We did actually have this partially implemented in the past. Might be something we should revive in the longer term.

Frida 8.1 Released

It’s time for a release, and this time we have some big new things for those of you building Frida-based tools, plus a few additional goodies. Let’s start with the first part.

There’s no doubt that Frida’s JavaScript API is fairly low-level and only meant to provide low-level building blocks that don’t pertain to just one specific use-case. If your use-case involves grabbing screenshots on iOS, for example, this is not functionality one would expect to find in Frida itself.

You may then wonder how different tools with common features are supposed to share agent code with each other, and luckily the answer is not “copy paste”. We have a growing ecosystem of Frida-specific libraries, like frida-screenshot, frida-uikit, frida-trace, etc.

Perhaps some of you would be interested in APIs for instrumenting backend software written in Java, .NET, Python, Ruby, or Perl, or perhaps you would want to trace crypto APIs across different OSes and libraries, or some other cool idea. I would then highly recommend that you publish your module to npm, perhaps naming your module frida-$name to make it easy to discover.

Now you might be asking “but Frida does not support require(), how can I even split my agent code into multiple files in the first place?”. I’m glad you asked! This is where a handy little CLI tool called frida-compile enters the picture.

You give it a .js file as input and it will take care of bundling up any other files it depends on into just one file. But unlike a homegrown concatenation solution using cat, the final result also gets an embedded source map, which means filenames and line numbers in stack traces are meaningful. Modules are also separated into separate closures so variables are contained and never collide. You can also use the latest JavaScript syntax, like arrow functions, destructuring, and generator functions, as it compiles the code down to ES5 syntax for you. This means that your code also runs on our Duktape-based runtime, which you are forced to use if you use Frida on a jailed iOS device, or on a jailbroken iOS device running iOS >= 9.

In order to give you a short feedback loop while developing, frida-compile also provides a watch mode through -w, so you get instant incremental builds as you develop your agent.

Anyway, enough theory. Let’s look at how we can use an off-the-shelf web application framework from npm, and inject that into any process.

First, make sure you have the latest version of Node.js installed. Next, create an empty directory and paste this into a file named “package.json”:

{
  "name": "hello-frida",
  "version": "1.0.0",
  "scripts": {
    "prepublish": "npm run build",
    "build": "frida-compile agent -o _agent.js",
    "watch": "frida-compile agent -o _agent.js -w"
  },
  "devDependencies": {
    "express": "^4.14.0",
    "frida-compile": "^2.0.6"
  }
}

Then in agent.js, paste the following code:

'use strict';

const express = require('express');

const app = express();

app
  .get('/ranges', (req, res) => {
    res.json(Process.enumerateRangesSync({
      protection: '---',
      coalesce: true
    }));
  })
  .get('/modules', (req, res) => {
    res.json(Process.enumerateModulesSync());
  })
  .get('/modules/:name', (req, res) => {
    try {
      res.json(Process.getModuleByName(req.params.name));
    } catch (e) {
      res.status(404).send(e.message);
    }
  })
  .get('/modules/:name/exports', (req, res) => {
    res.json(Module.enumerateExportsSync(req.params.name));
  })
  .get('/modules/:name/imports', (req, res) => {
    res.json(Module.enumerateImportsSync(req.params.name));
  })
  .get('/objc/classes', (req, res) => {
    if (ObjC.available) {
      res.json(Object.keys(ObjC.classes));
    } else {
      res.status(404).send('Objective-C runtime not available in this process');
    }
  })
  .get('/threads', (req, res) => {
    res.json(Process.enumerateThreadsSync());
  });

app.listen(1337);

Install frida-compile and build your agent in one step:

$ npm install

Then load the generated _agent.js into a running process:

$ frida Spotify -l _agent.js

You can now hit it with HTTP requests:

$ curl http://127.0.0.1:1337/ranges
$ curl http://127.0.0.1:1337/modules
$ curl http://127.0.0.1:1337/modules/libSystem.B.dylib
$ curl http://127.0.0.1:1337/modules/libSystem.B.dylib/exports
$ curl http://127.0.0.1:1337/modules/libSystem.B.dylib/imports
$ curl http://127.0.0.1:1337/objc/classes
$ curl http://127.0.0.1:1337/threads

Sweet. We just built a process inspection REST API with 7 different endpoints in fewer than 50 lines of code. What’s pretty cool about this is that we used an off-the-shelf web application framework written for Node.js. You can actually use any existing modules that rely on Node.js’ built-in net and http modules. Like an FTP server, IRC client, or NSQ client.

So up until this release you could use Frida-specific modules like those mentioned earlier. You could also use thousands of other modules from npm, as most of them don’t do any I/O. Now with this release you also get access to all net and http based modules, which opens up Frida for even more cool use-cases.

In case you are curious how this was implemented, I added Socket.listen() and Socket.connect() to Frida. These are minimal wrappers on top of GIO’s SocketListener and SocketClient, which are already part of Frida’s technology stack and used by Frida for its own needs. So that means our footprint stays the same with no dependencies added. Because frida-compile uses browserify behind the scenes, all we had to do was plug in our own builtins for net and http. I simply ported the original net and http modules from Node.js itself.

This release also brings some other goodies. One long-standing limitation with NativeFunction is that calling a system API that requires you to read errno (UNIX) or call GetLastError() (Windows) would be tricky to deal with. The challenge is that Frida’s own code might clobber the current thread’s error state between your NativeFunction call and when you try to read out the error state.

Enter SystemFunction. It is exactly like NativeFunction, except that the call returns an object wrapping the returned value and the error state right afterwards. Here’s an example:

const open = new SystemFunction(
    Module.findExportByName(null, 'open'),
    'int',
    ['pointer', 'int']);
const O_RDONLY = 0;

const path = Memory.allocUtf8String('/inexistent');
const result = open(path, O_RDONLY);
console.log(JSON.stringify(result, null, 2));
/*
 * Which on Darwin typically results in the following output:
 *
 * {
 *   "value": -1,
 *   "errno": 2
 * }
 *
 * Where 2 is ENOENT.
 */

This release also lets you read and modify this system error value from your NativeCallback passed to Interceptor.replace(), which might come handy if you are replacing system APIs. Note that you could already do this with Interceptor.attach(), but that’s not an option in cases where you don’t want the original function to get called.

Another big change worth mentioning is that our V8 runtime has been heavily refactored. The code is now easier to understand and it is way less work to add new features. Not just that, but our argument parsing is also handled by a single code-path. This means that all of our APIs are much more resilient to bad or missing arguments, so you get a JavaScript exception instead of having some APIs do fewer checks and happily crash the target process in case you forgot an argument.

Anyway, those are the highlights. Here’s a full summary of the changes:

8.1.0:

  • core: add Socket.listen() and Socket.connect()
  • core: add setImmediate() and clearImmediate()
  • core: improve set{Timeout,Interval}() to support passing arguments
  • core: fix performance-related bug in Interceptor’s dirty state logic

8.1.1:

  • core: add Script.nextTick()

8.1.2:

  • core: teach Socket.listen() and Socket.connect() about UNIX sockets
  • core: fix handling of this.errno / this.lastError replacement functions
  • core: add SystemFunction API to get errno / lastError on return
  • core: fix crash on close() during I/O with the Stream APIs
  • core: fix and consolidate argument handling in the V8 runtime

8.1.3:

  • core: temporarily disable Mapper on macOS in order to confirm whether this was the root cause of reported stability issues
  • core: add .call() and .apply() to NativeFunction
  • objc: fix parsing of opaque struct types

8.1.4:

  • core: fix crash in the V8 runtime caused by invalid use of v8::Eternal
  • frida-repl: add batch mode support through -e and -q

8.1.5:

  • node: generate prebuilds for 6.0 (LTS) and 7.0 only

8.1.6:

  • node: generate prebuilds for 4.0 and 5.0 in addition to 6.0 and 7.0

8.1.7:

  • objc: fix infinite recursion when proxying some proxies
  • objc: add support for proxying non-NSObject instances
  • python: fix removal of signal callbacks that are member functions

8.1.8:

  • core: implement hooking of single-instruction ARM functions
  • core: plug leak in the handling of unhookable functions on some architectures
  • core: fix setImmediate() callback processing behavior
  • core: plug leak in setTimeout()
  • core: fix race condition in the handling of setTimeout(0) and setImmediate() in the Duktape runtime
  • core: fix crash when processing tick callbacks in the Duktape runtime
  • core: fix lifetime issue in the Duktape runtime
  • core: fix the reported module sizes on Linux
  • core: fix crash when launching apps on newer versions of Android
  • core: fix handling of attempts to launch Android apps not installed
  • core: improve compatibility with different versions and flavors of Android by detecting Dalvik and ART field offsets dynamically
  • core: fix unload issue on newer versions of Android, which resulted in only the first attach() succeeding and subsequent attempts all timing out
  • core: move ObjC and Java into their own modules published to npm, and use frida-compile to keep baking them into Frida’s built-in JS runtime
  • java: improve ART compatibility by detecting ArtMethod field offsets dynamically
  • node: update dependencies
  • node: fix unhandled Promise rejection issues

8.1.9:

  • core: fix use-after-free caused by race condition on script unload

8.1.10:

  • core: make ApiResolver and DebugSymbol APIs preemptible to avoid deadlocks

8.1.11:

  • core: use a Mach exception handler on macOS and iOS, allowing us to reliably catch exceptions in apps that already have a Mach exception handler of their own
  • core: fix leak in InvocationContext copy-on-write logic in the Duktape runtime, used when storing data on this across onEnter and onLeave

8.1.12:

  • core: fix Interceptor argument replacement issue in the V8 runtime, resulting in the argument only being replaced the first time

Enjoy!

Frida 8.0 Released

It is time to level up to the next major version.

First off is the long-standing issue where multiple Frida clients attached to the same process were forced to coordinate so none of them would call detach() while one of the others was still using the session.

This was probably not a big deal for most users of Frida. However, we also had the same issue if one running frida-server was shared by multiple clients. You might have frida-trace running in one terminal while using the REPL in another, both attached to the same process, and you wouldn’t then expect one of them calling detach() to result in the other one getting kicked out.

Some of you may have tried this and observed that it works as expected, but this was due to some crazy logic in frida-server that would keep track of how many clients were interested in the same process, so it could ignore a detach() call if other clients were still subscribed to the same session. It also had some logic to clean up a certain client’s resources, e.g. scripts, if it suddenly disconnected.

Starting with 8.0 we have moved the session awareness into the agent, and kept the client-facing API the same, but with one little detail changed. Each call to attach() will now get its own Session, and the injected agent is aware of it. This means you can call detach() at any time, and only the scripts created in your session will be destroyed. Also, if your session is the last one alive, Frida will unload its agent from the target process.

That was the big change of this release, but we didn’t stop there.

One important feature of Frida’s scripts is that you can exchange messages with them. A script may call send(message[, data]) to send a JSON-serializable message, and optionally a binary blob of data next to it. The latter is so you don’t have to spend CPU-cycles turning your binary data into text that you include in the message.

It is also possible to communicate in the other direction, where the script would call recv(callback) to get a callback when you post_message() to it from your application. This allowed you to post a JSON-serializable message to your script, but there was no support for sending a binary blob of data next to it.

To address this shortcoming we renamed post_message() to post(), and gave it an optional second argument allowing you to send a binary blob of data next to it.

We also improved the C API by migrating from plain C arrays to GBytes, which means we are able to minimize how many times we copy the data as it flows through our APIs.

So in closing, let’s summarize the changes:

8.0.0:

  • core: add support for multiple parallel sessions
  • core: rename Script’s post_message() to post() and add support for passing out-of-band binary data to the script
  • core: replace C arrays with GBytes to improve performance
  • core: fix heap corruption caused by use-after-free in libgee
  • core: fix multiple crashes
  • core: fix exports enumeration crash on macOS Sierra
  • core: add basic support for running on Valgrind
  • core: bump the macOS requirement to 10.9 so we can rely on libc++
  • node: update to the new 8.x API
  • python: update to the new 8.x API
  • swift: update to the new 8.x API
  • swift: upgrade to Swift 3
  • qml: update to the new 8.x API
  • clr: update to the new 8.x API
  • clr: plug leaks

8.0.1:

  • node: fix Script#post()

8.0.2:

  • core: fix deadlock when calling recv().wait() from our JS thread

8.0.3:

  • core: reduce Interceptor base overhead by up to 65%
  • core: minimize Interceptor GC churn in our V8 runtime, using the same recycling and copy-on-write tricks as our Duktape runtime
  • core: speed up gum_process_get_current_thread_id() on macOS and iOS

Enjoy!

Frida 7.3 Released

It’s finally release o’clock, and this time around the focus has been on improving quality. As it’s been a while since the last time we upgraded our third-party dependencies, and I found myself tracking down a memory-leak in GLib that had already been fixed upstream, I figured it was time to upgrade our dependencies. So with this release I’m happy to announce that we’re now packing the latest V8, GLib, Vala compiler, etc. Great care was also taken to eliminate resource leaks, so you can attach to long-running processes without worrying about memory allocations or OS handles piling up.

So in closing, let’s summarize the changes:

7.3.0:

  • core: upgrade to the latest V8, GLib, Vala, Android NDK, etc.
  • core: plug resource leaks
  • core: fix thread enumeration on Linux/x86-32
  • core: (arm64) improve function hooking by adding support for relocating LDRPC with an FP/SIMD destination register

7.3.1:

  • core: build Android binaries with PIE like we used to

7.3.2:

  • core: add Script.setGlobalAccessHandler() for handling attempts to access undeclared global variables, which is useful for building REPLs

7.3.3:

  • objc: convert Number to NSNumber when an object is expected
  • objc: add support for auto-converting to an array of objects, useful when calling e.g. +[NSArray arrayWithObjects:count:]

7.3.4:

  • core: improve the unstable accessor API
  • core: fix the Duktape globals accessor logic so it’s only applied to reads

7.3.5:

  • core: improve hexdump() to support any NativePointer-conforming object
  • objc: fix handling of the L type

7.3.6:

  • core: fix regression in devkit header auto-generation logic

Enjoy!

Frida 7.2 Released

Some of you may be aware that Frida has two JavaScript runtimes, one based on V8, and another one based on Duktape. We also used to have a runtime based on JavaScriptCore, but it got retired when our Duktape runtime proved better in all of the situations where V8 wasn’t a good fit, e.g. on tiny embedded systems and systems where RWX pages are forbidden.

Anyway, what is pretty neat is that Duktape has an API for compiling to bytecode, allowing you to cache the compiled code and save precious startup time when it’s time to instrument a new process. Starting with this release we now have brand new API for compiling your JavaScript to bytecode, and of course instantiating a script from it. This API is not yet supported in our V8 runtime, but we should be able to implement it there after our next V8 upgrade, by using the WebAssembly infrastructure that started appearing in the latest releases.

So without further ado, let’s take this new API for a spin with the Duktape runtime by forcing Frida to favor Duktape through Session.disable_jit().

From Node.js:

'use strict';

const co = require('co');
const frida = require('frida');

co(function* () {
  const systemSession = yield frida.attach(0);
  yield systemSession.disableJit();
  const bytecode = yield systemSession.compileScript(`
    'use strict';

    rpc.exports = {
      listThreads: function () {
        return Process.enumerateThreadsSync();
      }
    };
  `);

  const session = yield frida.attach('Twitter');
  yield session.disableJit();
  const script = yield session.createScriptFromBytes(bytecode);
  yield script.load();

  const api = yield script.getExports();
  console.log('api.listThreads() =>', yield api.listThreads());

  yield script.unload();
})
.catch(err => {
  console.error(err);
});

And from Python:

from __future__ import print_function
import frida

system_session = frida.attach(0)
system_session.disable_jit()
bytecode = system_session.compile_script("""
'use strict';

rpc.exports = {
  listThreads: function () {
    return Process.enumerateThreadsSync();
  }
};
""")

session = frida.attach("Twitter")
session.disable_jit()
script = session.create_script_from_bytes(bytecode)
script.load()

api = script.exports
print("api.list_threads() =>", api.list_threads())

Note that the same caveats as specified in the Duktape documentation apply here, so make sure the code you’re trying to load is well-formed and generated by the same version of Duktape. It may get upgraded when you upgrade to a future version of Frida, but will at least be architecture-neutral; i.e. you can compile to bytecode on a 64-bit x86 desktop and load it just fine in a 32-bit iOS app on ARM.

So that’s bytecode compilation through the API, but you probably want to use the frida-compile CLI tool for this instead:

$ npm install frida-compile
$ ./node_modules/.bin/frida-compile agent.js -o agent.bin -b

While developing you can also use it in watch mode by adding -w, which makes it watch the inputs and perform fast incremental builds whenever one of them changes.

Whether you’re using bytecode (-b) or not, frida-compile is highly recommended as it also comes with a number of other benefits, letting you:

  • Split your script into multiple .js files by using require().
  • Leverage thousands of existing modules from npm, including some that are Frida-specific. For example: frida-trace, frida-uikit, frida-screenshot, etc.
  • Use ES6 syntax and have your code compiled to ES5 so it’s compatible with the Duktape runtime.

So in closing, let’s summarize the changes:

7.2.0:

  • core: add support for compiling and loading to/from bytecode
  • core: include error name and stack trace in RPC error replies
  • node: add support for the new bytecode APIs
  • node: augment RPC errors with name and stack when available
  • node: port examples to ES6
  • python: add support for the new bytecode APIs
  • python: update to the revised RPC protocol

7.2.1:

  • objc: add support for resolving methods on minimal Objective-C proxies

7.2.2:

  • objc: fix handling of methods returning structs and floating point values

7.2.3:

  • objc: expose the raw handle of Objective-C methods

7.2.4:

  • core: fix deadlock that was easily reproducible on iOS 9
  • java: improve Java.perform() robustness and handling of non-app processes

7.2.5:

  • objc: fix handling of methods returning a struct in registers on x86-64

7.2.6:

  • core: port Gum to MIPS
  • core: avoid swallowing exception when a Proxy object misbehaves
  • objc: add support for accessing Objective-C instance variables

7.2.7:

  • core: port .so injector to MIPS
  • core: enhance MIPS fuzzy backtracer with more branch-and-link instructions
  • core: fix UnixInputStream and UnixOutputStream pollable behavior on TTYs, fixing hang on script unload
  • core: remove “0x” prefix from hexdump() offsets

7.2.8:

  • objc: fix parsing of type hints
  • objc: add support for including type hints
  • objc: make ObjC.Block’s types field public
  • objc: add support for properly declaring void *
  • core: (MIPS) fix stack offset when getting/setting stack arguments

7.2.9:

  • core: fix bug preventing registers from being written in the V8 runtime

7.2.10:

  • core: add support for attaching to iOS Simulator processes
  • core: fix Android class-resolving regression introduced in 7.2.4

7.2.11:

  • core: always kill iOS apps through SpringBoard

7.2.12:

  • objc: unregister Objective-C classes on unload and GC

7.2.13:

  • core: fix application kill logic on iOS 9

7.2.14:

  • core: make the Duktape runtime preemptible like the V8 runtime
  • core: fix a few locking bugs in the V8 runtime

7.2.15:

  • core: implement the Kernel API in the Duktape runtime also
  • core: remove the dangerous Kernel.enumerateThreads() API

7.2.16:

  • core: improve robustness when quickly reattaching to the same process
  • core: fix deadlock when pending calls exist at detach time
  • core: fix hooking regression on 32-bit ARM
  • core: fix dlsym() deadlock in frida-gadget on Linux
  • core: fix Windows build regression
  • core: fix iOS 7 regression

7.2.17:

  • core: fix session teardown regression

7.2.18:

  • core: fix long-standing stability issue on iOS 9, where the injected bootstrap code was not pseudo-signed and caused processes to eventually lose their CS_VALID status
  • core: speed up app launching on iOS by eliminating unnecessary disk I/O
  • core: fix temporary directory clean-up on iOS

7.2.19:

  • core: fix preemption-related lifetime-issue in the Duktape runtime

7.2.20:

  • core: rework the V8 runtime to support fully asynchronous unloading
  • core: rework the Duktape runtime to support fully asynchronous unloading
  • core: make the Duktape runtime fully reentrant
  • core: add Script.pin() and Script.unpin() for extending a script’s lifetime in critical moments, e.g. for callbacks expected from external APIs out of one’s control
  • core: fix a timer-related leak in both the V8 and the Duktape runtime
  • objc: keep script alive until callback scheduled by ObjC.schedule() has been executed
  • objc: add a dealloc event to the ObjC proxy API

7.2.21:

  • core: fix hang on detach()

7.2.22:

  • core: fix hang on script unload
  • core: fix hang on abrupt connection loss during detach()

7.2.23:

  • core: fix two low-probability crashes during script unload

7.2.24:

  • core: fix use-after-free in the Duktape runtime
  • core: fix use-after-free bugs in ModuleApiResolver
  • core: improve unload-behavior when an exception handler is set

7.2.25:

  • core: fix app launching on iOS 9.3.3
  • frida-server: fix “hang” on detach when another client is attached to the same process

Enjoy!

Frida 7.1 Released

If you’ve ever used Frida to spawn programs making use of stdio you might have been frustrated by how the spawned process’ stdio state was rather undefined and left you with very little control. Starting with this release we have started addressing this, and programs are now always spawned with stdin, stdout and stderr redirected, and you can even input your own data to stdin and get the data being written to stdout and stderr. Frida’s CLI tools get this for free as this is wired up in the ConsoleApplication base-class. If you’re not using ConsoleApplication or you’re using a different language-binding, simply connect to the output signal of the Device object and your handler will get three arguments each time this signal is emitted: pid, fd, and data, in that order. Hit the input() method on the same class to write to stdin. That’s all there is to it.

Now that we have normalized the stdio behavior across platforms, we will later be able to add API to disable stdio redirection.

Beside this and lots of bug-fixes we have also massively improved the support for spawning plain programs on Darwin, on both Mac and iOS, where spawn() is now lightning fast on both and no longer messes up the code-signing status on iOS.

For those of you doing advanced instrumentation of Mac and iOS apps there’s now also brand new API for dynamically creating your own Objective-C protocols at runtime. We already supported creating new classes and proxy objects, and with this new API you can do even more.

So in closing, here’s a summary of the changes:

7.1.0:

  • core: add Device.input() API for writing to stdin of spawned processes
  • core: add Device.output signal for propagating output from spawned processes
  • core: implement the new spawn() stdio behavior in the Windows, Darwin, and Linux backends
  • core: downgrade to Capstone 3.x for now due to non-trivial regressions in 4.x
  • node: add support for the new stdio API
  • node: add missing return to error-path
  • python: add support for the new stdio API

7.1.1:

  • core: fix intermittent crash in spawn()

7.1.2:

  • core: rework the spawn() implementation on Darwin, now much faster and reliable
  • core: add support for enumerating and looking up dynamic symbols on Darwin
  • core: fix page size computation in the Darwin Mach-O parser

7.1.3:

  • core: revert temporary hack

7.1.4:

  • python: fix ConsoleApplication crash on EOF
  • frida-trace: flush queued events before exiting

7.1.5:

  • frida-repl: improve REPL autocompletion
  • objc: add ObjC.registerProtocol() for dynamic protocol creation
  • objc: fix handling of class name conflicts
  • objc: allow proxies to be named

7.1.6:

  • python: fix setup.py download fallback

7.1.7:

  • python: improve the setup.py download fallback

7.1.8:

  • python: fix the setup.py local fallback and look in home directory instead

7.1.9:

  • core: fix handling of overlapping requests to attach to the same pid
  • core: (Darwin) fix spawn() without attach()
  • core: (Darwin) fix crash when shutdown requests overlap
  • frida-server: always recycle the same temporary directory

7.1.10:

  • core: (Windows) upgrade from VS2013 to VS2015
  • node: add prebuild for Node.js 6.x
  • python: fix handling of unicode command-line arguments on Python 2.x
  • qml: use libc++ instead of libstdc++ on Mac

7.1.11:

  • core: provide a proper error message when the remote Frida is incompatible
  • core: ignore attempts to detach from the system session
  • core: guard against create_script() and detach() overlapping
  • core: fix setTimeout() so the delay is optional and defaults to 0
  • core: (V8 runtime) fix crash when closed File object gets GCed
  • core: (Darwin) fix intermittent crash on teardown
  • core: (QNX) fix implementation of gum_module_find_export_by_name()
  • core: (QNX) implement temporary TLS storage
  • frida-repl: monitor the loaded script and auto-reload on change
  • node: take level into account when handling log messages so console.warn() and console.error() go to stderr instead of stdout
  • node: do not let sessions keep the runtime alive

7.1.12:

  • core: fix the return value of Memory.readByteArray() for size = 0

7.1.13:

  • core: (Linux/Android) fix export address calculation for libraries with a preferred base
  • core: fix Java API not available error on Android 6.0
  • java: improve ART support by taking OS version and arch into account
  • frida-repl: add –no-pause to not pause spawned process at startup

Enjoy!

Frida 7.0 Released

It’s been a while since our last major release bump. This time we’re addressing the long-standing issue where 64-bit integers were represented as JavaScript Number values. This meant that values beyond 53 bits were problematic due to the fact that the underlying representation is a double.

The 64-bit types in the Memory, NativeFunction, and NativeCallback APIs are now properly represented by the newly introduced Int64 and UInt64 types, and their APIs are almost identical to NativePointer.

Now let’s cross our fingers that int64/uint64 make it into ES7.

So in closing, here’s a summary of the changes:

7.0.0:

  • core: rework handling of 64-bit integers
  • core: improve strictness of constructors
  • core: improve QNX support
  • frida-repl: update the logo

7.0.1:

  • core: fix Int64/UInt64 field capacity on 32-bit architectures

7.0.2:

  • core: allow Int64 and UInt64 to be passed as-is to all relevant APIs
  • core: fix handling of $protocols on ObjC instances

7.0.3:

  • core: fix race-condition where listener gets destroyed mid-call
  • core: fix handling of nested native exception scopes
  • core: improve QNX support
  • frida-repl: tweak the startup message

7.0.4:

  • core: massively improve the function hooking success-rate on 32-bit ARM
  • core: improve the function hooking success-rate on 64-bit ARM
  • core: fix the sp value exposed by Interceptor on 32-bit ARM

7.0.5:

  • core: spin the main CFRunLoop while waiting for Device#resume() when spawning iOS apps, allowing thread-sensitive early instrumentation to be applied from the main thread

7.0.6:

  • core: fix hooking of half-word aligned functions on 32-bit ARM
  • core: fix thread enumeration on Linux
  • core: add simple hexdump() API to the Script runtimes
  • core: make the Duktape runtime’s CpuContext serializable to JSON

7.0.7:

  • core: allow passing a NativePointer to hexdump()

7.0.8:

  • core: fix handling of wrapper objects in retval.replace()
  • core: fix behavior of Memory.readUtf8String() when a size is specified
  • core: add support for the new task_for_pid(0) method on the iOS 9.1 JB
  • core: don’t use cbnz which is not available in ARM mode on some processors
  • core: implement enumerate_threads() and modify_thread() for QNX

7.0.9:

  • core: fix early crash in FridaGadget.dylib on iOS when running with ios-deploy and other environments where we are loaded before CoreFoundation
  • core: run a CFRunLoop in the main thread of frida-helper on Darwin, allowing system session scripts to make use of even more Apple APIs
  • core: add stream APIs for working with GIO streams, for now only exposed through UnixInputStream and UnixOutputStream (UNIX), and Win32InputStream and Win32OutputStream (Windows)

7.0.10:

  • core: fix deadlock on script unload when I/O operations are pending

7.0.11:

  • core: spin the main CFRunLoop while FridaGadget.dylib is blocking waiting for Device#resume(), allowing thread-sensitive early instrumentation to be applied from the main thread
  • java: fix method type sanity-check

Enjoy!

Frida 6.2 Released

It’s release o’clock, and this time we’re bringing you massive performance improvements on all platforms, a brand new API for looking up functions, and major stability improvements on iOS 9.

Let’s talk about the latter subject first. Some of you may have noticed weird bugs and deadlocks when using Frida on iOS 9. The root cause was simply that our inline hooking was causing the process to lose the CS_VALID bit of its code-signing status. This was not a problem on iOS 8 and older as jailbreaks were always able to patch the kernel to loosen up on its code-signing requirements. Starting with this release we have implemented some tricks to be able to do inline hooking without breaking the code-signing status. For the technically curious this means that we dynamically generate a .dylib as a temporary file, write out the new versions of the memory pages that we’d like to modify, e.g. the libc memory page containing open(), then pseudo-sign this binary, ask the kernel to F_ADDFILESIGS to it, and finally mmap() from this file on top of the original memory pages.

This brings us to the next topic: performance. The tricks that I just talked about do actually add quite a bit of extra overhead just to hook one single function. It is also a very different approach from what we can do on systems with support for read-write-execute memory-pages and relaxed code-signing requirements, so this obviously meant that major architectural changes were needed. I had also been thinking for a while about being able to apply a whole batch of hooks in one go, allowing us to be more efficient and have more control on exactly when hooks are activated.

Starting with this release, our Interceptor API now supports transactions. Simply call begin_transaction(), hook all the functions, and make them all active in one go by calling end_transaction(). This results in a massive performance boost, and you get all of this for free without any changes to your existing code. This is because we implicitly begin a transaction whenever we’re entering the JavaScript runtime, and end it when we’re leaving it (and just before we send() a message or return from an RPC method). So unless you’re attaching your hooks from timers or asynchronous APIs like Memory.scan(), they will all be batched into a single transaction and get a performance boost.

Here’s how we stack up to CydiaSubstrate in terms of performance:

Note that if you’re using our instrumentation engine from C or C++ you will have to call begin_transaction() and end_transaction() yourself to get this boost, but your code will still work even if you don’t, because every operation will implicitly contain a transaction, and the API allows nesting those calls.

That was function hooking performance, but we didn’t stop there. If you’ve ever used frida-trace to trace Objective-C APIs, or glob for functions across all loaded libraries, you may have noticed that it could take quite a while to resolve all the functions. If you combined this with early instrumentation it could even take so long that we exceeded the system’s launch timeout. All of this has now been optimized, and to give you an idea of the speed-up, a typical Objective-C case that used to take seconds is now completing in a few milliseconds.

Now to the final part of the news. Considering that dynamically discovering functions to hook is such a common use-case, and not just something that frida-trace does, we now have a brand new API for just that:

ApiResolver #1

ApiResolver #2

So in closing, here’s a summary of the changes:

6.2.0:

  • core: improve Interceptor to avoid breaking dynamic code-signing on iOS 9
  • core: move to a transaction-based Interceptor API for improved performance
  • core: fix crash when scheduled callbacks are freed late (V8 and Duktape)
  • frida-trace: improve performance by removing setTimeout() logic, allowing many hooks to be applied in the same transaction
  • frida-trace: batch log events in 50 ms chunks to improve performance

6.2.1:

  • core: add ApiResolver API
  • frida-trace: improve performance by using the new ApiResolver API

6.2.2:

  • core: fix oops that prevented injection into Windows Store/Universal apps
  • core: fix crash on teardown on 32-bit ARM
  • core: add frida-inject, a tool to inject an agent into a running process with similar semantics to frida-gadget
  • core: (Linux) prevent libdl from unloading to work around TLS destructor bug
  • core: (Linux) fix race-condition on rapid uninject

6.2.3:

  • core: fix source-map handling for eval code, which manifested itself as unhandled exceptions getting swallowed, e.g. when running frida-trace
  • core: fix Python 3.x build system regression
  • frida-trace: fix path escaping issue
  • frida-trace: improve error-handling for bad handlers

6.2.4:

  • frida-trace: monitor handlers instead of polling them

6.2.5:

  • core: add support for hooking arbitrary instructions by calling Interceptor.attach() with a function instead of a callbacks object
  • core: add support for detaching individual listeners added by Interceptor.attach(), even synchronously from their callbacks
  • core: add Memory.scanSync()
  • core: fix clobber by improving Interceptor to preserve r12 aka IP on ARM
  • core: expose r8 through r12 to the JavaScript runtimes
  • core: fix crash on architectures where unaligned word access is not supported
  • frida-repl: simplify logic by using the RPC feature
  • node: upgrade to prebuild 3.x

6.2.6:

  • core: fix regression on non-jailbroken iOS systems
  • core: fix Interceptor regression in the Duktape runtime
  • core: fix module name of resolved imports
  • core: add API for specifying which host to connect to
  • core: improve QNX support and fix build regressions
  • core: fix the frida-inject build system on Mac
  • core: (Windows) fix crash when USB device location retrieval fails
  • frida-server: allow overriding the default listen address
  • frida-node: add addRemoteDevice() and removeRemoteDevice() to DeviceManager
  • frida-python: add -H switch for specifying the host to connect to
  • frida-python: add add_remote_device() and remove_remote_device() to DeviceManager
  • frida-python: fix compatibility issues with the Duktape runtime
  • frida-python: canonicalize the requested RPC method name

Enjoy!

Frida 6.1 Released

Some time ago @s1341 ported Frida to QNX, and just a few weeks back he was running into memory footprint issues when using Frida on embedded ARM devices. This was right after he contributed pull-requests porting Frida to linux-arm. We started realizing that it might be time for a new JavaScript runtime, and agreed that Duktape seemed like a great fit for our needs.

This runtime has now landed, all tests are passing, and it even beats our V8 runtime on the measured overhead for a call to a hooked function with an empty onEnter/onLeave callback. To give you an idea:

…/interceptor_on_enter_performance: V8 min=2 max=31 avg=2 OK
…/interceptor_on_enter_performance: DUK min=1 max=2 avg=1 OK

(Numbers are in microseconds, measured on a 4 GHz i7 running OS X 10.11.2.)

Anyway, even if that comparison isn’t entirely fair, as we do some clever recycling and copy-on-write tricks that we don’t yet do in our V8 runtime, this new runtime is already quite impressive. It also allows us to run on really tiny devices, and the performance difference between a roaring JIT-powered monster like V8 and a pure interpreter might not really matter for most users of Frida.

So starting with this release we are also including this brand new runtime in all of our prebuilt binaries so you can try it out and tell us how it works for you. It only adds a few hundred kilobytes of footprint, which is nothing compared to the 6 MB that V8 adds per architecture slice. Please try it out by passing --disable-jit to the CLI tools, or calling session.disable_jit() before the first call to session.create_script().

Considering that this new runtime also solves some issues that would require a lot of work to fix in our JavaScriptCore runtime, like ignoring calls from background threads and avoid poisoning the app’s heap, we decided to get rid of that runtime and switch to this new Duktape-based runtime on OSes where V8 cannot currently run, like on iOS 9. We feature-detect this at runtime, so you still get to use V8 on iOS 8 like before – unless you explicitly --disable-jit as just mentioned.

So in closing, here’s a summary of the changes:

6.1.0:

  • core: replace the JavaScriptCore runtime with its successor built on Duktape
  • core: add disable_jit() to allow users to try out the new Duktape engine
  • core: fix crash on Linux when injecting into processes where pthread_create has never been called/bound yet
  • core: add support for linux-armhf (e.g. Raspberry Pi)
  • python: add disable_jit() to Session
  • node: add disableJit() to Session
  • CLI tools: add –disable-jit switch
  • frida-repl: upgrade to latest prompt-toolkit
  • frida-trace: fix crash when attempting to trace partially resolved imports
  • frida-trace: stick to ES5 in the generated handlers for Duktape compatibility

6.1.1:

  • core: fix synchronization logic and error-handling bugs in the Duktape runtime

6.1.2:

  • core: fix Android regression resulting in crash on inject
  • core: fix Python 3.x build regression
  • clr: add DisableJit() to Session

6.1.3:

  • core: give the iOS frida-helper all the entitlements that the Preferences app has, so system session scripts can read and write system configuration
  • core: changes to support AppContainer ACL on temporary directory/files within
  • node: fix pid check so it allows attaching to the system session

6.1.4:

  • core: implement spawn() for console binaries on iOS
  • core: improve support for hooking low-level OS APIs
  • core: fix mapper issues preventing us from injecting into Mac processes where libraries frida-agent depends are not yet loaded
  • core: make InvocationContext available to replaced functions also

6.1.5:

  • core: add support for generator functions in scripts generated by frida-load
  • frida-repl: fix race condition resulting in hang
  • frida-repl: fix spurious error message on exit

Enjoy!

Frida 6.0 Released

Epic release this time, with brand new iOS 9 support and improvements all over the place. For some more background, check out my blog posts here and here.

There’s a lot of ground to cover here, but the summary is basically:

6.0.0:

  • core: add support for OS X El Capitan
  • core: add support for iOS 9
  • core: fix launchd plist permissions in Cydia package
  • core: disable our dynamic linker on iOS for now
  • core: add new JavaScript runtime based on JavaScriptCore, as we cannot use V8 on iOS 9 with the current jailbreak
  • core: add brand new system session when attaching to pid=0
  • core: improve arm hooking, including support for early TBZ/TBNZ/IT/B.cond, and avoid relocating instructions that a later instruction loops back to
  • core: fix relocation of LDR.W instructions on arm64
  • core: abort when we’re stuck in an exception loop
  • core: fix AutoIgnorer-related deadlocks
  • core: drop our . prefix so temporary files are easier to discover
  • python: add support for running without ES6 support
  • python: tweak setup.py to allow offline installation
  • python: lock the prompt-toolkit version to 0.38 for now
  • frida-repl: fix display of raw buffers as returned by Memory.readByteArray()
  • frida-repl: fix crash in completion on error
  • node: add support for DeviceManager’s added and removed signals
  • node: add example showing how to watch available devices
  • node: use prebuild instead of node-pre-gyp
  • node: Babelify the source code read by frida.load()
  • node: remove frida.load() as it’s now in the frida-load module

6.0.1:

  • python: stop providing 3.4 binaries and move to 3.5 instead
  • node: fix Linux linking issue where we fail to pick up our libffi
  • node: also produce prebuild for Node.js LTS

6.0.2:

  • core: provide FridaGadget.dylib for instrumenting iOS apps without jailbreak
  • core: add support for the iOS Simulator
  • core: improve MemoryAccessMonitor to allow monitoring any combination of R, W or X operations on a page
  • python: fix UTF-8 fields being accidentally exposed as str on Python 2.x

6.0.3:

  • core: fix spawn() on OS X

6.0.4:

  • core: add partial support for using the gadget standalone
  • CLI tools: fix crash when the stdout encoding cannot represent all characters
  • frida-trace: always treat handler scripts as UTF-8

6.0.5:

  • core: add logical shift right and left operations to NativePointer
  • core: improve Interceptor to support attaching to a replaced function
  • core: add support for hooking tiny functions on 32-bit ARM
  • core: emulate {Get/Set}LastErrror and TLS key access on Windows, allowing us to hook more low-level APIs

6.0.6:

  • core: fix launchd / Jetsam issue on iOS 9
  • core: fix iOS 9 code signing issue
  • core: update security attributes on named pipe to allow us to inject into more Windows apps

6.0.7:

  • core: add support for injecting into processes on linux-arm
  • core: fix crashes related to the DebugSymbol API on Mac and iOS
  • frida-trace: improve manpage parser

6.0.8:

  • core: fix Linux compatibility issue caused by failing to link libstdc++ statically

6.0.9:

  • core: add support for running frida-gadget standalone
  • core: add a temporary workaround for Windows compatibility regression
  • core: port the Fruity backend to Linux, allowing direct access to connected iOS devices
  • core: expose the InvocationContext context read-write in the JavaScriptCore runtime also
  • core: fix issue with InvocationContext’s CpuContext getting GCed prematurely

6.0.10:

Re-release of 6.0.9 with a Windows build regression fix.

6.0.11:

  • core: prevent stale HostSession objects in case of network errors
  • CLI tools: assume UTF-8 when the stdout encoding is unknown
  • node: fix double free caused by using the wrong Nan API

6.0.12:

  • core: update security attributes on named pipe on Windows
  • core: add CreateProcessW flags to prevent IFEO loop on Windows
  • core: fix hooking of recursive functions on arm and arm64
  • python: fix Python 3 line endings regression
  • node: update prebuild dependency

Enjoy!

Frida 5.0 Released

Wow, another major release! We decided to change the Device API to give you persistent IDs so you can easily tell different devices apart as they’re hotplugged.

But that’s just the beginning of it, we’re also bringing a ton of other improvements this time:

5.0.0:

  • core: change Device.id to represent individual devices across reconnects
  • core: add new Droidy backend for interfacing with connected Android devices
  • core: adjust confusing iPhone 5+ device name on Darwin
  • core: normalize the fallback iOS device name for consistency with Android
  • core: upgrade V8 to 4.5.103.30
  • objc: include both class and instance methods in $methods and $ownMethods
  • python: add -D switch for specifying the device id to connect to
  • python: add frida-ls-devices CLI tool for listing devices
  • python: update to the new Device.id API
  • python: add get_local_device() and improve API consistency with frida-node
  • node: update to the new Device.id API
  • node: improve the top-level facade API
  • qml: update to the new Device.id API
  • clr: update to the new Device.id API
  • frida-ps: improve the output formatting

5.0.1:

  • core: add support for source maps
  • node: add frida.load() for turning a CommonJS module into a script
  • node: upgrade Nan

5.0.2:

  • core: add console.warn() and console.error()
  • core: add Module.enumerateImports() and implement on Darwin, Linux, and Windows
  • core: allow null module name when calling Module.findExportByName()
  • core: move Darwin.Module and Darwin.Mapper from frida-core to frida-gum, allowing easy Mach-O parsing and out-of-process dynamic linking
  • core: better handling of temporary files
  • frida-trace: add support for conveniently tracing imported functions
  • frida-trace: blacklist dyld_stub_binder from being traced
  • python: avoid logging getting overwritten by the status message changing

5.0.3:

  • core: improve arm64 hooking, including support for hooking short functions

5.0.4:

  • core: improve arm64 hooking, also taking care to avoid relocating instructions that other instructions depend on, including the next instruction after a BL/BLR/SVC instruction
  • core: port Arm64Writer and Arm64Relocator to Capstone

5.0.5:

  • core: fix crash on teardown by using new API provided by our GLib patch
  • core: fix module name resolving on Linux
  • core: improve ELF handling to also consider ET_EXEC images as valid modules
  • core: improve arm64 hooking
  • core: port {Arm,Thumb}Writer and {Arm,Thumb}Relocator to Capstone
  • python: fix tests on OS X 10.11
  • node: fix tests on OS X 10.11

5.0.6:

  • core: turn NativeFunction invocation crash into a JS exception when possible
  • core: add Process.setExceptionHandler() for handling native exceptions from JS
  • core: install a default exception handler that emits error messages
  • core: prevent apps from overriding our exception handler if we install ours early in the process life-time
  • core: gracefully handle it if we cannot replace native functions
  • core: allow RPC exports to return ArrayBuffer values
  • python: add support for rpc methods returning ArrayBuffer objects
  • node: add support for rpc methods returning ArrayBuffer objects

5.0.7:

  • core: don’t install a default exception handler for now

5.0.8:

Re-release of 5.0.7 due to build machine issues.

5.0.9:

  • python: update setup.py to match new build server configuration

5.0.10:

  • core: fix instrumentation of arm64 functions with early usage of IP registers

Enjoy!

Frida 4.5 Released

Time for another packed release. This time we’re bringing a brand new spawn gating API that lets you catch processes spawned by the system, and tons of Android improvements and improvements all over the place.

So without further ado, the list of changes:

4.5.0:

  • core: add Process.pageSize constant
  • core: let Memory.alloc() allocate raw pages when size >= page size
  • core: fix NativeFunction’s handling of small return types
  • core: fix PC alignment when rewriting BLX instructions
  • core: add spawn gating API
  • core: implement get_frontmost_application() on Android
  • core: implement enumerate_applications() on Android
  • core: add support for spawning Android apps
  • core: add support for injecting into arm64 processes on Android
  • core: add support for Android M
  • core: patch the kernel’s live SELinux policy
  • core: integrate with SuperSU to work around restrictions on Samsung kernels
  • core: work around broken sigsetjmp on Android, and many other Android fixes
  • core: fix crash when enumerating modules on Linux
  • core: optimize exports enumeration for remote processes on Darwin
  • dalvik: port to ART and deprecate Dalvik name, now known as Java
  • java: add Java.openClassFile() to allow loading classes at runtime
  • java: fixes for array conversions and field setters
  • python: add support for the new spawn gating API
  • python: allow script source and name to be unicode on Python 2.x also
  • python: fix error-propagation in Python 3.x
  • python: fix the Linux download URL computation
  • node: add support for the new spawn gating API
  • node: port to Nan 2.x

4.5.1:

  • core: fix ensure_host_session() error propagation

Enjoy!

Frida 4.4 Released

With 4.4 out the door, we can now offer you a brand new RPC API that makes it super-easy to communicate with your scripts and have them expose services to your application. We also got some amazing contributions from Adam Brady, who just ported frida-node to Nan, making it easy to build it for multiple versions of Node.js.

So to summarize this release:

  • core: add new RPC API
  • python: add support for calling RPC exports
  • node: add support for calling RPC exports
  • node: allow posted message value to be anything serializable to JSON
  • node: port to Nan

Enjoy!

Frida 4.3 Released

It’s release o’clock, and this time we have a slew of improvements all over the place. In brief:

4.3.0:

  • core: add support for getting details about the frontmost application, initially only for iOS
  • python: add Device.get_frontmost_application()
  • node: add Device.getFrontmostApplication()

4.3.1:

  • core: add support for relocating PC-relative CBZ on arm64
  • frida-repl: fix crash and loading of script on Py3k

4.3.2:

  • core: add support for launching an iOS app with a URL
  • dalvik: fix bug in field caching
  • frida-trace: color and indent events based on thread ID and depth
  • frida-ps: fix application listing on Py3k

4.3.3:

  • core: re-enable the Darwin mapper after accidentally disabling it

4.3.4:

  • core: gracefully handle attempts to replace functions
  • core: throw an exception when Interceptor’s attach() and replace() fail
  • core: fix clean-up of agent sessions
  • core: fix assertion logging and log to CFLog on Darwin
  • dalvik: add Dalvik.synchronized(), Dalvik.scheduleOnMainThread() and Dalvik.isMainThread()
  • dalvik: port Dalvik.androidVersion and Dalvik.choose() to Android 4.2.2
  • python: fix the PyPI download URL for windows-i386
  • frida-trace: handle attach() failures gracefully

4.3.5:

  • frida-server: better resource tracking

4.3.6:

  • core: fix for arm64 function hooking
  • dalvik: fix for Dalvik.enumerateLoadedClasses()

4.3.7:

  • objc: add ObjC.Block for implementing and interacting with blocks

Enjoy!

Frida 4.2 Released

The Frida co-conspirators have been cracking away on several fronts, so much lately that I figured it was worth jotting this down to get the word out.

In Dalvik land, @marc1006 contributed a really neat new feature – the ability to do object carving, essentially scanning the heap for objects of a certain type. Check this out:

const strings = [];
Dalvik.choose('java.lang.String', {
  onMatch: function (str) {
    strings.push(str);
  },
  onComplete: function () {
    console.log('Found ' + strings.length + ' strings!');
  }
});

Meanwhile, @Tyilo has been rocking out adding the same feature for Objective-C:

const strings = [];
ObjC.choose(ObjC.classes.NSString, {
  onMatch: function (str) {
    strings.push(str);
  },
  onComplete: function () {
    console.log('Found ' + strings.length + ' strings!');
  }
});

In other mobile news, @pancake added support for enumerating applications on Firefox OS. Sweet!

While all of this was going on, @s1341 has been hard at work stabilizing the QNX port, and it’s reportedly working really well now.

On my end I have been applying Frida to interesting challenges at NowSecure, and ran into quite a few bugs and limitations in the Objective-C integration. There’s now support for overriding methods that deal with struct types passed by value, e.g. -[UIView drawRect:], which means NativeFunction and NativeCallback also support these; so for declaring a struct simply start an array with the fields’ types specified sequentially. You can even nest them. So for the - drawRect: case where a struct is passed by value, and that struct is made out of two other structs, you’d declare it like this:

const f = new NativeFunction(ptr('0x1234'), 'void',
    [[['double', 'double'], ['double', 'double']]]);

Another thing worth mentioning is that a long-standing issue especially visible when instrumenting 32-bit iOS apps, but affecting all platforms, has finally been fixed.

So let’s run quickly through all the changes:

4.1.8:

  • core: add support for enumerating applications on Firefox OS
  • core: add NativePointer.toMatchPattern() for use with Memory.scan()
  • core: fix QNX injector race condition
  • objc: massively improved handling of types
  • objc: fix implicit conversion from JS string to NSString
  • objc: fix crash during registration of second proxy or unnamed class
  • objc: new ObjC.Object properties: $className and $super
  • dalvik: add Dalvik.choose() for object carving

4.1.9:

  • core: NativeFunction and NativeCallback now support functions passing struct types by value
  • core: fix accidental case-sensitivity in Process.getModuleByName()
  • dalvik: new object property: $className

4.2.0:

  • core: add this.returnAddress to Interceptor’s onEnter and onLeave callbacks
  • objc: add ObjC.choose() for object carving

4.2.1:

  • core: fix exports enumeration of stripped libraries on QNX
  • objc: new ObjC.Object property: $kind, a string that is either instance, class or meta-class
  • objc: fix the $class property so it also does the right thing for classes
  • objc: fix crash when looking up inexistent method
  • python: ensure graceful teardown of the reactor thread
  • frida-discover: fix regression
  • frida-repl: fix hang when target crashes during evaluation of expression

4.2.2:

  • core: fix exception handling weirdness; very visible on ios-arm
  • core: QNX stability improvements
  • objc: add ObjC.api for direct access to the Objective-C runtime’s API
  • objc: new ObjC.Object properties: equals, $superClass and $methods
  • objc: fix iOS 7 compatibility
  • objc: fix toJSON() of ObjC.classes and ObjC.protocols
  • dalvik: fix handling of java.lang.CharSequence
  • frida-repl: add %time command for easy profiling

4.2.3:

  • core: fix crash when handling exceptions without a message object
  • core: fix the life-time of CpuContext JS wrappers
  • core: expose the file mapping info to Process.enumerateRanges()
  • core: make it possible to coalesce neighboring ranges when enumerating
  • core: add convenience API for looking up modules and ranges
  • core: make the QNX mprotect read in a loop instead of just the once
  • dalvik: avoid crashing the process if a type conversion fails
  • dalvik: allow null as call parameter
  • objc: fix conversion of structs with simple field types
  • objc: speed up implicit string conversion by caching wrapper object

4.2.4:

  • objc: fix crash when interacting with not-yet-realized classes

4.2.5:

  • core: optimize Interceptor callback logic and make it twice as fast when onEnter and onLeave aren’t both specified
  • core: fix return-address seen by the invocation-context on arm64
  • core: add a fuzzy backtracer for arm64

4.2.6:

  • core: fix access to arguments 4 through 7 on arm64
  • core: add Memory.readFloat(), Memory.writeFloat(), Memory.readDouble() and Memory.writeDouble()
  • dalvik: improved type checking
  • qnx: implement side-stack for calling onEnter()/onLeave() with the stack-hungry V8 engine

4.2.7:

  • core: Darwin backend bug-fixes
  • core: optimize handling of the send() data payload
  • core: add APIs for interacting with the iOS kernel through task_for_pid(0), only available in the attach(pid=0) session
  • core: side-stack support for replaced functions on QNX
  • objc: add getOwnPropertyNames() to ObjC.classes
  • frida-repl: improved completion

4.2.8:

  • python: fix Py3k regression

4.2.9:

  • objc: add $ownMethods to ObjC.Object
  • dalvik: add support for primitive arrays and object arrays
  • python: improve compatibility between Python 2 and 3
  • frida-repl: better magic commands

4.2.10:

  • core: fix Interceptor vector register clobbering issue on arm64
  • core: improve temporary directory handling on Android

4.2.11:

  • dalvik: add support for accessing instance and static fields
  • dalvik: type conversion improvements
  • python: resolve python runtime lazily on Mac to allow our binaries to work with multiple Python distributions
  • python: pip support

4.2.12:

  • python: fix Py3k regressions

That’s all for now. Please help spread the word by sharing this post across the inter-webs. We’re still quite small as an open source project, so word-of-mouth marketing means a lot to us.

Enjoy!

Frida 4.1 Released

It’s release o’clock, and this time we’re taking the iOS support to the next level while also bringing some solid quality improvements. I’m also really excited to announce that I’ve recently joined NowSecure, and the awesomeness of this release is no conincidence.

Let’s start with a brand new iOS feature. It’s now possible to list installed apps, which frida-ps can do for you:

$ frida-ps -U -a
  PID NAME        IDENTIFIER
10582 Facebook    com.facebook.Facebook
11066 IRCCloud    com.irccloud.IRCCloud
  451 Mail        com.apple.mobilemail
10339 Mailbox     com.orchestra.v2
 6866 Messages    com.apple.MobileSMS
10626 Messenger   com.facebook.Messenger
11043 Settings    com.apple.Preferences
10542 Skype       com.skype.skype
11218 Slack       com.tinyspeck.chatlyio
11052 Snapchat    com.toyopagroup.picaboo
$

Add the -i switch and it will also include all installed applications, and not just those of them that are currently running.

This is also available from your language binding of choice, e.g. from Python:

>>> import frida
>>> iphone = frida.get_usb_device()
>>> print("\n".join(map(repr, iphone.enumerate_applications())))
Application(identifier="com.google.ios.youtube", name="YouTube")
Application(identifier="com.toyopagroup.picaboo", name="Snapchat")
Application(identifier="com.skype.skype", name="Skype", pid=10542)

>>>

That’s cool, but wouldn’t you like to do early instrumentation of those apps? Now you can do that too, by just asking us to spawn an app identifier:

$ frida-trace -U -f com.toyopagroup.picaboo -I "libcommonCrypto*"

Or at the API level:

>>> import frida
>>> iphone = frida.get_usb_device()
>>> pid = iphone.spawn(["com.toyopagroup.picaboo"])
>>> snapchat = iphone.attach(pid)
>>> apply instrumentation
>>> iphone.resume(pid)

Note that we piggy-back on Cydia Substrate for the early launch part in order to maximize interoperability; after all it’s not too good if multiple frameworks all inject code into launchd and risk stepping on each others’ toes. This dependency is however a soft one, so we’ll throw an exception if Substrate isn’t installed when trying to call spawn() with an app identifier.

So, early instrumentation of iOS apps is pretty cool. But, those applications are typically consuming tons of Objective-C APIs, and if we want to instrument them we often find ourselves having to create new Objective-C classes in order to create delegates to insert between the application and the API. Wouldn’t it be nice if such Objective-C classes could be created in pure JavaScript? Now they can:

const MyConnectionDelegateProxy = ObjC.registerClass({
  name: 'MyConnectionDelegateProxy',
  super: ObjC.classes.NSObject,
  protocols: [ObjC.protocols.NSURLConnectionDataDelegate],
  methods: {
    '- init': function () {
      const self = this.super.init();
      if (self !== null) {
        ObjC.bind(self, {
          foo: 1234
        });
      }
      return self;
    },
    '- dealloc': function () {
      ObjC.unbind(this.self);
      this.super.dealloc();
    },
    '- connection:didReceiveResponse:': function (conn, resp) {
      /* this.data.foo === 1234 */
    },
    /*
     * But those previous methods are declared assuming that
     * either the super-class or a protocol we conform to has
     * the same method so we can grab its type information.
     * However, if that's not the case, you would write it
     * like this:
     */
    '- connection:didReceiveResponse:': {
      retType: 'void',
      argTypes: ['object', 'object'],
      implementation: function (conn, resp) {
      }
    },
    /* Or grab it from an existing class: */
    '- connection:didReceiveResponse:': {
      types: ObjC.classes
          .Foo['- connection:didReceiveResponse:'].types,
      implementation: function (conn, resp) {
      }
    },
    /* Or from an existing protocol: */
    '- connection:didReceiveResponse:': {
      types: ObjC.protocols.NSURLConnectionDataDelegate
          .methods['- connection:didReceiveResponse:'].types,
      implementation: function (conn, resp) {
      }
    },
    /* Or write the signature by hand if you really want to: */
    '- connection:didReceiveResponse:': {
      types: 'v32@0:8@16@24',
      implementation: function (conn, resp) {
      }
    }
  }
});

const proxy = MyConnectionDelegateProxy.alloc().init();
/* use `proxy`, and later: */
proxy.release();

Though most of the time you’d like to build a proxy object where you pass on everything and only do some logging for the few methods you actually care about. Check this out:

const MyConnectionDelegateProxy = ObjC.registerProxy({
  protocols: [ObjC.protocols.NSURLConnectionDataDelegate],
  methods: {
    '- connection:didReceiveResponse:': function (conn, resp) {
      /* fancy logging code here */
      /* this.data.foo === 1234 */
      this.data.target
          .connection_didReceiveResponse_(conn, resp);
    },
    '- connection:didReceiveData:': function (conn, data) {
      /* other logging code here */
      this.data.target
          .connection_didReceiveData_(conn, data);
    }
  },
  events: {
    forward: function (name) {
      console.log('*** forwarding: ' + name);
    }
  }
});

const method = ObjC.classes.NSURLConnection[
    '- initWithRequest:delegate:startImmediately:'];
Interceptor.attach(method.implementation, {
  onEnter: function (args) {
    args[3] = new MyConnectionDelegateProxy(args[3], {
      foo: 1234
    });
  }
});

So that’s Objective-C. The Dalvik integration also got some sweet new API for enumerating loaded classes thanks to @marc1006, who also fixed our handling of static methods and being able to return booleans from overriden implementations.

We also got lots of awesome improvements from @Tyilo who helped improve the ObjC integration, beat the REPL into better shape, added APIs for enumerating malloc ranges, and added some convenience APIs to NativePointer.

While all of this was going on, @s1341 has been hard at work doing an amazing job porting Frida to QNX, which is now really close to working like a charm.

Let’s run through the remaining changes:

4.0.1:

  • objc: support for more types
  • frida-trace: fix ObjC tracing regression

4.0.2:

  • frida-node: fix encoding of the pixels property

4.0.3:

  • frida-repl: fix Windows regression

4.0.5:

  • objc: support for more types and better type checking
  • objc: arm64 now working properly
  • frida-repl: allow variables to be created

4.0.6:

  • platform: support passing a plain array of data to send()
  • arm: support for relocating cbz/cbnz instructions

4.1.0:

  • platform: fix spawning of child processes that write to stdout
  • platform: fix NativeCallback’s handling of bool/int8/uint8 return values (this was preventing Dalvik method overrides from being able to return false).
  • platform: allow Memory.readByteArray() with length < 1
  • arm: support for relocating the ldrpc t2 instruction
  • arm: improved redirect resolver
  • arm64: fix relocation of the adrp instruction
  • arm64: support for relocating PC-relative ldr instruction
  • dalvik: add Dalvik.enumerateLoadedClasses()
  • dalvik: fix handling of static methods
  • python: fix console.log() on Windows
  • frida-repl: bugfixes and improvements
  • frida-trace: glob support for tracing ObjC methods

4.1.1:

  • platform: add missing pid field in enumerate_applications()

4.1.2:

  • objc: class and proxy creation APIs
  • objc: new ObjC.protocols API for enumerating protocols

4.1.3:

  • platform: improved concurrency by releasing V8 lock while calling NativeFunction
  • platform: add Process.getModuleByName(name)
  • platform: faster and more robust detach
  • python: stability improvements in CLI tools
  • frida-repl: replace readline with prompt-toolkit

4.1.4:

  • platform: faster and more robust teardown
  • frida-server: clean up on SIGINT and SIGTERM

4.1.5:

  • frida-ps: add support for listing applications

4.1.6:

  • platform: fix crash on spawn on Mac, iOS and Linux
  • platform: add NativePointer.compare() and NativePointer.equals()
  • platform: add Process.enumerateMallocRanges{,Sync}()
  • frida-trace: switch from Enter to Ctrl+C for stopping
  • frida-trace: fix spawning of iOS apps
  • frida-repl: add prototype names to autocomplete

4.1.7:

  • python: CLI tools stability improvements

That’s all for now. Please help spread the word by sharing this post across the inter-webs. We’re still quite small as an open source project, so word-of-mouth marketing means a lot to us.

Enjoy!

Frida 4.0.0 Released

It’s time for an insane release with tons of improvements.

Let’s start with a user-facing change. The CLI tool called frida-repl has been renamed to just frida, and now does tab completion! This and some other awesome REPL goodies were contributed by @fitblip.

There is also integrated support for launching scripts straight from the shell:

$ frida Calculator -l calc.js
    _____
   (_____)
    |   |    Frida 4.0.0 - A world-class dynamic
    |   |                  instrumentation framework
    |`-'|
    |   |    Commands:
    |   |        help      -> Displays the help system
    |   |        object?   -> Display information about 'object'
    |   |        exit/quit -> Exit
    |   |
    |   |    More info at http://www.frida.re/docs/home/
    `._.'

# The code in calc.js has now been loaded and executed
[Local::ProcName::Calculator]->
# Reload it from file at any time
[Local::ProcName::Calculator]-> %reload
[Local::ProcName::Calculator]->

Or, perhaps you’re tired of console.log() and would like to set some breakpoints in your scripts to help you understand what’s going on? Now you can, because Frida just got an integrated Node.js-compatible debugger.

Yo Dawg

Yep yep, but it is actually quite useful, and all of the CLI tools provide the --debug switch to enable it:

# Connect Frida to a locally-running Calculator.app
# and load calc.js with the debugger enabled
$ frida Calculator -l calc.js --debug
    _____
   (_____)
    |   |    Frida 4.0.0 - A world-class dynamic
    |   |                  instrumentation framework
    |`-'|
    |   |    Commands:
    |   |        help      -> Displays the help system
    |   |        object?   -> Display information about 'object'
    |   |        exit/quit -> Exit
    |   |
    |   |    More info at http://www.frida.re/docs/home/
    `._.'

Debugger listening on port 5858
# We can now run node-inspector and start debugging calc.js
[Local::ProcName::Calculator]->

Here’s what it looks like:

Frida Debugger Session

Ever found yourself wanting to frida-trace Objective-C APIs straight from the shell? Thanks to @Tyilo you now can:

# Trace ObjC method calls in Safari
$ frida-trace -m '-[NSView drawRect:]' Safari

There are also other goodies, like brand new support for generating backtraces and using debug symbols to symbolicate addresses:

var f = Module.findExportByName("libcommonCrypto.dylib",
    "CCCryptorCreate");
Interceptor.attach(f, {
    onEnter: function (args) {
        console.log("CCCryptorCreate called from:\n" +
            Thread.backtrace(this.context, Backtracer.ACCURATE)
            .map(DebugSymbol.fromAddress).join("\n") + "\n");
    }
});

Or perhaps you’re on Windows and trying to figure out who’s accessing certain memory regions? Yeah? Well check out the brand new MemoryAccessMonitor. Technically this code isn’t new, but it just hasn’t been exposed to the JavaScript API until now.

Another nice feature is that starting with this release it is no longer necessary to forward multiple TCP ports when using frida-server running on another device, e.g. Android.

There is now also much better error feedback propagated all the way from a remote process to different exceptions in for example Python. With the previous release attaching to an inexistent pid on Mac would give you:

SystemError: GDBus.Error:org.gtk.GDBus.UnmappedGError.Quark._g_2
dio_2derror_2dquark.Code0: task_for_pid() for remote pid failed w
hile trying to make pipe endpoints: (os/kern) failure (5)

Whoah, madness. This is now simply:

frida.ProcessNotFoundError: unable to find process with pid 1234

That’s better. Let’s talk about performance. Perhaps you used frida-trace and wondered why it spent so much time “Resolving functions…”? On a typical iOS app resolving just one function would typically take about 8 seconds. This is now down to ~1 second. While there were some optimizations possible, I quickly realized that no matter how fast we make the enumeration of function exports, we would still need to transfer the data, and the transfer time alone could be unreasonable. Solution? Just move the logic to the target process and transfer the logic instead of the data. Simple. Also, the Dalvik and ObjC interfaces have been optimized so seconds have been reduced to milliseconds. The short story here is further laziness in when we interrogate the language runtimes. We took this quite far in the ObjC interface, where we now use ES6 proxies to provide a more idiomatic and efficient API.

That brings us to the next topic. The ObjC interface has changed a bit. Essentially:

var NSString = ObjC.use("NSString");

is now:

var NSString = ObjC.classes.NSString;

You still use ObjC.classes for enumerating the currently loaded classes, but this is now behaving like an object mapping class name to a JavaScript ObjC binding.

Also, there’s no more casting, so instead of:

var NSSound = ObjC.use('NSSound');
var sound = ObjC.cast(ptr("0x1234"), NSSound);

You just go:

var sound = new ObjC.Object(ptr("0x1234"));

Yep, no more class hierarchies trying to mimic the ObjC one. Just a fully dynamic wrapper where method wrappers are built on the first access, and the list of methods isn’t fetched unless you try to enumerate the object’s properties.

Anyway, this is getting long, so let’s summarize the other key changes:

  • The Dalvik interface now handles varargs methods. Thanks to @dmchell for reporting and helping track this down.
  • NativePointer also provides .and(), .or() and .xor() thanks to @Tyilo.
  • The Interceptor’s onEnter/onLeave callbacks used to expose the CPU registers through this.registers, which has been renamed to this.context, and now allows you to write to the registers as well.
  • Process.enumerateThreads()’s thread objects got their CPU context field renamed from registers to context for consistency.
  • Synchronous versions of enumerateFoo() API available as enumerateFooSync() methods that simply return an array with all of the items.
  • Memory.readCString() is now available for reading ASCII C strings.
  • Frida.version can be interrogated to check which version you’re running, and this is also provided on the frida-core end, which for example is exposed by frida-python through frida.__version__.
  • Stalker now supports the jecxz and jrcxz instructions. This is good news for CryptoShark, which should soon provide some updated binaries to bundle the latest version of Frida.
  • V8 has been updated to 4.3.62, and a lot of ES6 features have been enabled.
  • We’re now using a development version of the upcoming Capstone 4.0.
  • All third-party dependencies have been updated to the latest and greatest.
  • Windows XP is now supported. This is not a joke. I realized that we didn’t actually use any post-XP APIs, and as I had to rebuild the dependencies on Windows I figured we might as well just lower our OS requirements to help those of you still instrumenting software on XP.

Enjoy!

Frida 3.0.0 Released

You may have wondered:

Why a Python API, but JavaScript debugging logic?

Well, you can now do this:

$ npm install frida

We just brought you brand new Node.js bindings, and they are fully asynchronous:

Check out the examples to get an idea what the API looks like. It’s pretty much a 1:1 mapping of the API provided by the Python bindings, but following Node.js / JavaScript conventions like camelCased method-names, methods returning ES6 Promise objects instead of blocking, etc.

Now, combine this with NW.js and you can build your own desktop apps with HTML, CSS, and JavaScript all the way through.

So, brand new Node.js bindings; awesome! We did not stop there, however. But first, a few words about the future. I am excited to announce that I have just started a company with the goal of sponsoring part-time development of Frida. By offering reverse-engineering and software development expertise, the goal is to generate enough revenue to pay my bills and leave some time to work on Frida. Longer term I’m hoping there will also be demand for help adding features or integrating Frida into third-party products. In the meantime, however, if you know someone looking for reverse-engineering or software development expertise, I would really appreciate it if you could kindly refer them to get in touch. Please see my CV for details.

That aside, let’s get back to the release. Next up: 32-bit Linux support! Even Stalker has been ported. Not just that, the Linux backend can even do cross-architecture injection like we do on the other platforms. This means a 64-bit Frida process, e.g. your Python interpreter, can inject into a 32-bit process. The other direction works too.

Another awesome update is that Tyilo contributed improvements to frida-trace so it now uses man-pages for auto-generating the log handlers. Awesome, huh? But there’s even more goodies:

  • frida-server ports are now recycled, so if you’re using Frida on Android you won’t have to keep forwarding ports unless you’re actually attaching to multiple processes at the same time.
  • Linux and Android spawn() support has been improved to also support PIE binaries.
  • Android stability and compatibility improvements.
  • Mac and Linux build system have been revamped, and make it easy to build just the parts that you care about; and maybe even some components you didn’t even know were there that were previously not built by default.
  • Python bindings have a minor simplification so instead of frida.attach(pid).session.create_script() it’s simply just frida.attach(pid).create_script(). This is just like in the brand new Node.js bindings, and the reason we had to bump the major version.

That’s the gist of it. Please help spread the word by sharing this post across the inter-webs. We’re still quite small as an open source project, so word-of-mouth marketing means a lot to us.

Enjoy!

Frida 2.0.2 Released

Thanks to your excellent feedback we just eliminated a crasher when using Frida on Windows with certain iOS device configurations. As this is a very important use-case we decided to do a hotfix release without any other changes.

Please keep the bug-reports coming!

Frida 2.0.1 Released

Just a quick bug-fix release to remedy an iOS issue that slipped through the final testing of 2.0.0. Enjoy!

Frida 2.0.0 Released

It’s time for a new and exciting release! Key changes include:

  • No more kernel panics on Mac and iOS! Read the full story here.
  • Mac and iOS injector performs manual mapping of Frida’s dylib. This means we’re able to attach to heavily sandboxed processes.
  • The CLI tools like frida-trace, frida-repl, etc., have brand new support for spawning processes:
$ frida-trace -i 'open*' -i 'read*' /bin/cat /etc/resolv.conf
    27 ms	open$NOCANCEL()
    28 ms	read$NOCANCEL()
    28 ms	read$NOCANCEL()
    28 ms	read$NOCANCEL()
Target process terminated.
Stopping...
$
  • Usability improvements in frida-repl and frida-discover.
  • First call to DeviceManager.enumerate_devices() does a better job and also gives you the currently connected iOS devices, so for simple applications or scripts you no longer have to subscribe to updates if you require the device to already be present.
  • The python API now provides you with frida.get_usb_device(timeout = 0) and frida.get_remote_device() for easy access to iOS and remote/Android devices.
  • The onEnter and onLeave callbacks passed to Interceptor.attach() may access this.registers to inspect CPU registers, which is really useful when dealing with custom calling conventions.
  • console.log() logs to the console on your application’s side instead of the target process. This change is actually why we had to bump the major version for this release.
  • Android 5.0 compatibility, modulo ART support.
  • Brand new support for Android/x86. Everything works except the Dalvik integration; please get in touch if you’d like to help out with a pull-request to fix that!

Want to help out? Have a look at our GSoC 2015 Ideas Page to get an overview of where we’d like to go next.

Enjoy!

Update 2am: An iOS issue slipped through the final testing, so we just pushed 2.0.1 to remedy this.

Update 11pm: Thanks to your excellent feedback we found a critical bug when using Frida on Windows with certain iOS device configurations. Please upgrade to 2.0.2 and let us know if you run into any issues.

Frida 1.8.0 Released

This release introduced a serious regression on iOS and was quickly pulled from our Cydia repo, though it was available for Mac, Linux and Android while waiting to be replaced by 2.0.0.

Frida 1.6.7 Released

Tired of waiting for Frida to attach to 32-bit processes on 64-bit Mac or iOS systems? Or perhaps frida-trace takes a while to resolve functions? If any of the above, or none of it, then this release is for you!

Attaching to 32-bit processes on Mac/iOS hosts has been optimized, and instead of seconds this is now a matter of milliseconds. That’s however specific to Darwin OSes; this release also speeds up enumeration of module exports on all OSes. This is now 75% faster, and should be very noticable when using frida-trace and waiting for it to resolve functions.

Also, as an added bonus, teardown while attached to multiple processes no longer crashes on Darwin and Linux.

Enjoy!

Frida 1.6.5 Released

It’s release o’clock, and time for some bug fixes:

  • iOS 8.1 is now supported, and the ARM64 support is better than ever.
  • The iOS USB transport no longer disconnects when sending a burst of data to the device. This would typically happen when using frida-trace and tracing a bunch of functions, resulting in a burst of data being sent over the wire. This was actually a generic networking issue affecting Mac and iOS, but was very reproducible when using Frida with a tethered iOS device.
  • Eliminated crashes on shutdown of the Python interpreter.
  • The onEnter and onLeave callbacks in frida-trace scripts are now called with this bound to the correct object, which means that it’s bound to an object specific to that thread and invocation, and not an object shared by all threads and invocations.

Frida 1.6.4 Released

It’s time for a bug-fix release!

Stalker improvements:

  • The engine no longer pre-allocates a fixed chunk of 256 MB per thread being traced, and now grows this dynamically in a reentrancy-safe manner.
  • Eliminated a bug in the cache lookup logic where certain blocks would always result in a cache miss. Those blocks thus got recompiled every time they were about to get executed, slowing down execution and clogging up the cache with more and more entries, and eventually running out of memory.
  • Relocation of RIP-relative cmpxchg instruction is now handled correctly.

Better Dalvik integration (Android):

  • App’s own classes can now be loaded.
  • Several marshalling bugs have been fixed.

Script runtime:

  • More than one NativeFunction with the same target address no longer results in use-after-free.

Also, CryptoShark 0.1.2 is out, with an upgraded Frida engine and lots of performance improvements so the GUI is able to keep up with the Stalker. Go get it while it’s hot!

Frida 1.6.3 Released

This latest release includes a bunch of enhancements and bug fixes. Some of the highlights:

  • The remainder of Frida’s internals have been migrated from udis86 to Capstone, which means that our Stalker is now able to trace binaries with very recent x86 instructions. Part of this work also included battle-testing it on 32- and 64-bit binaries on Windows and Mac, and all known issues have now been resolved.

  • Memory.protect() has been added to the JavaScript API, allowing you to easily change page protections. For example:

Memory.protect(ptr("0x1234"), 4096, 'rw-');
  • Process.enumerateThreads() omits Frida’s own threads so you don’t have to worry about them.

  • Python 3 binaries are now built against Python 3.4.

So with this release out, let’s talk about CryptoShark:

Grab a pre-built Windows binary here, or build it from source if you’d like to try it out on Mac or Linux.

Enjoy!

Frida 1.6.2 Released

It’s release o’clock, and this time we’re bringing you more than just bugfixes. Meet Instruction.parse():

var a = Instruction.parse(ptr("0x1234"));
var b = Instruction.parse(a.next);
console.log(a);
console.log(b);

Output:

push rbp
mov rbp, rsp

How is this implemented you ask? That’s the cool part. Frida already uses the amazing Capstone disassembly framework behind the scenes, and thus it makes perfect sense to make it available to the JavaScript runtime. Have a look at the JavaScript API Reference for all the details.

Enjoy!

Frida 1.6.1 Released

It’s time for a bugfix release. Highlights:

  • Compatibility with the Pangu iOS jailbreak on ARM64. The issue is that RWX pages are not available like they used to be with the evad3rs jailbreak.
  • Fix occasional target process crash when detaching.
  • Fix crash when trying to attach to a process the second time after failing to establish the first time. This primarily affected Android users, but could happen on any OS when using frida-server.
  • Faster and more reliable injection on Linux/x86-64 and Android/ARM.
  • Fix issues preventing hooking of HeapFree and friends on Windows.
  • Upgraded GLib, libgee, json-glib and Vala dependencies for improved performance and bugfixes.
  • No more resource leaks. Please report if you find any.

Also new since 1.6.0, as covered in my blog post, there is now a full- featured binding for Qml. This should be of interest to those of you building graphical cross-platform tools.

Frida 1.6.0 Released

As some of you may have noticed, Frida recently got brand new Android support, allowing you to easily instrument code just like on Windows, Mac, Linux and iOS. This may sound cool and all, but Android does run a lot of Java code, which means you’d only be able to observe the native side-effects of whatever that code was doing. You could of course use Frida’s FFI API to poke your way into the VM, but hey, shouldn’t Frida just do that dirty plumbing for you? Of course it should!

Here’s what it looks like in action:

Dalvik.perform(function () {
    var Activity = Dalvik.use("android.app.Activity");
    Activity.onResume.implementation = function () {
        send("onResume() got called! Let's call the original implementation");
        this.onResume();
    };
});

The Dalvik.perform() call takes care of attaching your thread to the VM, and isn’t necessary in callbacks from Java. Also, the first time you call Dalvik.use() with a given class name, Frida will interrogate the VM and build a JavaScript wrapper on-the-fly. Above we ask for the Activity class and replace its implementation of onResume with our own version, and proceed to calling the original implementation after sending a message to the debugger (running on your Windows, Mac or Linux machine). You could of course choose to not call the original implementation at all, and emulate its behavior. Or, perhaps you’d like to simulate an error scenario:

Dalvik.perform(function () {
    var Activity = Dalvik.use("android.app.Activity");
    var Exception = Dalvik.use("java.lang.Exception");
    Activity.onResume.implementation = function () {
        throw Exception.$new("Oh noes!");
    };
});

So there you just instantiated a Java Exception and threw it straight from your JavaScript implementation of Activity.onResume.

This release also comes with some other runtime goodies:

  • Memory.copy(dst, src, n): just like memcpy
  • Memory.dup(mem, size): short-hand for Memory.alloc() followed by Memory.copy()
  • Memory.writeXXX(): the missing Memory.read() counterparts: S8, S16, U16, S32, U32, S64, U64, ByteArray, Utf16String and AnsiString
  • Process.pointerSize to make your scripts more portable
  • NativePointer instances now have a convenient isNull() method
  • NULL constant so you don’t have to do ptr("0") all over the place
  • WeakRef.bind(value, fn) and WeakRef.unbind(id) for the hardcore: The former monitors value so fn gets called as soon as value has been garbage-collected, or the script is about to get unloaded. It returns an id that you can pass to unbind() for explicit cleanup. This API is useful if you’re building a language-binding, where you need to free native resources when a JS value is no longer needed.

Enjoy!

Frida 1.4.2 Released

Just a quick bugfix release to squash this annoying bug, which is reproducible on all supported x86 OSes. Thanks for Guillaume for tracking this one down.

As a bonus, frida-repl now also works on Windows. Happy REPLing!

Frida 1.4.1 Released

Interested in spawning processes on Windows or Linux, and not just on Mac? Or maybe you’ve been bitten by the Linux injector crashing your processes instead of letting you inject into them? Or maybe you had a function name that was so long that frida-trace overflowed the max filename length on Windows? Well, if any of the above, or none of it, then Frida 1.4.1 is for you!

Thanks to Guillaume and Pedro for making this release awesome. Keep those pull- requests and bug reports coming!

Frida 1.4.0 Released

Did anyone say Android? Frida 1.4.0 is out, with brand new Android support! Have a look at the documentation here to get started. Also new in this release is that Frida is now powered by the amazing Capstone Disassembly Engine, which means our cross-platform code instrumentation is even more powerful. It also paves the way for taking the x86-only stealth tracing to new architectures in future releases.

Enjoy!

Frida 1.2.1 Released

Had some fun tracing Apple’s crypto APIs, which lead to the discovery of a few bugs. So here’s 1.2.1 bringing some critical ARM-related bugfixes:

  • ARM32: Fix crashes caused by register clobber issue in V8 on ARM32 due to an ABI difference regarding r9 in Apple’s ABI compared to AAPCS.
  • ARM32: Fix ARM32/Thumb relocator branch rewriting for immediate same-mode branches.
  • ARM64: Improve ARM64 relocator to support rewriting b and bl.

Frida 1.2.0 Released

It’s release-o-clock, and Frida 1.2.0 is finally out! Bugfixes aside, this release introduces brand new ARM64 support, which is quite useful for those of you using Frida on your iPhone 5S or iPad Air. You can now inject into both 64- and 32-bit processes, just like on Mac and Windows.

This release also improves stability on ARM32, where attaching to short functions used to result in undefined behavior.

Enjoy!

Frida 1.0.11 Released

Some of you experienced issues injecting into processes on Windows, as well as crashes on iOS. Here’s a new release bringing some serious improvements to Frida’s internals:

  • V8 has been upgraded to 3.25 in order to fix the iOS stability issues. This also means new features (like ECMAScript 6) and improved performance on all platforms. Another nice aspect is that Frida now depends on a V8 version that runs on 64-bit ARM, which paves the way for porting Frida itself to AArch64.
  • The Windows injector has learned some new tricks and will get you into even more processes. A configuration error was also discovered in the Windows build system, which explains why some of you were unable to inject into some processes.
  • For those of you building Frida on Windows, the build system there now depends on VS2013. This means XP is no longer supported, though it is still possible to build with the v120_xp toolchain if any of you still depend on that, so let me know if this is a deal-breaker for you.
  • The recently added support for this.lastError (Windows) is now working correctly.

That’s all for now. Let us know what you think, and if you like Frida, please help spread the word! :)

Frida 1.0.10 Released

This release brings a few improvements:

  • Interceptor is now compatible with a lot more functions on iOS/ARM.
  • A new CLI tool called frida-repl provides you with a basic REPL to experiment with the JavaScript API from inside a target process.
  • onLeave callback passed to Interceptor.attach() is now able to replace the return value by calling retval.replace().
  • Both onEnter and onLeave callbacks passed to Interceptor.attach() can access this.errno (UNIX) or this.lastError (Windows) to inspect or manipulate the current thread’s last system error.

Here’s how you can combine the latter three to simulate network conditions for a specific process running on your Mac:

~ $ frida-repl TargetApp

Then paste in:

callbacks = { \
    onEnter: function onEnter(args) { \
        args[0] = ptr(-1); // Avoid side-effects on socket \
    }, \
    onLeave: function onLeave(retval) { \
        var ECONNREFUSED = 61; \
        this.errno = ECONNREFUSED; \
        retval.replace(-1); \
    } \
}; \
Module.enumerateExports("libsystem_kernel.dylib", { \
    onMatch: function (exp) { \
        if (exp.name.indexOf("connect") === 0 && exp.name.indexOf("connectx") !== 0) { \
            Interceptor.attach(exp.address, callbacks); \
        } \
    }, \
    onComplete: function () {} \
});

Enjoy!

Frida 1.0.9 Released

Another release — this time with some new features:

  • Objective-C integration for Mac and iOS. Here’s an example to whet your appetite:
var UIAlertView = ObjC.use('UIAlertView'); /* iOS */
ObjC.schedule(ObjC.mainQueue, function () {
    var view = UIAlertView.alloc().initWithTitle_message_delegate_cancelButtonTitle_otherButtonTitles_(
        "Frida",
        "Hello from Frida",
        ptr("0"),
        "OK",
        ptr("0"));
    view.show();
    view.release();
});
  • Module.enumerateExports() now also enumerates exported variables and not just functions. The onMatch callback receives an exp object where the type field is either function or variable.

To get the full scoop on the ObjC integration, have a look at the JavaScript API reference.

Frida 1.0.8 Released

We just rolled out a bugfix release: - Support injection into Mac App Store apps - Eliminate iOS daemon auto-start issues - No more iOS crashes shortly after injecting

Frida 1.0.7 Released

This release brings USB device support in the command-line tools, and adds frida-ps for enumerating processes both locally and remotely.

For example to enumerate processes on your tethered iOS device:

$ frida-ps -U

The -U switch is also accepted by frida-trace and frida-discover.

Docs how to set this up on your iOS device will soon be added to the website.

However, that’s not the most exciting part. Starting with this release, Frida got its first contribution since the HN launch. Pete Morici dived in and contributed support for specifying module-relative functions in frida-trace:

$ frida-trace -a 'kernel32.dll+0x1234'

Enjoy!

Frida 1.0.6 Released

This release simplifies the licensing and fixes bugs reported by the community since the HN launch.

Primarily: - Relicense remaining GPLv3+ Frida components to LGPLv2.1+ (same as frida-gum). - Tracer works on 64-bit with function addresses in the upper range - Linux build links with Frida’s own libraries instead of the build machine’s corresponding libraries.

Frida 1.0.5 Released

This release improves frida-trace with support for auto-generating, loading and reloading function handlers from scripts on the filesystem. Have a look at our Quick-start guide for a walkthrough. Also new in this release is Py3k support, which is available from PyPI on all platforms.