如何在运行时确定应用程序是用于开发、应用商店还是自定义分发?

32

有没有一种程序化的方法可以确定当前正在运行的应用程序是仅用于开发构建和签名的,还是用于发布的?能否确定它是为应用商店还是 Ad Hoc 分发而构建的?

例如,是否可以访问代码签名并从那里获取信息?或者在其中某一个变体中存在某些文件不存在于其他变体中吗?部分捆绑信息吗?或者可以从可执行文件中推导出来吗?

任何提示都将不胜感激。


看起来 embedded.mobileprovision 文件是以 ASN.1 格式存储的。

5个回答

30
最简单的检查方法是查看embedded.mobileprovision文件 ([[NSBundle mainBundle] pathForResource:@"embedded.mobileprovision" ofType:nil]):

  • 它是一个签名后的属性列表(PKCS#7 signed data,根据 openssl asn1parse -inform der),解析有些困难,但一个劣质的hack是只需搜索 <plist</plist>.
  • 开发版本包含UDIDs以及 <key>get-task-allow</key><true/>
  • Ad Hoc发布版本包含UDIDs (和 get-task-allow=false)
  • App Store发布版本不包含UDIDs。

您可以检查可执行文件中嵌入的授权信息 (otool -l命令将其列为LC_CODE_SIGNATURE)。解析这个更加繁琐(您需要解析Mach-O头和加载命令,并且对于默认的“universal”二进制文件,您需要检查当前加载的架构或所有架构)。

  • 开发版本包含<key>get-task-allow</key><true/>
  • Ad Hoc和App Store版本包含<key>get-task-allow</key><false/>

我不认为授权信息可以区分Ad Hoc和App Store版本。

除了证书,开发/Ad Hoc/App Store应用程序之间没有任何区别(授权信息/配置文件中有一些其他内容,但我无法想到更可靠的内容)。

安全注意事项

这两种方法都不那么难以规避。对于第一种方法,应用程序可以只需“swizzle” - [NSBundle pathForResource:ofType:] 。第二种方法取决于您用于读取文件的API,可能会更加困难。


非常感谢您的有用反馈。确定分布类型的原因是我想销售一个库,该库可以在开发和测试期间免费使用,但在App Store分发时需要许可证。我在Xcode构建目录中找到的embedded.mobileprovision文件是带有一些嵌入式XML的二进制文件。安装在设备上的应用程序是相同的吗?还是只安装了XML部分? - Codo
嗨Codo,我也处于同样的情况...你最终是如何实现检查的? - Andrea
1
对于内部分发,您会看到这个:<key>ProvisionsAllDevices</key> <true/> - Sveinung Kval Bakken
@SveinungKvalBakken 我猜你是指企业内部分发。我认为它可以像应用商店分发一样处理,除非你想为企业内部分发提供特殊的许可条款。 - tc.
2
谢谢!我已经将它封装在一个类别中,希望能够节省其他人的工作量:https://github.com/blindsightcorp/BSMobileProvision - Kaolin Fire

12

openssl asn1parse -inform DEM -in *Mobile_Provision_File* -strparse 54是我发现的最简单的访问数据的方式。

编辑:

security cms -D -i *Mobile_Provision_File*实际上更简单。openssl 命令会在输出中留下一些无用信息。


太棒了。这正是我长期以来一直在寻找的东西。 - Chaitanya Gupta

2

我提取了一个embedded.mobileprovision文件,并将其粘贴到在线ASN.1查看器中(例如http://www.geocities.co.jp/SiliconValley-SanJose/3377/asn1JS.html),这就是我得到的:

SEQUENCE {
   OBJECTIDENTIFIER 1.2.840.113549.1.7.2 (signedData)
   [0] {
      SEQUENCE {
         INTEGER 1
         SET {
            SEQUENCE {
               OBJECTIDENTIFIER 1.3.14.3.2.26
               NULL 
            }
         }
         SEQUENCE {
            OBJECTIDENTIFIER 1.2.840.113549.1.7.1 (data)
            [0] {
               OCTETSTRING 3c3f786d6c20766 ... 6c6973743e0a
            }
         }
         [0] {
            SEQUENCE {
               SEQUENCE {
                  [0] {
                     INTEGER 2
                  }
 ... [much more]

有了这个和一些ASN.1知识,你的解释就很合理。

有趣的部分是以3c3f786d6c开头的八位字符串。那是苹果属性列表格式中包含有关分发类型(开发人员、Ad-hoc、App Store)的所有答案的XML部分。


0

我创建了一个gist来检测Ad Hoc构建
请见:https://gist.github.com/iShawnWang/d904934efded271d83b36288562df410

以下是检测AdHoc的两个条件:

1.embedded.mobileprovision中包含字段ProvisionedDevices(调试和Ad Hoc Build包含此字段,发布版不包含)。

2.它不是DEBUG Build,我们可以使用#ifdef DEBUG来判断它。

NS_INLINE BOOL isAdHoc(){
    BOOL isAdHoc = NO;
    BOOL isDebug;

#ifdef DEBUG
    isDebug=YES;
#else
    isDebug=NO;
#endif

    NSData *data=[NSData dataWithContentsOfURL:[[NSBundle mainBundle]URLForResource:@"embedded" withExtension:@"mobileprovision"]];
    NSString *str=[[NSString alloc]initWithData:data encoding:NSISOLatin1StringEncoding];
    NSRange rangeOfDevicesUDIDs = [str rangeOfString:@"ProvisionedDevices"];

    isAdHoc = rangeOfDevicesUDIDs.location!=NSNotFound && !isDebug;
    return isAdHoc;
}

0
#if (DEBUG)
#define SERVER @"aaaa.com/dev"
#else
#define SERVER @"aaa.com/pro"
#endif

这是我区分调试模式和发布模式的方式,

但是除非使用配置文件名称,否则我对Adhoc或生产模式没有任何想法。


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