有没有一种程序化的方法可以确定当前正在运行的应用程序是仅用于开发构建和签名的,还是用于发布的?能否确定它是为应用商店还是 Ad Hoc 分发而构建的?
例如,是否可以访问代码签名并从那里获取信息?或者在其中某一个变体中存在某些文件不存在于其他变体中吗?部分捆绑信息吗?或者可以从可执行文件中推导出来吗?
任何提示都将不胜感激。
看起来 embedded.mobileprovision 文件是以 ASN.1 格式存储的。
embedded.mobileprovision
文件 ([[NSBundle mainBundle] pathForResource:@"embedded.mobileprovision" ofType:nil]
):
openssl asn1parse -inform der
),解析有些困难,但一个劣质的hack是只需搜索 <plist
和 </plist>
.<key>get-task-allow</key><true/>
您可以检查可执行文件中嵌入的授权信息 (otool -l
命令将其列为LC_CODE_SIGNATURE
)。解析这个更加繁琐(您需要解析Mach-O头和加载命令,并且对于默认的“universal”二进制文件,您需要检查当前加载的架构或所有架构)。
<key>get-task-allow</key><true/>
<key>get-task-allow</key><false/>
我不认为授权信息可以区分Ad Hoc和App Store版本。
除了证书,开发/Ad Hoc/App Store应用程序之间没有任何区别(授权信息/配置文件中有一些其他内容,但我无法想到更可靠的内容)。
这两种方法都不那么难以规避。对于第一种方法,应用程序可以只需“swizzle” - [NSBundle pathForResource:ofType:]
。第二种方法取决于您用于读取文件的API,可能会更加困难。
openssl asn1parse -inform DEM -in *Mobile_Provision_File* -strparse 54
是我发现的最简单的访问数据的方式。
编辑:
security cms -D -i *Mobile_Provision_File*
实际上更简单。openssl 命令会在输出中留下一些无用信息。
我提取了一个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部分。
我创建了一个gist来检测Ad Hoc构建
请见:https://gist.github.com/iShawnWang/d904934efded271d83b36288562df410
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;
}
#if (DEBUG)
#define SERVER @"aaaa.com/dev"
#else
#define SERVER @"aaa.com/pro"
#endif
这是我区分调试模式和发布模式的方式,
但是除非使用配置文件名称,否则我对Adhoc或生产模式没有任何想法。
<key>ProvisionsAllDevices</key> <true/>
- Sveinung Kval Bakken