ios 越狱与安全性分析

通过看一些文档发现越狱有风险,但是风险还是在可控范围内的,所以touchid用于交易还是可行的。

一越狱存在的问题

理论上iPhone越狱没有安全性可言,所有安装在你手机的APP都以root权限运行,它们可以

•任意读写文件系统数据

•HTTP(S)实时被监测

•重新打包ipa

•暴露的函数符号

•未加密的静态字符

•篡改程序逻辑控制流

•拦截系统框架API

•逆向加密逻辑

•跟踪函数调用过程(objc_msgSend)

•可见视图的具体实现

•伪造设备标识

•可用的URL schemes

runtime任意方法调用

以上安全风险都基于一个前提:安装了一个恶意APP或插件。所以只要自己注意不要下载到这些东西就不会有问题。越狱后不知名的APP就不要下了,特别是那些只有盗版市场有的APP。不知名的盗版市场最好也不好用,cydia的源不要随意添加,下载插件要谨慎。

另外实际上AppStore上的APP在越狱环境下也不是绝对安全的,因为苹果也检测不到这些APP有没有做以上那些不轨之事。对于在盗版市场下载知名APP,似乎跟在AppStore上下载没区别,目前没见到有安装包被注入程序,不像Android市场。像支付宝这样敏感的APP数据是有加密的,就算获取了也没那么容易破解。所以也不用太担心在越狱机器上用它们不安全。虽然越狱后的iPhone有这么高风险,但比Android安全得多,因为市场环境好,没多少恶意APP出现,所以情况还是乐观的,了解清楚情况,只要稍微注意点就没问题,至今没听说有人因越狱了iPhone损失了什么

二越狱防护

一般而言完美越狱的设备,是非常危险的,通过脚本动态库注入,可以修改app的方法实现。所以尽量少越狱,即使越狱也不要随意安装插件。

1越狱检测,很多现在常用检测是判断

/Applications/Cydia.app

/Library/MobileSubstrate/MobileSubstrate.dylib

这两个是否存在,但是黑客现可能会改变这些工具的安装路径,躲过你的判断。

但比较好的办法是通过检测当前程序运行的环境变量:

voidprintEnv(void)

•{

char*env = getenv("DYLD_INSERT_LIBRARIES");

•NSLog(@"%s", env);

•}

未越狱设备返回结果是null,越狱设备就各有各的精彩了,尤其是老一点的iOS版本越狱环境。

2敏感交易的时候我们可以做一次校验判断是否正版app,通过二进制文件的验证,来确定app的安全性。

网上的方法是读取沙盒的程序二进制经过md5加密后做一些处理传给服务器验证,这个我也没想好。

3 GDB是大多数hackers的首选,阻止GDB依附是应用的常规办法

•#import 

intmain(intargc,charchar*argv[])

•{

•#ifndef DEBUG

•ptrace(PT_DENY_ATTACH,0,0,0);

•#endif

@autoreleasepool{

returnUIApplicationMain(argc, argv,nil, NSStringFromClass([WQMainPageAppDelegateclass]));

•}

•}

但遗憾的是,iPhone真实的运行环境是没有sys/ptrace.h抛出的。虽然ptrace方法没有被抛出,但是不用担心,我们可以通过dlopen拿到它。

dlopen:当path参数为0是,他会自动查找$LD_LIBRARY_PATH,$DYLD_LIBRARY_PATH, $DYLD_FALLBACK_LIBRARY_PATH和当前工作目录中的动态链接库.

1#import 

2#import 

3

4typedefint(*ptrace_ptr_t)(int_request, pid_t _pid, caddr_t _addr,int_data);

5#if !defined(PT_DENY_ATTACH)

6#define PT_DENY_ATTACH 31

7#endif  // !defined(PT_DENY_ATTACH)

8

9voiddisable_gdb() {

10void* handle = dlopen(0, RTLD_GLOBAL | RTLD_NOW);

11ptrace_ptr_t ptrace_ptr = dlsym(handle,"ptrace");

12ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0);

13dlclose(handle);

14}

15

16intmain(intargc,charchar*argv[])

17{

18#ifndef DEBUG

19disable_gdb();

20#endif

21@autoreleasepool{

22returnUIApplicationMain(argc, argv,nil, NSStringFromClass([WQMainPageAppDelegateclass]));

23}

}

4敏感的逻辑代码重写为C的代码

把函数名隐藏在结构体里,以函数指针成员的形式存储。

这样做的好处是,编译后,只留了下地址,去掉了名字和参数表,提高了逆向成本和攻击门槛。

也许,程序中存在一个类似这样的类:

@interfaceXXUtil : NSObject

•+ (BOOL)isVerified;

•+ (BOOL)isNeedSomething;

•+ (void)resetPassword:(NSString*)password;

@end

改写的程序如下:

•//XXUtil.h

•#import 

typedefstruct_util {

BOOL(*isVerified)(void);

BOOL(*isNeedSomething)(void);

void(*resetPassword)(NSString*password);

•}XXUtil_t ;

•#define XXUtil ([_XXUtil sharedUtil])

@interface_XXUtil : NSObject

•+ (XXUtil_t*)sharedUtil;

@end

24//XXUtil.m

25#import "XXUtil.h"

26

27staticBOOL_isVerified(void)

28{

29//bala bala ...

30returnYES;

31}

32

33staticBOOL_isNeedSomething(void)

34{

35//bala bala ...

36returnYES;

37}

38

39staticvoid_resetPassword(NSString*password)

40{

41//bala bala ...

42}

43

44staticXXUtil_t* util =NULL;

45@implementation_XXUtil

46

47+(XXUtil_t*)sharedUtil

48{

49staticdispatch_once_t onceToken;

50dispatch_once(&onceToken, ^{

51util = malloc(sizeof(XXUtil_t));

52util->isVerified = _isVerified;

53util->isNeedSomething = _isNeedSomething;

54util->resetPassword = _resetPassword;

55});

56returnutil;

57}

58

59+ (void)destroy

60{

61util ? free(util): 0;

62util =NULL;

63}

@end

最后,根据Xcode的报错指引,把以前这样的调用

[XXUtilisVerified];

对应改成:

XXUtil->isVerified();

5数据保护API

文件系统中的文件、keychain中的项,都是加密存储的。当用户解锁设备后,系统通过UDID密钥和用户设定的密码生成一个用于解密的密码密钥,存放在内存中,直到设备再次被锁,开发者可以通过Data

Protection API来设定文件系统中的文件、keychain中的项应该何时被解密。

1)文件保护

•/*为filePath文件设置保护等级*/

NSDictionary*attributes = [NSDictionarydictionaryWithObject:NSFileProtectionComplete

•forKey:NSFileProtectionKey];

•[[NSFileManagerdefaultManager]setAttributes:attributes

•ofItemAtPath:filePath

•error:nil];

//文件保护等级属性列表

NSFileProtectionNone//文件未受保护,随时可以访问(Default)

NSFileProtectionComplete//文件受到保护,而且只有在设备未被锁定时才可访问

NSFileProtectionCompleteUntilFirstUserAuthentication//文件收到保护,直到设备启动且用户第一次输入密码

NSFileProtectionCompleteUnlessOpen//文件受到保护,而且只有在设备未被锁定时才可打开,不过即便在设备被锁定时,已经打开的文件还是可以继续使用和写入

2keychain项保护

1/*设置keychain项保护等级*/

2NSDictionary*query = @{(__bridgeid)kSecClass: (__bridgeid)kSecClassGenericPassword,

3(__bridgeid)kSecAttrGeneric:@"MyItem",

4(__bridgeid)kSecAttrAccount:@"username",

5(__bridgeid)kSecValueData:@"password",

6(__bridgeid)kSecAttrService:[NSBundlemainBundle].bundleIdentifier,

7(__bridgeid)kSecAttrLabel:@"",

8(__bridgeid)kSecAttrDescription:@"",

9(__bridgeid)kSecAttrAccessible:(__bridgeid)kSecAttrAccessibleWhenUnlocked};

10

11OSStatus result = SecItemAdd((__bridge CFDictionaryRef)(query),NULL);

1//keychain项保护等级列表

2kSecAttrAccessibleWhenUnlocked//keychain项受到保护,只有在设备未被锁定时才可以访问

3kSecAttrAccessibleAfterFirstUnlock//keychain项受到保护,直到设备启动并且用户第一次输入密码

4kSecAttrAccessibleAlways//keychain未受保护,任何时候都可以访问(Default)

5kSecAttrAccessibleWhenUnlockedThisDeviceOnly//keychain项受到保护,只有在设备未被锁定时才可以访问,而且不可以转移到其他设备

6kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly//keychain项受到保护,直到设备启动并且用户第一次输入密码,而且不可以转移到其他设备

7kSecAttrAccessibleAlwaysThisDeviceOnly//keychain未受保护,任何时候都可以访问,但是不能转移到其他设备

for example

把一段信息infoStrng字符串写进文件,然后通过Data

Protection API设置保护。

1NSString*documentsPath =[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES)firstObject];

2NSString*filePath = [documentsPathstringByAppendingPathComponent:@"DataProtect"];

3[infoStringwriteToFile:filePath

4atomically:YES

5encoding:NSUTF8StringEncoding

6error:nil];

7NSDictionary*attributes = [NSDictionarydictionaryWithObject:NSFileProtectionComplete

8forKey:NSFileProtectionKey];

9[[NSFileManagerdefaultManager]setAttributes:attributes

10ofItemAtPath:filePath

11error:nil];

设备锁屏(带密码保护)后,即使是越狱机,在root权限下cat读取那个文件信息也会被拒绝。

参考链接:

http://blog.csdn.net/yiyaaixuexi/article/category/1302847/1

这个妹子是阿里安全部的,很厉害啊。。。。

微博:程序媛念茜

你可能感兴趣的:(ios 越狱与安全性分析)