為什么要應(yīng)用完整性校驗(yàn)
大家可能聽過(guò)馬甲包類似的概念搔驼。如果惡意攻擊者搞你的App,直接換個(gè)App Icon疙渣,App名字 以及皮膚直接上架了就很尷尬了匙奴。
怎么做
從安全攻防角度講,你了解攻擊的方式妄荔,更容易知道怎么防泼菌,但是也是相對(duì)而言谍肤,只是不斷消磨攻擊者的意志,但愿他們放棄哗伯。
方式一:越獄檢測(cè)
這種方式最簡(jiǎn)單暴力荒揣,我們可以檢測(cè)當(dāng)前設(shè)備是否越獄,在關(guān)鍵性業(yè)務(wù)判斷給出提示強(qiáng)制退出以免造成安全問題焊刹,這里的關(guān)鍵性業(yè)務(wù)可能是需要自己定義范圍系任,比如牽扯到用戶敏感信息等業(yè)務(wù)。下面貼出關(guān)鍵性代碼:
const char* jailbreak_tool_pathes[] = {
"/Applications/Cydia.app",
"/Library/MobileSubstrate/MobileSubstrate.dylib",
"/bin/bash",
"/usr/sbin/sshd",
"/etc/apt"
};
#define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0])
+ (BOOL)isJailBroken
{
if ([self isSimulator] == YES)
{
return NO;
}
for (int i=0; i<ARRAY_SIZE(jailbreak_tool_pathes); i++) {
if ([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithUTF8String:jailbreak_tool_pathes[i]]]) {
NSLog(@"The device is jail broken!");
return YES;
}
}
NSLog(@"The device is NOT jail broken!");
return NO;
}
+ (BOOL)isSimulator {
#if TARGET_OS_SIMULATOR
return YES;
#else
return NO;
#endif
}
這種方式其實(shí)是非常間接的方式避免了這個(gè)話題
方式二:判斷Mach-O文件否被篡改
通過(guò)檢測(cè)SignerIdentity判斷是Mach-O文件否被篡改虐块。原理是:SignerIdentity的值在info.plist中是不存在的俩滥,開發(fā)者不會(huì)加上去,蘋果也不會(huì)贺奠,只是當(dāng)ipa包被反編譯后篡改文件再次打包霜旧,需要偽造SignerIdentity。所以只要被攻擊篡改東西如果重新運(yùn)行到手機(jī)上就會(huì)出現(xiàn)這個(gè)東西儡率。
+ (BOOL)checkMach_O
{
NSBundle *bundle = [NSBundle mainBundle];
NSDictionary *info = [bundle infoDictionary];
if ([info objectForKey: @"SignerIdentity"] != nil){
//存在這個(gè)key挂据,則說(shuō)明被二次打包了
return YES;
}
return NO;
}
方式三:重簽名檢測(cè)
由于要篡改App必然重簽名,至于為什么重簽名儿普,是因?yàn)樘O果做了校驗(yàn)改動(dòng)了任何東西校驗(yàn)失敗是直接閃退的崎逃,其實(shí)原理也是校驗(yàn)文件的hash值。簽名打包過(guò)程會(huì)出現(xiàn)這個(gè)embedded.mobileprovision文件眉孩,這個(gè)文件有teamID的一個(gè)東西我們可以校驗(yàn)是否是我們自己的團(tuán)隊(duì)的teamID來(lái)判斷个绍。或者判斷BundleID 是否被修改勺像。
+ (BOOL)checkCodeSignWithProvisionID:(NSString *)provisionID
{
// 描述文件路徑
NSString *embeddedPath = [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"];
if ([[NSFileManager defaultManager] fileExistsAtPath:embeddedPath]) {
// 讀取application-identifier
NSString *embeddedProvisioning = [NSString stringWithContentsOfFile:embeddedPath encoding:NSASCIIStringEncoding error:nil];
NSArray *embeddedProvisioningLines = [embeddedProvisioning componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
for (int i = 0; i < [embeddedProvisioningLines count]; i++) {
if ([[embeddedProvisioningLines objectAtIndex:i] rangeOfString:@"application-identifier"].location != NSNotFound) {
NSInteger fromPosition = [[embeddedProvisioningLines objectAtIndex:i+1] rangeOfString:@"<string>"].location+8;
NSInteger toPosition = [[embeddedProvisioningLines objectAtIndex:i+1] rangeOfString:@"</string>"].location;
NSRange range;
range.location = fromPosition;
range.length = toPosition - fromPosition;
NSString *fullIdentifier = [[embeddedProvisioningLines objectAtIndex:i+1] substringWithRange:range];
// NSLog(@"%@", fullIdentifier);
NSArray *identifierComponents = [fullIdentifier componentsSeparatedByString:@"."];
NSString *appIdentifier = [identifierComponents firstObject];
// 對(duì)比簽名ID
if (![appIdentifier isEqual:provisionID])
{
return NO;
}
else
{
return YES;
}
}
}
}
return YES;
}
了解簽名的原理有利于防止App被重簽名障贸。
方式四:關(guān)鍵資源hash值檢測(cè)
我們對(duì)Plist文件以及App 的icon資源文件做hash值校驗(yàn)。網(wǎng)上一些對(duì)_CodeSignature的CodeResources以及App二進(jìn)制文件的校驗(yàn)做法有問題吟宦。因?yàn)閄code打包過(guò)程不同環(huán)境造成的hash值不一樣篮洁,通過(guò)下圖可以看出不同環(huán)境打包過(guò)程造成的hash值不一樣的選項(xiàng)。所以我們必須過(guò)濾掉變化的文件殃姓。檢測(cè)Plist文件以及App Icon資源文件這些東西袁波。
//生成資源文件名及對(duì)應(yīng)的hash的字典
+(NSDictionary *)getBundleFileHash{
NSMutableDictionary * dicHash = [NSMutableDictionary dictionary];
NSArray * fileArr = [self allFilesAtPath:[[NSBundle mainBundle]resourcePath]];
for (NSString * fileName in fileArr) {
//對(duì)應(yīng)的文件生成hash
NSString * HashString = [FileHash md5HashOfFileAtPath:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:fileName]];
if (HashString != nil) {
[dicHash setObject:HashString forKey:fileName];
}
}
//所有資源文件的hash就保存在這數(shù)組里
return dicHash;
}
有些加密工具為了放進(jìn)加固SDK放在了本地校驗(yàn),但是通過(guò)服務(wù)器校驗(yàn)比較安全點(diǎn)蜗侈。
總結(jié):
通過(guò)下面鏈接了解:
- Xcode build 對(duì)二進(jìn)制文件以及_CodeSignature的CodeResources造成變化的原理篷牌。
LLVM怎么做Deterministic Build
- 簽名的原理
iOS逆向(五)-ipa包重簽名