苹果是如何知道你是否使用了私有API?

115

我向苹果提交了一个没有源代码的二进制文件。

除了手动检查源代码外,苹果如何知道您使用了什么以及调用了哪些API?


更改标题 - 我想你的意思是“苹果是如何知道…” - Anurag
10个回答

184

我知道3种方法,但这些只是一些猜测,因为我不在苹果审核团队工作。

1. otool -L

此命令将列出应用程序链接到的所有库。可以通过此方法检测是否使用了明显不应使用的库,例如 IOKit 和 WebKit。

2. nm -u

此命令将列出所有链接的符号。可以检测以下内容:

  • 未经记录的 C 函数,例如 _UIImageWithName;
  • Objective-C 类,例如 UIProgressHUD;
  • 实例变量,例如 UITouch._phase (可能是导致最近几个月基于 Three20 的应用程序被拒绝的原因)。

3. 列出 Objective-C 选择器或 strings

Objective-C 选择器存储在二进制文件的特殊区域中,因此 Apple 可以从那里提取内容,并检查您是否使用了一些未经记录的 Objective-C 方法,例如 -[UIDevice setOrientation:]

由于选择器与您发送消息的类无关,即使您的自定义类定义了与 UIDevice 无关的 -setOrientation:,也有可能被拒绝。


您可以使用 Erica Sadun 的 APIKit 来检测由于(误报)私有 API 而导致的潜在拒绝。


(如果您真的真的真的想规避这些检查,可以使用运行时功能,例如

  • dlopen、dlsym
  • objc_getClass、sel_registerName、objc_msgSend
  • -valueForKey:; object_getInstanceVariable、object_getIvar 等

来获取那些私有库、类、方法和实例变量。)


很棒的答案。我只想补充一点,如果你的应用程序在没有使用私有API的情况下做某些极其困难的事情,我相信你的应用程序会受到额外的审查。 - Matthew Frederick
1
我想知道为什么你说不应该链接IOKit和WebKit? - hjaltij
3
你需要在什么文件上执行otool命令?是.app文件吗? - serverpunk
苹果难道不能编译一个带有保护机制的iOS版本,然后在上面运行你的应用程序吗? - Eric
1
@Eric,他们可以,尽管这样的工具版本可能会影响性能。无论如何,看到私有API不断进入应用商店,很明显他们没有这样做,或者至少并不总是这样做。 - Nate
显示剩余6条评论

26

您可以使用以下一行代码在终端中列出Mach-O程序中的选择器:

otool -s __TEXT __objc_methname "$1" |expand -8 | cut -c17- | sed -n '3,$p' | perl -n -e 'print join("\n",split(/\x00/,scalar reverse (reverse unpack("(a4)*",pack("(H8)*",split(/\s/,$_))))))'

+1,@Robert Diamond,您能否更详细地描述一下相同的内容。 我需要检查Google分析是否使用UDID调用。谢谢。 - Mangesh

13

假设你想要使用一些私有API;Objective-C允许你从一个字符串构造任何SEL:

   SEL my_sel = NSSelectorFromString([NSString stringWithFormat:\
@"%@%@%@", "se","tOr","ientation:"]);
    [UIDevice performSelector:my_sel ...];

一个机器人或库怎样扫描捕捉这个问题?他们需要使用某种在运行时监视私有访问的工具来捕捉这个问题。即使他们构建了这样的运行时工具,也很难捕捉,因为这个调用可能被隐藏在一些很少被执行的路径中。


user1203764 评论 这些类型的调用实际上是可以被检测到的。 - Rup
@Rup可以在这里发表一下关于使用valueForKey的看法吗?有关访问UIBarButton项目的私有API违规问题https://dev59.com/kGfWa4cB1Zd3GeqPejBu - Dan Rosenstark
1
@Yar 有趣的问题!但是我不够专业,无法发表评论,抱歉。Farcaller所说的似乎对我来说是合理的。 - Rup
谢谢 @Rup,在这个领域似乎没有足够的专家 :) - Dan Rosenstark
我认识的某个人说他刚刚接到了这样一个来自App Store的电话。 - bugloaf
当然,使用NSSelectorFromString可能会引起苹果审核人员的怀疑,如果是这样的话 - 他可以使用其他工具来重构原始代码(反汇编)并理解使用的原始意图。 - Motti Shneor

7

我想他们会查看您的二进制文件尝试导入的所有符号(无疑在其中的符号表中很容易获得信息),如果发现这些符号中有任何一个在他们的“私有API列表”中,则会对您进行警告。实际上非常容易自动化。


1
实际上,我可以肯定地说这不是事实(至少不是他们所做的全部),因为我知道已经通过私有API使用。如果只需要这些,私有API使用就不会滑过去。我的经验表明,KennyTM的答案几乎肯定是正确的。这是Objective-C与其他语言(如C)根本不同的领域。 - Nate

1
一个可执行文件并不完全是一个黑盒子。如果你调用了一个库,那么它很容易被找到。这就是为什么我对现代计算机科学教育中汇编语言的消失感到遗憾。像ldd这样的工具可以告诉你链接了什么,尽管我不记得哪个版本的ldd适用于Mac iPhone开发套件。

1
我经常想知道:如果你编写的二进制文件进行自修改,只有在满足某些条件后(比如应用程序发布日期之后)才生成导入私有API的代码,那么苹果是否会发现它。他们肯定会向我们报告一些有趣的统计数据,比如在越狱手机上运行我们游戏的数量。 - Sniggerfardimungus
@user30997,特权代码可能只能通过系统调用访问;执行线程切换到更高的特权级别,并检查先前的特权是否有权限执行代码。这只是一个例子,还有其他方法可以实现,但我非常怀疑开发人员会天真到遗漏基本的运行时特权检查机制,否则它肯定已经被公开了。 - L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳

1
otool -L somebinary

1
除了符号调查之外...
苹果很容易拥有一个版本的SDK,在调用每个私有方法堆栈时检查,以确保它是从指定的方法之一输入的。

这还不够,因为程序只能在将来的任意时间根据其他逻辑调用此私有调用。要做到这一点,苹果必须完全阻止私有 API,或者让框架自动向苹果报告私有 API 调用-这会严重损害性能。 - Motti Shneor

0
即使您是静态链接,最坏的情况也是他们可以从私有API列表中取样代码,并将您的二进制文件与它们进行比对(这也相对容易自动化)。
了解苹果公司,我敢打赌他们拥有全面的自动化系统,任何不确定性可能要么被否认,要么被手动审核。
总之,我认为试图愚弄苹果公司可能并不值得努力。

4
了解苹果公司的审查过程,当遇到任何不确定情况时,他们会拿出一组骰子来增加趣味性。 - JUST MY correct OPINION

0

有很多逆向工程工具可以用来检查代码

  • nm - 列出目标文件中的符号
  • objdump - 显示目标文件的信息。
  • otool - 查看 Mach-O[关于] 可执行文件的内容
  • strings - 这将获取所有字符串。

您可以在 Objective-CSwift 的 gists 中找到使用这些命令的示例/表示


0
这个桌面应用程序 App Scanner 可以通过拆分 Mach-O 二进制文件来扫描 .app 文件中的私有 API 使用情况。如果它可以做到,那么苹果也可以!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接