Is there a way to determine programmatically if the currently running app was built and signed for development only or whether it was built for distribution? And can one det
The easiest way to check is to look at embedded.mobileprovision
([[NSBundle mainBundle] pathForResource:@"embedded.mobileprovision" ofType:nil]
):
openssl asn1parse -inform der
), but a bad hack is to just look for <plist
and </plist>
.<key>get-task-allow</key><true/>
The other thing you can check is the entitlements embedded in the executable (otool -l
lists it as LC_CODE_SIGNATURE
). Parsing this is even more tedious (you need to parse the Mach-O header and load commands, and for "universal" binaries which are now the default, you'll need to check the currently-loaded architecture or all architectures).
<key>get-task-allow</key><true/>
<key>get-task-allow</key><false/>
I don't think the entitlements distinguish between Ad Hoc and App Store builds.
Apart from those and the certificate it's signed with, there's no difference between Development/Ad Hoc/App Store apps (there are a few other things in the entitlements/provisioning profile, but nothing more reliable that I can think of).
Neither of these are that difficult to circumvent. For the first method, the app could just "swizzle" -[NSBundle pathForResource:ofType:]
. The second method is a bit more difficult depending on what API you use to read the file.
openssl asn1parse -inform DEM -in *Mobile_Provision_File* -strparse 54
is the easiest way to access the data that I've found.
EDIT:
security cms -D -i *Mobile_Provision_File*
is actually easier. The openssl command leaves some garbage in the output.
I create a gist to detect Ad Hoc build
See : https://gist.github.com/iShawnWang/d904934efded271d83b36288562df410
1.embedded.mobileprovision
contains field ProvisionedDevices
(Debug and Ad Hoc Build contains this field ,Release not)
2.it is not DEBUG Build , we can use #ifdef DEBUG
to decide it
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;
}
I've extracted an embedded.mobileprovision file and pasted into an online ASN.1 viewer (e.g. http://www.geocities.co.jp/SiliconValley-SanJose/3377/asn1JS.html), and that's what a got:
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]
With this and some ASN.1 knowledge, your explanation makes perfect sense.
The interesting part is the octet string starting 3c3f786d6c. That's the XML part in Apple's property list format that contains all the answers about the distribution type (developer, ad-hoc, App Store).
#if (DEBUG)
#define SERVER @"aaaa.com/dev"
#else
#define SERVER @"aaa.com/pro"
#endif
that's the way i distinguish the debug and release mode ,
but i have no idea for adhoc or production unless use the provision profile name