42

The iOS app Display Recorder claims to be able to record the screen of an iOS device, even while it is in the background. Given that UIGetScreenImage() is private API and will lead to a rejection on application submission when detected by the static analysis Apple runs, how were they able to do this recording in an approved application?

Additionally, the app causes a red bar to appear at the top of the screen while it records, similar to the native iOS's phone call functionality.

I've been an iOS developer for awhile, and I'm a bit stumped at how this was even done, even down to the detail of putting the red bar at the top when outside of the app. I was under the impression we basically had no control of what's happening when the app runs in the background, short of some key pieces of functionality (like audio playing, etc).

Even if the developer tapped into private API/libraries to accomplish this, how were they able to do this in a way that wasn't detected during review? My apologies if I'm missing something obvious that was introduced with a later version of iOS here.

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
svguerin3
  • 2,433
  • 3
  • 29
  • 53
  • Magic/Bribes/.... I suspect that app is manically taking screenshots and compositing them. That app is gonna get yanked out, and fast, anyhow. – CodaFi Jun 18 '12 at 20:03
  • 3
    How was it approved???? Depends on the alignment of the planets! The current phase of the moon, etc.... The approval process at Apple is top secret and seemingly random sometimes. An app that was accepted a month ago may be rejected today and vice versa. Like rooster117 said: they may have gotten really lucky – PaulG Jun 18 '12 at 20:03
  • I've had apps approved and rejected on updates. They may have gotten really lucky. I downloaded it myself and it's really poor quality. It felt like 1fps and I was trying to record an app with video and it just didn't record the video at all so I agree that its probably screen shots put together to make a video. Also its recording sound through the mic which may be how they are able to get it approved and run in the background. – rooster117 Jun 18 '12 at 20:05
  • Agreed, I'm surprised it was approved as well. I definitely know how to take screenshots like crazy from the Obj-C code (within the app), but I didn't know it would or even 'could' continue to take screenshots when the app suspends? Also, how was the red bar added? If all this is possible, why don't we see more apps out there that do screen capturing outside of an app, or apps that have overlays on the homescreen of the device? This app could theoretically be running background threads to send videos to unknown sources.. I'm just blown away that this was approved. – svguerin3 Jun 18 '12 at 20:08
  • 1
    Quick follow-up, I see the red bar comes natively when audio is being recorded, sorry for my oversight there. Still amazed this passed through Apple's gates, though. – svguerin3 Jun 18 '12 at 20:15
  • Someone's getting fired over there for sure... I wonder if they somehow are retaining a global CG context for those screen grabs... – CodaFi Jun 18 '12 at 20:19
  • Is it possible to record an IOSurface? That might be how it works. Im surprised that it car record audio because the jb app "Display Recorder" cannot do that. – C0deH4cker Jun 18 '12 at 20:21
  • 2
    I need to find out who that reviewer was. Maybe I can get him/her to approve my apps as well. – Dancreek Jun 18 '12 at 20:30
  • I got it too, and even though it's way above 1fps (at least in the captures I've tried, it's still way below 30 fps. – Nicolas Miari Jun 23 '12 at 02:24
  • Just learned that this app was on the "New and Noteworthy" page of the AppStore in some countries. They have no idea... – C0deH4cker Jun 23 '12 at 03:52

2 Answers2

61

Looked into it and it doesnt link against IOSurface. I did however find that it uses dlsym, and after some more reverse engineering, I found this:

/System/Library/Frameworks/IOKit.framework/IOKit
IOServiceGetMatchingServices
IOServiceGetMatchingService
IOServiceMatching
IOMasterPort
IOIteratorNext
IORegistryEntryCreateCFProperty
IOObjectRelease
/System/Library/Frameworks/UIKit.framework/UIKit
UIGetScreenImage
/System/Library/PrivateFrameworks/IOMobileFramebuffer.framework/IOMobileFramebuffer
IOMobileFramebufferOpen
IOMobileFramebufferGetLayerDefaultSurface
/System/Library/PrivateFrameworks/IOSurface.framework/IOSurface
IOSurfaceAcceleratorCreate
IOSurfaceAcceleratorTransferSurface
IOSurfaceLock
IOSurfaceUnlock
IOSurfaceGetWidth
IOSurfaceGetHeight
IOSurfaceCreate
IOSurfaceGetBaseAddress

So, as you see here, after each framework path are the strings of the symbols that it loads from each framework, dynamically. This is to avoid getting in trouble for linking against a Private Framework. Since it is loaded in at runtime, a static analyzer cannot tell that this app uses it, thereby escaping detection.

It does look like my initial suspicion was correct; it is using IOSurface to sneak past sandbox restrictions to have raw screen access. It also uses UIGetScreenImage, which I assume is for the second method of generating video. It also uses some IOKit functions and IOMobileFramebuffer functions. It looks like the app is grabbing an IOSurface from the IOMobileFramebufferGetLayerDefaultSurface function. Not quite sure what it uses IOKit for though.

In conclusion, this app uses some sneaky techniques to avoid detection by static analyzers: it doesn't link against the private frameworks but instead grabs the symbols dynamically. It uses a combination of IOSurface and IOMobileFramebuffer to record the video, or UIGetScreenImage for the other mode. It is a tricky app that WILL get pulled from the AppStore, so if you want it, you better get it now.

UPDATE:

It appears that this app was indeed pulled from the AppStore. If you were lucky enough to grab a copy before it was pulled, that's great. I know that I'm glad I got it.

Apple probably justified its decision by stating that the app used private APIs and it could be viewed as a potential security problem (an app that watches you as you type in your iTunes password is one example, scary thought). I wonder if this will lead to a change in their reviewing process, but we will likely never know. One thing that is interesting to me is that there are still many more tricks developers could potentially use to hide their app's behavior from static analysis. No reviewing process is perfect, but they can do pretty well. Even if Apple automatically refuses apps that link against the dlsym symbol, there are methods that can be used to bypass detection.

UPDATE 2:

Apparently, there is another version of this application in the AppStore now. It is called "Disp Recorder" and has the same exact icon as the first. The GUI looks almost identical to the original one with a few minor changes. I haven't yet reversed the newer one, but I'd be willing to bet that they used the same techniques to hide the illegal behavior. I will update this answer once I reverse the new version. The new one costs $5, but if you have ever wanted a screen recording app on an unjailbroken device, you should grab it before it is pulled.

UPDATE 3:

It looks as if I was very much correct with how this application works. There is an open-source implementation of this on GitHub by @coolstarorg called RecordMyScreen. If you still wonder how this app works, I suggest you go check it out.

C0deH4cker
  • 3,959
  • 1
  • 24
  • 35
  • 13
    And please, nobody ask me or anybody else to send a copy of the app. That is piracy and I do not condone piracy at all. – C0deH4cker Jul 05 '12 at 04:42
  • Great work, and +1 for the comment about piracy (too much association of reverse engineering with stealing). Just FYI, simply loading private frameworks dynamically with `dlopen` and then using `dlsym` is not generally enough to avoid Apple's detection of private API usage, although that may get you past Xcode's (Organizer) pre-submission **validate** step. – Nate Jul 10 '12 at 21:05
  • seems like it was removed and reposted again. this time as «Dpl Recorder» https://itunes.apple.com/de/app/dpl-recorder/id585152395?mt=8 – vikingosegundo Dec 12 '12 at 03:42
  • @vikingosegundo And this time for $10. I wonder if it's the same developer posting it multiple times or just random people ripping it off. I'm not about to spend another $10 on this just to reverse engineer the app to see what tricks it uses to avoid detection. I'll update the answer with the tiny bit of info that I learned from quickly reversing the second iteration of the app. – C0deH4cker Dec 12 '12 at 04:55
  • @C0deH4cker The link to the implementation you have given uses the API CARenderServerRenderDisplay which might have an impact on performance. You did a great job in reverse engineering the display recorder app and finding out the API's used. As we can see, these API's give complete control to the developer over the IOSurface and hence, improve performance. On the contrary, RecordMyScreen uses a higher level API, just like the _createScreenIOSurface API which can as well be used. – Hrishikesh_Pardeshi Jan 11 '13 at 13:54
  • 3
    @C0deH4cker +1 for not being a script kiddie and actually being true to your username – Zoltán Matók Jan 04 '14 at 17:52
  • Most private screen-recording APIs have been forbidden on iOS 9+ , but someone has found a new solution [here](https://github.com/xindawndev/RecordMyScreen-iOS10) (not open sourced), It seems to use airplay protocol. Are you interested? – Grey Oct 26 '16 at 03:03
  • and I've found unofficial airplay protocol specification [here](http://nto.github.io/AirPlay.html) and [here](https://github.com/jamesdlow/open-airplay) – Grey Oct 26 '16 at 03:15
13

@C0deH4cker's suggestion of the IOSurface framework is just crazy enough to work. IOSurface provides a kernel interface (allowing an app to slip out of its sandbox quietly), for a rectangular pixel buffer (screen grabs), that can be converted to a CGImage or UIImage using framework-related methods.

Even apple suggests that the framework's raison d'être is to:

Contain low-level interfaces for sharing graphics surfaces between applications.

Best part is, it's not legal in iOS. The framework used to be called CoreSurface in iOS 2.x, which was quickly and quietly deprecated in 3.x, only to be replaced by iOSurface. I guess the fact that it's private and unlisted in the iOS references meant that the app store testers didn't test for it. Interesting.

CodaFi
  • 43,043
  • 8
  • 107
  • 153
  • 4
    I downloaded the app on both my iphone and ipad. Gonna do some reversing later to figure this out. Will inform you of my findings in the morning (tired at 2 am). – C0deH4cker Jun 19 '12 at 05:59
  • APIs being private and unlisted does not mean that testers don't test for it. Every review process has its flaws, but Apple's is not that flimsy. – Nate Jul 10 '12 at 21:02
  • Yes, but clearly they were this time. At the time of your writing, they pulled it. I'm willing to admit that this was merely a slip-up, but there is also the strong possibility they simply forgot to test for this lib. – CodaFi Jul 10 '12 at 21:04
  • Not necessarily (*"clearly they were this time"*). The fact that the app got through does not necessarily mean that Apple reviewers didn't test for it. It may have been heavily obfuscated by the developer (above and beyond simply avoiding direct linkage, and using `dlopen` and `dlsym`). Developers have gone to great lengths to foil Apple's detection of private API usage. – Nate Jul 11 '12 at 07:43