Microsoft Azure customers gain access to NowSecure Mobile App Security and Privacy Testing for scalability, reliability, and agility of Azure to drive mobile appdev and shape business strategies.

Media Announcement
magnifying glass icon

iOS 9 Reverse Engineering with JavaScript

Posted by

Ole André Vadla Ravnås

Security Researcher at NowSecure
Ole is the creator of Frida, an open-source tool for performing dynamic instrumentation of mobile apps, and indulges his passion for reverse-engineering as a security researcher at NowSecure.
iOS 9 Reverse Engineering with JavaScript

Frida 6.0, released this week, includes brand new support for iOS 9. Whether you’re doing security research on apps or system services, or you’re an app developer wanting to trace API calls, this new release has got you covered.

As some of you may know, Frida can inject V8 into any process, on both desktop and mobile. This JavaScript runtime that Frida injects is conceptually just a language binding for Frida’s instrumentation engine, frida-gum. Beside letting you enumerate threads, loaded modules, hook arbitrary functions, call native APIs, etc., all implemented in C and assembly, there are also the ObjC and Java modules written in pure JavaScript. These leverage the aforementioned low-level primitives to give you easy access to the higher-level internals of any app or system service.

Now with Pangu’s iOS 9 jailbreak and Apple’s Kernel Patch Protection, it looks like we’ll have to live without some of the kernel adjustments that were common in earlier jailbreaks. Among them was the patch lifting Apple’s ban on RWX (Read-Write-Execute) memory pages, and this happens to be an important feature that the V8 engine was designed to take advantage of.

This was a challenge for Frida, depending on V8 for its JS runtime, but also a long-standing issue preventing us from instrumenting apps on non-jailbroken devices, where one could otherwise just repackage the app with Frida included and instrument away.

I am super-excited to announce that after weeks of coding here at NowSecure, with countless cups of coffee consumed, we are no longer dependent on V8. Yes, with Frida 6.0 we have a brand new JavaScript runtime based on JavaScriptCore. This is a system framework, so we don’t even have to add that to our binary footprint. We do however still use V8 on other OSes, and kernels that support RWX pages, but it is no longer our Achilles heel. Plus, Frida will soon be seen instrumenting apps on non-jailbroken devices.

So, that’s iOS. What else is new? Something that kept coming up when building tools on top of Frida is that it would be very useful to collect details about the system you’re instrumenting. Perhaps what kind of OS, architecture, IP addresses of network interfaces, etc. Exactly what kind of details are necessary really depends on the needs of your tool, and it doesn’t really make sense to add all possible system information to Frida’s APIs. There would always be something missing, and for everybody else there would be a lot of unnecessary complexity. Now with Frida 6.0 we have finally solved this. All you have to do is attach to pid 0, and you get a so-called system session running inside Frida itself. Scripts that you create here can inspect Process.platform, Process.arch, etc., or use NativeFunction to call an OS API, like say, for enumerating network interfaces.

Beside these features, improved injection capabilities on OS X El Capitan, REPL improvements and many bug-fixes, this release also improves Frida’s function hooking. That part is however a story of its own, but here’s the TLDR for the technically curious: We added support for relocating more position-dependent instructions, and even take great care to allow you to hook functions that happen to reside in the libc. The challenge there is that with iOS 9, and other systems that don’t permit RWX pages, for Frida to modify a function in order to hook it, it has to flip the memory page that it’s on to RW (read-write), perform the modification, then flip it back to RX (read-execute). If, however, the function to be modified happens to fall on the same page as the libc function we use to change the page protection, then we obviously can’t call it, as it’s not currently executable. The solution is to perform that system-call ourselves.

I hope you enjoy this new release, and if you do please help spread the word! 🙂 If for some reason Frida doesn’t work for you, please do get in touch.