6 ms·
I'm actually very surprised this hasn't happened years ago. The power of Objective-C's runtime has always made this pretty straightforward. Apple can defend a
by makecheck 11y ago
I'm actually very surprised this hasn't happened years ago. The power of Objective-C's runtime has always made this pretty straightforward.
Apple can defend against unauthorized calls to even runtime-composed method names though. I can think of a few ways.
They could move as much "private" functionality as possible outside of Objective-C objects entirely, which requires that you know the C function name and makes it obvious when you've linked to it. This should probably be done for at least the really big things like obtaining a device ID or listing processes.
Even if they stick with Objective-C, they could have an obfuscation process internal to Apple that generates names for private methods. Their own developers could use something stable and sane to refer to the methods but each minor iOS update could aggressively change the names. If the methods are regularly breaking with each release and they're much harder to find in the first place, that may be a sufficient deterrent to other developers.
They could make it so that the methods are not even callable outside of certain framework binaries, or they could examine the call stack to require certain parent APIs. At least that way, if you want to call a private API, you have to somehow trick a public API into doing it for you.
And, I think Apple does say somewhere that developers shouldn't use leading underscores for their own APIs. They could hack NSSelectorFromString(), etc. to refuse to return selectors that match certain Apple-reserved patterns in all circumstances.
- BooneJS 11y agoWhat's so magical about Obj-C's runtime that this cannot be detected by Apple? If a third-party can scan for them, why can't Apple? If you're going to have a walled garden, by all means please ensure the walls can't be scaled or dug under.
- matthewmacleod 11y agoI'm sure they can, and will probably start doing so.
- K0nserv 11y agoAFAIK the combination of NSSelectorFromString and NSClassFromString would allow you to build and make calls from obfuscated strings during runtime. Since Objective-C uses message passing this is non trivial to catch. Compared to C were you must explicitly reference symbols that are easy to automatically check for detecting the use of third party APIs is more difficult. I am not sure if you have to explicitly link against certain frameworks/dylibs though, someone with more knowledge feel free to correct me
- uxp 11y agoThe article touches on how to dynamically link into a framework/dylib at runtime with dlopen(3) and dlsym(3) to resolve it's symbols address space. I've always wondered why Apple doesn't run all apps against a "debug" build of iOS that asserts that the caller of private APIs is itself internal/private to Apple, but instead relies on something akin to grepping the output of strings(1)
- K0nserv 11y agoThis seems like a good approach, but you can still get around it by detecting apple reviews and not doing anything with private APIs during them
- kenrikm 11y agoIt's quite trivial to setup a method that implements "NSSelectorFromString" [1] etc.. and have it read from a Json payload send from a server. It's very hard for Apple to check for that unless they have active monitoring on apps after the review process. [1] https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/Selector.html https://developer.apple.com/library/ios/documentation/Genera...
- NateLawson 11y agoRight. Any runtime behavior can be altered by observed state from outside the phone. There's even a paper on intentionally inserting security flaws into your code and then exploiting them from your own server to change execution patterns: https://www.usenix.org/conference/usenixsecurity13/technical-sessions/presentation/wang_tielei https://www.usenix.org/conference/usenixsecurity13/technical... Ultimately, you need to enforce access control instead of just trying to detect problems a priori. Apple's sandbox is a great start to that, and I expect they'll keep improving it to block apps like these.
- jandrese 11y ago
- NateLawson 11y agoWe don't know why these apps got through in particular. However, I do think we have a unique vantage point by being outside any particular app store. We scan code on both iOS and Android, identifying libraries and patterns of behavior. OpenSSL, for example, is the same code, regardless of platform, but the versions of it may vary depending on packaging and porting. We found one guy who had compiled OpenSSL for Android and was distributing binaries from github. Not the safest way to get your software. As a third-party, you can move quickly and correlate info across app stores. But I also think we've developed a pretty unique code analysis engine that neither Apple nor Google has. :-)
- mikeash 11y agoPrivate API isn't a security mechanism. Apple attempts to detect it, and reject apps that use it, purely to be friendlier to their users. Private API usage makes apps more likely to break with OS updates, and Apple doesn't want apps breaking. So while Apple is motivated to catch this stuff to an extent, they aren't that motivated, and they may well be perfectly happy with the current level of sophistication.
- joosters 11y agoDoes anyone know why they aren't access protected? It seems like poor security to just hope that apps don't call these functions.
- mikeash 11y agoDidn't I just answer that? It's not security at all, and not meant to be.
- joosters 11y agoNot really. If there are apps using these disallowed APIs, why would Apple care about breaking them if they removed access? In every case where an app is discovered using the APIs, they remove them from the app store. App compatibility is not the issue. There's still no clear reason why Apple choose to enforce the security via app reviews, rather than the system call returning 'permission denied' to apps without the right security level.
- deleted 11y ago[deleted]
- masklinn 11y ago> I'm actually very surprised this hasn't happened years ago. It has, and very early on Apple didn't check for their usage so developers started using class-dump results to look for interesting private/undocumented APIs. Things went south when Apple started checking and rejecting applications which did that: https://www.cocoanetics.com/2009/11/forbidden-fruit-apple-apis/ https://www.cocoanetics.com/2009/11/forbidden-fruit-apple-ap... The youmi stuff is creepy, but generally speaking it's more a question of there being no guarantee about these API's stability or continuity, so the application may break between even minor OS updates, which is undesirable.
- jws 11y agodlopen() can be used to call a C function by a string name. More ambitious programmers can scan executable regions of memory for the instruction stream of the target function and call the address directly without any help from symbolic names at all.
- conradev 11y agoCorrect. Even easier, they can store a hash of the symbol name and walk the dyld cache until they find a match. No dlsym required. The runtime isn't as straightforward as SourceDNA makes it seem.
- makecheck 11y agoI didn't say the function would be in a dynamic library, although you're right that this would work if it was. A statically-linked function would have to be referenced directly in the executable somewhere.
- lnanek2 11y agoIt's kind of an arms race. In the early days of iOS app development, developers would just not call the private APIs during the review period and hide them in an easter egg or enable them from the client checking with the server to see if the setting had been flipped to start using them. Ever since Apple started actually scanning the binaries developers have had to go to greater lengths to obfuscate the usage, but still give users the most powerful features. Some of the things developed during the arms race have become best practices, though. If you are an iOS game developer and you release a game update without the ability to adjust the game substantially from the server side, you are really in trouble. It takes another long review period from Apple to change anything, so best practice is to control the functionality from the server where if it makes the game too difficult for the users or something it can be adjusted without suffering the Apple review delay.
- mikestew 11y ago> I'm actually very surprised this hasn't happened years ago. It has happened years ago. About a year ago I left a company that was doing this for at least the last two or three years. Their motivations were strictly a technical workaround to get functionality that Apple didn't present to a public API, not to nefariously gather user info, but the technique is the same, and not particularly difficult to figure out. Probably a good five years ago Apple rejected an app of mine for use of a private API (this was about the time their static analysis was implemented). Another company that sold a buttload of copies of their app had to have used the same API, and their app came out a little bit before mine. Could be Apple just missed it, but I suspect the company in question was doing something similar. (They made millions, I languished in obscurity, but I'm not bitter. <g>) And those are just the ones I directly know about, or strongly suspect. I'm sure there are/were plenty more.
- Hello71 11y ago> They could move as much "private" functionality as possible outside of Objective-C objects entirely, which requires that you know the C function name and makes it obvious when you've linked to it. https://stackoverflow.com/questions/6530701/is-the-function-dlopen-private-api/24266440#24266440 https://stackoverflow.com/questions/6530701/is-the-function-...
- United857 11y agoI wonder if it's possible to for the ObjC runtime to randomly obfuscate a processes' "private" selectors on startup, and rewrite ObjC invocations within system frameworks dynamically, to make private API usage harder. Like what ASLR does for memory addresses, but for selectors.