An Alternative Approach

This post is an overview of an alternative approach to attaching Reveal or Spark to third party apps on a jailbroken device. Peter Steinberger posted a blog post demonstrating how this works using MobileSubstrate. Unfortunately, this approach didn’t work for me and a few others that shared my woes via Twitter.

As Peter said in his blog post, the iOS7 jailbreak will allow us to attach the debugger to 3rd party apps in order to study the view heirarchy of complex apps. This will provide developers with insight to how others have approached similar problems.¹

Jailbreak + Setup

Although Peter’s post can get you 90% of the way, I’ll reiterate his steps here to save you an extra tab in your browser.

  1. I jailbroke my iPad 3 using the 1.0.1 version of evasi0n’s app.
  2. Be sure to install OpenSSH. Once installed, make sure you can ssh into your device via ssh root@ using the default password alpine. Obviously you should replace this example IP address with your device’s wifi address.
  3. Next, we’ll copy our libReveal.dlylib and our libSpark.dlyib files onto our device. It doesn’t really matter where the files are copied to on the device, but since I started down the path of using MobileSubstrate, I ended up copying both files to its DynamicLibraries directory: scp /Applications/ root@ and scp "/Applications/Spark" root@

Beyond this, if Mobile Substrate works for you, then there is no need to go any further. But for the rest of us, we’ll have to resort to other options.


Thankfully, it is possible to perform code injection using the dynamic linker. Using the environment variable DYLD_INSERT_LIBRARIES, we can inject Reveal and/or Spark into 3rd party applications on the device. According to the man page, this environment variable is:²

    This  is  a colon separated list of dynamic libraries to load before the ones specified in the
    program.  This lets you test new modules of existing dynamic shared libraries that are used in
    flat-namespace images by loading a temporary dynamic shared library with just the new modules.
    Note that this has no effect on images built a two-level  namespace  images  using  a  dynamic
    shared library unless DYLD_FORCE_FLAT_NAMESPACE is also used.

Knowing this, all we need to do is set the environment variable to our dylib path and we will be good to go. To inject Reveal, copy this into your ssh terminal.

launchctl setenv DYLD_INSERT_LIBRARIES /Library/MobileSubstrate/DynamicLibraries/libReveal.dylib
launchctl setenv DYLD_FORCE_FLAT_NAMESPACE ''

As of this post, Reveal is having trouble attaching to and inspecting Springboard. Thankfully, Spark Inspector is able to take on the load of Springboard, so if you wish to inject both libraries, you can also do that by using a colon separated list of libraries.

launchctl setenv DYLD_INSERT_LIBRARIES /Library/MobileSubstrate/DynamicLibraries/libReveal.dylib:/Library/MobileSubstrate/DynamicLibraries/SparkInspector.dylib
launchctl setenv DYLD_FORCE_FLAT_NAMESPACE ''

Once you have this set, that’s really all you need to do. Launch an app to get started. If you want to inspect Springboard you’ll have to restart the device first. I use sbreload from the UIKitTools Cydia package, but killall SpringBoard should work too.

The good thing about this approach is that it doesn’t require MobileSubstrate and it works on ARM and ARM64, as verified via Twitter.