Quantcast
Channel: Frida • A world-class dynamic instrumentation toolkit
Viewing all 199 articles
Browse latest View live

Frida 4.4 Released

$
0
0

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.5 Released

$
0
0

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 5.0 Released

$
0
0

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 6.0 Released

$
0
0

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 6.1 Released

$
0
0

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=2max=31avg=2 OK
…/interceptor_on_enter_performance: DUK min=1max=2avg=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 presentation at FOSDEM 2016

Frida 6.2 Released

$
0
0

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 7.0 Released

$
0
0

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 7.1 Released

$
0
0

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.2 Released

$
0
0

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';constco=require('co');constfrida=require('frida');co(function*(){constsystemSession=yieldfrida.attach(0);yieldsystemSession.disableJit();constbytecode=yieldsystemSession.compileScript(`'use strict';rpc.exports={listThreads:function(){returnProcess.enumerateThreadsSync();}};`);constsession=yieldfrida.attach('Twitter');yieldsession.disableJit();constscript=yieldsession.createScriptFromBytes(bytecode);yieldscript.load();constapi=yieldscript.getExports();console.log('api.listThreads() =>',yieldapi.listThreads());yieldscript.unload();}).catch(err=>{console.error(err);});

And from Python:

from__future__importprint_functionimportfridasystem_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.exportsprint("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

Enjoy!

Frida 7.3 Released

$
0
0

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

Enjoy!

Frida 8.0 Released

$
0
0

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 8.1 Released

$
0
0

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';constexpress=require('express');constapp=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:

constopen=newSystemFunction(Module.findExportByName(null,'open'),'int',['pointer','int']);constO_RDONLY=0;constpath=Memory.allocUtf8String('/inexistent');constresult=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

Enjoy!

Frida 9.0 Released

$
0
0

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 callSession#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:

importfridadevice=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 addsPOSIX_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 10.0 Released

$
0
0

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 10.4 Released

$
0
0

Frida provides quite a few building blocks that make it easy to do portable instrumentation across many OSes and architectures. One area that’s been lacking has been in non-portable use-cases. While we did provide some primitives like Memory.alloc(Process.pageSize) and Memory.patchCode(), making it possible to allocate and modify in-memory code, there wasn’t anything to help you actually generate code. Or copy code from one memory location to another.

Considering that Frida needs to generate and transform quite a bit of machine code for its own needs, e.g. to implement Interceptor and Stalker, it should come as no surprise that we already have C APIs to do these things across six different instruction set flavors. Initially these APIs were so barebones that I didn’t see much value in exposing them to JavaScript, but after many years of interesting internal use-cases they’ve evolved to the point where the essential bits are now covered pretty well.

So with 10.4 we are finally exposing all of these APIs to JavaScript. It’s also worth mentioning that these new bindings are auto-generated, so future additions will be effortless.

Let’s take a look at an example on x86:

vargetLivesLeft=Module.findExportByName('game-engine.so','get_lives_left');varmaxPatchSize=64;// Do not write out of bounds, may be// a temporary buffer!Memory.patchCode(getLivesLeft,maxPatchSize,function(code){varcw=newX86Writer(code,{pc:getLivesLeft});cw.putMovRegU32('eax',9999);cw.putRet();cw.flush();});

Which means we replaced the beginning of our target function with simply:

moveax,9999ret

I.e. assuming the return type is int, we just replaced the function body withreturn 9999;.

As a side-note you could also use Memory.protect() to change the page protection and then go ahead and write code all over the place, butMemory.patchCode() is very handy because it also

  • ensures CPU caches are flushed;
  • takes care of code-signing corner-cases on iOS.

So that was a simple example. Let’s try something a bit crazier:

varmultiply=newNativeCallback(function(a,b){returna*b;},'int',['int','int']);varimpl=Memory.alloc(Process.pageSize);Memory.patchCode(impl,64,function(code){varcw=newX86Writer(code,{pc:impl});cw.putMovRegU32('eax',42);varstackAlignOffset=Process.pointerSize;cw.putSubRegImm('xsp',stackAlignOffset);cw.putCallAddressWithArguments(multiply,['eax',7]);cw.putAddRegImm('xsp',stackAlignOffset);cw.putJmpShortLabel('done');cw.putMovRegU32('eax',43);cw.putLabel('done');cw.putRet();cw.flush();});varf=newNativeFunction(impl,'int',[]);console.log(f());

Though that’s quite a few hoops just to multiply 42 by 7, the idea is to illustrate how calling functions, even back into JavaScript, and jumping to labels, is actually quite easy.

Finally, let’s look at how to copy instructions from one memory location to another. Doing this correctly is typically a lot more complicated than a straight memcpy(), as some instructions are position-dependent and need to be adjusted based on their new locations in memory. Let’s look at how we can solve this with Frida’s new relocator APIs:

varimpl=Memory.alloc(Process.pageSize);Memory.patchCode(impl,Process.pageSize,function(code){varcw=newX86Writer(code,{pc:impl});varlibcPuts=Module.findExportByName(null,'puts');varrl=newX86Relocator(libcPuts,cw);while(rl.readOne()!==0){console.log('Relocating: '+rl.input.toString());rl.writeOne();}cw.flush();});varputs=newNativeFunction(impl,'int',['pointer']);puts(Memory.allocUtf8String('Hello!'));

We just made our own replica of puts() in just a few lines of code. Neat!

Note that you can also insert your own instructions, and use skipOne() to selectively skip instructions in case you want to do custom instrumentation. (This is how Stalker works.)

Anyway, that’s the gist of it. You can find the brand new API references at:

Also note that Process.arch is convenient for determining which writer/relocator to use. On that note you may wonder why there’s just a single implementation for 32- and 64-bit x86. The reason is that these instruction sets are so close that it made sense to have a unified implementation. This also makes it easier to write somewhat portable code, as some meta register-names are available. E.g. xax resolves to eax vs rax depending on the kind of process you are in.

Enjoy!

Frida 10.5 Released

$
0
0

The midnight oil has been burning and countless cups of coffee have been consumed here at NowSecure, and boy do we have news for you this time.

Continuing in the spirit of last release’ low-level bag of goodies, we’ll be moving one level up the stack this time. We are going to introduce a brand new way to use new CodeWriter APIs, enabling you to weave in your own instructions into the machine code executed by any thread of your choosing. We’re talking lazy dynamic recompilation on a per-thread basis, with precise control of the compilation process.

But first a little background. Most people using Frida are probably using theInterceptor API to perform inline hooking, and/or doing method swizzling or replacement through the ObjC and Java APIs. The idea is typically to modify some interesting API that you expect to be called, and be able to divert execution to your own code in order to observe, augment, or fully replace application behavior.

One drawback to such approaches is that code or data is modified, and such changes can be trivially detected. This is fine though, as being invisible to the hosting process’ own code is always going to be a cat and mouse game when doing in-process instrumentation.

These techniques are however quite limited when trying to answer the question of “behind this private API, which other APIs actually get called for a given input?”. Or, when doing reversing and fuzzing, you might want to know where execution diverges between two known inputs to a given function. Another example is measuring code coverage. You could use Interceptor’s support for instruction-level probes, first using a static analysis tool to find all the basic blocks and then using Frida to put single-shot probes all over the place.

Enter Stalker. It’s not a new API, but it’s been fairly limited in what it allowed you to do. Think of it as a per-thread code-tracer, where the thread’s original machine code is dynamically recompiled to new memory locations in order to weave in instrumentation between the original instructions.

It does this recompilation lazily, one basic-block at a time. Considering that a lot of self-modifying code exists, it is careful about caching compiled blocks in case the original code changes after the fact.

Stalker also goes to great lengths to recompile the code such that side-effects are identical. E.g. if the original instruction is a CALL it will make sure that the address of the original next instruction is what’s pushed on the stack, and not the address of the next recompiled instruction.

Anyway, Stalker has historically been like a pet project inside of a pet project. A lot of fun, but other parts of Frida received most of my attention over the years. There have been some awesome exceptions though. Me and@karltk did some fun pair-programming sessions many years ago when we sat down and decided to get Stalker working well on hostile code. At some later point I put together CryptoShark in order get people excited about its potential. Some time went by and suddenly Stalker received a critical bug-fix contributed by Eloi Vanderbeken. Early this year, Antonio Ken Iannillo jumped on board and ported it to arm64. Then, very recently, Erik Smit showed up and fixed a critical bug where we would produce invalid code for REP-prefixed JCC instructions. Yay!

Stalker’s API has so far been really limited. You can tell it to follow a thread, including the thread you’re in, which is useful in combination with inline hooking, i.e. Interceptor. The only two things you could do was:

  1. Tell it which events you’re interested in, e.g. call: true, which will produce one event per CALL instruction. This means Stalker will add some logging code before each such instruction, and that would log where the CALL happened, its target, and its stack depth. The other event types are very similar.
  2. Add your own call probes for specific targets, giving you a synchronous callback into JavaScript when a CALL is made to a specific target.

I’m super-excited to announce that we’ve just introduced a third thing you can do with this API, and this one is a game changer. You can now customize the recompilation process, and it’s really easy:

'use strict';varappModule=Process.enumerateModulesSync()[0];varappStart=appModule.base;varappEnd=appStart.add(appModule.size);Process.enumerateThreadsSync().forEach(function(thread){console.log('Stalking '+thread.id);Stalker.follow(thread.id,{transform:function(iterator){varinstruction=iterator.next();varstartAddress=instruction.address;varisAppCode=startAddress.compare(appStart)>=0&&startAddress.compare(appEnd)===-1;do{if(isAppCode&&instruction.mnemonic==='ret'){iterator.putCmpRegI32('eax',60);iterator.putJccShortLabel('jb','nope','no-hint');iterator.putCmpRegI32('eax',90);iterator.putJccShortLabel('ja','nope','no-hint');iterator.putCallout(onMatch);iterator.putLabel('nope');}iterator.keep();}while((instruction=iterator.next())!==null);}});});functiononMatch(context){console.log('Match! pc='+context.pc+' rax='+context.rax.toInt32());}

The transform callback gets called synchronously whenever a new basic block is about to be compiled. It gives you an iterator that you then use to drive the recompilation-process forward, one instruction at a time. The returnedInstruction tells you what you need to know about the instruction that’s about to be recompiled. You then call keep() to allow Stalker to recompile it as it normally would. This means you can omit this call if you want to skip some instructions, e.g. because you’ve replaced them with your own code. The iterator also allows you to insert your own instructions, as it exposes the full CodeWriter API of the current architecture, e.g. X86Writer.

The example above determines where the application’s own code is in memory, and adds a few extra instructions before every RET instruction in any code belonging to the application itself. This code checks if eax contains a value between 60 and 90, and if it does, calls out to JavaScript to let it implement arbitrarily complex logic. This callback can read and modify registers as it pleases. What’s nice about this approach is that you can insert code into hot code-paths and selectively call into JavaScript, making it easy to do really fast checks in machine code but offload more complex tasks to a higher level language. You can also Memory.alloc() and have the generated code write directly there, without entering into JavaScript at all.

So that’s the big new thing in 10.5. Special thanks to @asabil who helped shape this new API.

In closing, the only other big change is that the Instruction API now exposes a lot more details of the underlying Capstone instruction. Stalker also uses a lot less memory on both x86 and arm64, and is also more reliable. Lastly,Process.setExceptionHandler() is now a documented API, along with ourSQLite API.

Enjoy!

Frida 10.6 Released

$
0
0

It’s time for some big updates to Frida’s Gadget.

This component is really useful when dealing with jailed iOS and Android devices, but is now also able to cover a lot of other scenarios.

Its environment variables are now gone, and have been replaced by an optional configuration file. Because some apps may look for loaded libraries with “Frida” in their name as part of their “anti-debug” defenses, we now allow you to rename Gadget’s binary however you like. Along with this it now also supports three different interaction types.

It can listen on a TCP port, like before, and it can also load scripts from the filesystem and run fully autonomously. The latter part used to be really limited but is now really flexible, as you can even tell it to load scripts from a directory, where each script may have filters. This is pretty useful for system-wide tampering, and should allow for even more interesting use-cases.

So without further ado, I would urge you all to check out the brand new docs available here.

Enjoy!

Frida 10.7 Released

$
0
0

iOS users rejoice: Frida is now compatible with the latest Electra jailbreak on iOS 11! At the time of this writing that means 1.0.4, but now that Electra seems to have stabilized it should be safe to assume that we’ll also be compatible with future updates. Just make sure you’re not running anything older than 1.0.4.

In other news, our Android support has improved significantly over the last releases, so if you’re even slightly behind: go grab the latest 10.7.x right away.

Enjoy!

Frida 7.2 Released

$
0
0

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';constco=require('co');constfrida=require('frida');co(function*(){constsystemSession=yieldfrida.attach(0);yieldsystemSession.disableJit();constbytecode=yieldsystemSession.compileScript(`'use strict';    rpc.exports = {      listThreads: function () {        return Process.enumerateThreadsSync();      }    };  `);constsession=yieldfrida.attach('Twitter');yieldsession.disableJit();constscript=yieldsession.createScriptFromBytes(bytecode);yieldscript.load();constapi=yieldscript.getExports();console.log('api.listThreads() =>',yieldapi.listThreads());yieldscript.unload();}).catch(err=>{console.error(err);});

And from Python:

from__future__importprint_functionimportfridasystem_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.exportsprint("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!

Viewing all 199 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>