Cannot bind() a socket inside Apple Calendar (dylib injection)

1.3k views Asked by At

I’m trying to inspect iOS 8.1's Apple Calendar (MobileCal.app) on Reveal following this guide.

For that, I’m injecting libReveal.dylib which launches its own HTTP server to which the OS X Reveal app connects to.

This technique works fine with most of iOS system apps (Phone, Notes, Reminders, etc.) but something in Calendar is preventing the HTTP server from being set up.

When Calendar is run, libReveal.dylib is properly injected, but then I see this on the log:

MobileCal[5110] : ERROR: Error starting HTTP Server: Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted" UserInfo=0x17426aa40 {NSLocalizedDescription=Operation not permitted, NSLocalizedFailureReason=Error in bind() function}

MobileCal[5110] : ERROR: Reveal server failed to start with error: Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted" UserInfo=0x17426aa40 {NSLocalizedDescription=Operation not permitted, NSLocalizedFailureReason=Error in bind() function}

Any ideas about what could be stopping the HTTP server from being set up within Calendar? I have noticed that the MobileCal.app bundle has an Entitlements.plist file, whereas most of the other system apps don't. May this issue be related to the entitlements file?


I also contacted Reveal support, they were responsive, but could not pinpoint what is causing of the problem. Using RevealLoader from Cydia produces the same result.

1

There are 1 answers

2
creker On BEST ANSWER

You're right about Entitlements.plist. Problem is very simple - MobileCal.app is using custom sandbox profile.

There are actually many sandbox profiles in iOS, not just for AppStore apps. Many iOS system components use them. To know which one you need to look at the app's entitlements. More specifically, seatbelt-profiles key.

MobileCal.app is signed with MobileCal profile. And this is exactly why you can't use bind(). I suspect all networking is blocked. Same can be said about Camera.app. It uses MobileSlideShow profile which also blocks all networking.

I can think of and actually used two solutions to this problem:

  1. Write a daemon. Daemon will do all the work that's blocked by sandbox profile. App and daemon will communicate through some IPC API (like notifications or mach ports). Main problem with this - IPC API could also be blocked by sandbox profile. For example, Camera.app sandbox blocks all IPC APIs that could send arbitary data. Only Darwin notifications work which can't send arbitary data. There are ways to solve this but it will be very ugly.

  2. Resign the app with sandbox profile removed. That way the app will have access to everything and you can do all the work inside your injected dylib. This is what I use now and it works very well. It's also kind of hack but it significantly improves your code by not having to deal with IPC and it's complexity. For me it worth it.

That's all in general. For your I case I think only the second solution will work.

Of cource, just editing Entitlements.plist is not enough. Actual entitlements are in app's binary itself. You can resign either on your mac or on iDevice itself. On mac you have a choice of codesign and ldid. On iDevice your only choice is ldid.

Let's look at how you can solve your problem with ldid. First, you dump entitlements with

ldid -e MobileCal > entitlements.xml

Then you edit dumped entitlements and resign the app binary with

ldid -Sentitlements.xml MobileCal

(Yes, there is no space between -S and entitlement file).

That's it.