虽然公司的项目目前还不算健壮,安全问题对于大部分小公司来说似乎并没什么必要,不过要攻击的话,我有十足的把握,我们是无法承受冲击的。嘿嘿嘿~不过带着一颗入坑iOS的心思,搜集了一下资料后,还是做了一些尝试。

iOS App安全防范总结:

1.防止抓包篡改数据
2.防止反编译
3.阻止动态调试
4.防止二次打包

关键检测:越狱检测

  • OK,下面是正文开始。

1.防止抓包篡改数据

对于抓包,利用神器charles的操作会在另外的文章单独介绍。如果不懂以下为利用charles抓包。
charles抓包教程

若别人真想抓你程序包,该如何防范呢?我目前只能说,let it go ~ let it go~随他抓,随他抓。因为基本上只要想抓取程序访问的数据,基本上是能抓取到的。对于iOS来说,目前我是做了两种操作。

1)判断是否设置了代理
对于抓包,现在的手段基本是设置代理,所以我们可以通过判断是否设置了代理的方式来进行下一步的防范。

#在网络请求前插入这个方法,再根据需求做相应的防范
+ (BOOL)getDelegateStatus
{
NSDictionary *proxySettings = CFBridgingRelease((__bridge CFTypeRef _Nullable)((__bridge NSDictionary *)CFNetworkCopySystemProxySettings()));
NSArray *proxies = CFBridgingRelease((__bridge CFTypeRef _Nullable)((__bridge NSArray *)CFNetworkCopyProxiesForURL((__bridge CFURLRef)[NSURL URLWithString:@"http://www.google.com"], (__bridge CFDictionaryRef)proxySettings)));
NSDictionary *settings = [proxies objectAtIndex:0];
NSLog(@"host=%@", [settings objectForKey:(NSString *)kCFProxyHostNameKey]);
NSLog(@"port=%@", [settings objectForKey:(NSString *)kCFProxyPortNumberKey]);
NSLog(@"type=%@", [settings objectForKey:(NSString *)kCFProxyTypeKey]);
if ([[settings objectForKey:(NSString *)kCFProxyTypeKey] isEqualToString:@"kCFProxyTypeNone"])
{
//没有设置代理
return NO; } else {
//设置代理了
return YES;
}
}

2)RSA
通过与后台的配合,设置公钥与私钥,对请求数据和返回数据进行加密。这里另外起一篇单独介绍。

2.防止反编译(防止class-dump、hopper反编)

越狱检测

一般能拿到自己ipa包都需要有一台越狱的手机

  • 判断设备是否安装了越狱常用工具:
    一般安装了越狱工具的设备都会存在以下文件:
    /Applications/Cydia.app
    /Library/MobileSubstrate/MobileSubstrate.dylib
    /bin/bash
    /usr/sbin/sshd
    /etc/apt

  • 判断设备上是否存在cydia应用

  • 是否有权限读取系统应用列表
    没有越狱的设备是没有读取所有应用名称的权限

  • 检测当前程序运行的环境变量 DYLD_INSERT_LIBRARIES
    非越狱手机DYLD_INSERT_LIBRARIES获取到的环境变量为NULL。

综上所述,检查设备是否越狱

+ (BOOL)isJailbroken {
// 检查是否存在越狱常用文件
NSArray *jailFilePaths = @[@"/Applications/Cydia.app",
@"/Library/MobileSubstrate/MobileSubstrate.dylib",
@"/bin/bash",
@"/usr/sbin/sshd",
@"/etc/apt"];
for (NSString *filePath in jailFilePaths) {
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
return YES;
}
} // 检查是否安装了越狱工具Cydia
if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"cydia://package/com.example.package"]]){
return YES;
} // 检查是否有权限读取系统应用列表
if ([[NSFileManager defaultManager] fileExistsAtPath:@"/User/Applications/"]){
NSArray *applist = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@"/User/Applications/"
error:nil];
NSLog(@"applist = %@",applist);
return YES;
} // 检测当前程序运行的环境变量
char *env = getenv("DYLD_INSERT_LIBRARIES");
if (env != NULL) {
return YES;
} return NO;
}

代码混淆

这里生成混淆代码的方法我们通过shell脚本来实现,同时我们需要一个文档来写入我们需要进行混淆的方法名或是变量名。

  • 打开终端,cd到文件所在目录,使用

touch confuse.sh
touch func.list

此时将目录中的.sh和.list文件拖入项目中

  • 写入shell脚本

在项目中找到刚刚拖进来的.sh文件,在confuse.sh中写入脚本

#!/bin/bash

# 这是Shell脚本,如果不懂shell,自行修炼:http://www.runoob.com/linux/linux-shell.html

# 以下使用sqlite3进行增加数据,如果不了解sqlite3命令,自行修炼:http://www.runoob.com/sqlite/sqlite-tutorial.html

#数据表名
TABLENAME="CodeObfuscationOC" #数据库名
SYMBOL_DB_FILE="CodeObfuscation.db" #要被替换的方法列表文件
STRING_SYMBOL_FILE="$PROJECT_DIR/ConfusionDemo/func.list" #被替换后的宏定义在此文件里
HEAD_FILE="$PROJECT_DIR/$PROJECT_NAME/CodeObfuscation.h" #维护数据库方便日后做bug排查
createTable()
{
echo "create table $TABLENAME(src text,des text);" | sqlite3 $SYMBOL_DB_FILE
} insertValue()
{
echo "insert into $TABLENAME values('$1','$2');" | sqlite3 $SYMBOL_DB_FILE
} query()
{
echo "select * from $TABLENAME where src='$1';" | sqlite3 $SYMBOL_DB_FILE
} #生成随机16位名称
randomString()
{
openssl rand -base64 64 | tr -cd 'a-zA-Z' | head -c 16
} #删除旧数据库文件
rm -f $SYMBOL_DB_FILE #删除就宏定义文件
rm -f $HEAD_FILE #创建数据表
createTable #touch命令创建空文件,根据指定的路径
touch $HEAD_FILE
echo '#ifndef CodeObfuscation_h
#define CodeObfuscation_h' >> $HEAD_FILE
echo "//confuse string at `date`" >> $HEAD_FILE #使用cat将方法列表文件里的内容全部读取出来,形成数组,然后逐行读取,并进行替换
cat "$STRING_SYMBOL_FILE" | while read -ra line;
do
if [[ ! -z "$line" ]]
then
random=`randomString`
echo $line $random #将生成的随机字符串插入到表格中
insertValue $line $random #将生成的字符串写入到宏定义文件中,变量是$HEAD_FILE
echo "#define $line $random" >> $HEAD_FILE
fi
done
echo "#endif" >> $HEAD_FILE
sqlite3 $SYMBOL_DB_FILE .dump
  • 添加run script命令

 
640.jpg
  • 然后添加$PROJECT_DIR/ConfusionDemo/confuse.sh

  • 给脚本授权

接下来还是在我们项目的文件夹下,通过终端给我们的脚本赋予最高权限

chmod 777 confuse.sh
  • 添加预编译文件PCH

 
6401.jpg

然后配置PCH文件

 
6402.jpg
  • 添加$PROJECT_DIR/ConfusionDemo/PrefixHeader.pch

  • 生成CodeObfuscation.h文件

这时候我们编译一下代码,会发现项目中多出了一个CodeObfuscation.h文件(如果没有,可到项目文件夹中找,我的就是在文件夹里找到的- -,然后拖进项目)。这个文件就是替换方法名的文件,我们在PCH文件中引入他。

  • 在func.list中添加准备替换的方法名

在项目中点开之前拖进来的func.list文件,然后在里面加入自己想要混淆的方法名

//此处方法名为项目中自己编码的方法名,不可混淆系统方法名
viewControllerTestMethodA
viewControllerTestMethodB
viewControllerTestMethodC
viewControllerMethodWithParameter
testString
testArray
testMutDic
  • 结果

编译之后

#ifndef CodeObfuscation_h
#define CodeObfuscation_h #define viewControllerTestMethodA CTBxmOXAbJYekhnH
#define viewControllerTestMethodB RnPEjnXygFXLdikO
#define viewControllerTestMethodC IzHlDYOpaAFYFTXa
#define viewControllerMethodWithParameter nWqyalBcfoUSRVpc
#define testString MNPoVYdmCcklAnCO
#define testArray kHMRxPlGXGeqekxL
#define testMutDic hphPSODIvbBFSTHX
#endif

看到 CodeObfuscation有这种变化,恭喜你,已经代码混淆成功。即使通过class-dump反编出来的,也只是一堆乱码。

  • 需要注意的几点

    不可以混淆iOS中的系统方法;

    不可以混淆iOS中init等初始化方法;

    不可以混淆xib的文件,会导致找不到对应文件;

    不可以混淆storyboard中用到的类名;

    混淆有风险,有可能会被App Store以2.1大礼包拒掉。

3.阻止动态调试

GDB、LLDB是Xcode内置的动态调试工具。使用GDB、LLDB可以动态的调试你的应用程序(通过下断点、打印等方式,查看参数、返回值、函数调用流程等)。

为了阻止hackers使用调试器 GDB、LLDB来攻击你的App,你可以在main.m文件中插入以下代码:

#import <dlfcn.h>
#import <sys/types.h> typedef int (*ptrace_ptr_t)(int _request, pid_t _pid, caddr_t _addr, int _data);
#if !defined(PT_DENY_ATTACH)
#define PT_DENY_ATTACH 31
#endif // !defined(PT_DENY_ATTACH) void disable_gdb() {
void* handle = dlopen(0, RTLD_GLOBAL | RTLD_NOW);
ptrace_ptr_t ptrace_ptr = dlsym(handle, "ptrace");
ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0);
dlclose(handle);
} int main(int argc, char *argv[]) {
// Don't interfere with Xcode debugging sessions.
#if !(DEBUG)
disable_gdb();
#endif @autoreleasepool {
return UIApplicationMain(argc, argv, nil,
NSStringFromClass([MyAppDelegate class]));
}
}

4.防止二次打包

iOS 和 OS X 的应用和框架包含了二进制代码和所需要的资源文件(如:图片、不同的语言文件、XIB/Storyboard文件、profile文件等),在通过开发者私钥签名程序包时,对于可执行文件( Mach-O ),会将签名直接写入到该文件中,而对于其他的资源文件,会统一写到 _CodeSignature 文件下的 CodeResources 文件中,它仅仅是一个 plist 格式文件。

这个列表文件中不光包含了文件和它们的签名的列表,还包含了一系列规则,这些规则决定了哪些资源文件应当被设置签名。伴随 OS X 10.10 DP 5 和 10.9.5 版本的发布,苹果改变了代码签名的格式,也改变了有关资源的规则。如果你使用10.9.5或者更高版本的 codesign 工具,在 CodeResources 文件中会有4个不同区域,其中的 rules 和 files 是为老版本准备的,而 files2 和 rules2 是为新的第二版的代码签名准备的。最主要的区别是在新版本中你无法再将某些资源文件排除在代码签名之外,在过去你是可以的,只要在被设置签名的程序包中添加一个名为 ResourceRules.plist 的文件,这个文件会规定哪些资源文件在检查代码签名是否完好时应该被忽略。但是在新版本的代码签名中,这种做法不再有效。所有的代码文件和资源文件都必须 设置签名,不再可以有例外。在新版本的代码签名规定中,一个程序包中的可执行程序包,例如扩展 (extension),是一个独立的需要设置签名的个体,在检查签名是否完整时应当被单独对待。

有些hacker可能会通过篡改你的程序包(包括资源文件和二进制代码)加入一些广告或则修改你程序的逻辑,然后重新签名打包,由于第三方hacker获取不到签名证书的私钥,因此会替换掉程序包中签名相关的文件embedded.mobileprovision,我们可以直接检查此文件是否被修改,来判断是否被二次打包,如果程序被篡改,则退出程序。
检测embedded.mobileprovision是否被篡改:

// 校验值,可通过上一次打包获取
#define PROVISION_HASH @"w2vnN9zRdwo0Z0Q4amDuwM2DKhc="
static NSDictionary * rootDic=nil; void checkSignatureMsg()
{
NSString *newPath=[[NSBundle mainBundle]resourcePath]; if (!rootDic) { rootDic = [[NSDictionary alloc] initWithContentsOfFile:[newPath stringByAppendingString:@"/_CodeSignature/CodeResources"]];
} NSDictionary*fileDic = [rootDic objectForKey:@"files2"]; NSDictionary *infoDic = [fileDic objectForKey:@"embedded.mobileprovision"];
NSData *tempData = [infoDic objectForKey:@"hash"];
NSString *hashStr = [tempData base64EncodedStringWithOptions:0];
if (![PROVISION_HASH isEqualToString:hashStr]) {
abort();//退出应用
}
}

参考

https://blog.csdn.net/u011656331/article/details/81120420
https://mp.weixin.qq.com/s/zD5EtFpSzKQ0h-ORTC9WqQ

作者:小苏羿
链接:https://www.jianshu.com/p/0cfb5859f15f
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

iOS App的几种安全防范的更多相关文章

  1. iOS App之间常用的五种通信方式及适用场景总结

    iOS系统是相对封闭的系统,App各自在各自的沙盒(sandbox)中运行,每个App都只能读取iPhone上iOS系统为该应用程序程序创建的文件夹AppData下的内容,不能随意跨越自己的沙盒去访问 ...

  2. iOS - app 进行安全加固

    研究了大半年逆向工程了,没在博客做记录,最近看到篇,跟自己的想法不谋而合,摘要下: 运行在越狱设备上的 iOS app,非常容易遭到破解分析,这里我列举一些可以加大破解难度的方法,希望有所帮助. 一些 ...

  3. iOS App上架流程(2016详细版)

    iOS App上架流程(2016详细版) 原文地址:http://www.jianshu.com/p/b1b77d804254 感谢大神整理的这么详细 一.前言: 作为一名iOSer,把开发出来的Ap ...

  4. 用Model-View-ViewModel构建iOS App(转)

    转载自 Model-View-ViewModel for iOS [译] 如果你已经开发一段时间的iOS应用,你一定听说过Model-View-Controller, 即MVC.MVC是构建iOS a ...

  5. 用Model-View-ViewModel构建iOS App

    如果你已经开发一段时间的iOS应用,你一定听说过Model-View-Controller,即MVC.MVC是构建iOS App的标准模式.然而,最近我已经越来越厌倦MVC的一些缺点.在本文,我将重温 ...

  6. APP开发:对于IOS APP应用的推广渠道有哪些?

    亿合科技了解到,随着移动互联网时代的到来,苹果从2007年进入中国市场,一直备受大众喜爱,手机应用也层出不穷.那么对于那么多的IOS APP应用怎么能获得用户的喜爱呢?于是推广APP应用是需要做的,亿 ...

  7. 最新Xcode7.x环境下上架iOS App到AppStore 完整流程

    最新Xcode7.x环境下上架iOS App到AppStore 流程  part 1 前言部分 之前App要上架遇到些问题到网上搜上架教程发现都是一些老的版本的教程 ,目前iTunesConnect ...

  8. [摘抄]iOS App icon、启动页、图标规范

    以下内容都是我在做App时通过自己的经验和精品的分析得来的,希望会帮助到你.但是有时个别情况也要个别分析,要活学活用. 一. App  Icon 在设计iOS App Icon时,设计师不需要切圆角, ...

  9. iOS app 程序启动原理

    iOS app 程序启动原理 Info.plist: 常见设置     建立一个工程后,会在Supporting files文件夹下看到一个"工程名-Info.plist"的文件, ...

随机推荐

  1. JS基础 sessionStorage

    html5中的Web Storage包括了两种存储方式:sessionStorage和localStorage. sessionStorage用于本地存储一个会话(session)中的数据,这些数据只 ...

  2. vue cli3 打包到tomcat上报错问题

    首先  项目打包步骤 1.vue config.js  添加 publicPath: './', // 公共路径 assetsDir:'static', 2.将代理注释掉 proxy 3.将hash需 ...

  3. 你所不知道的 Console

    1.凡人视角 打印字符串 代码: console.log("I am a 凡人"); 打印提示消息 代码: console.info("Yes, you arm a 凡人 ...

  4. JS实现异步的几种方式

    1.JS执行环境:单线程   单线程:就是指一次只能完成一件任务.若有多个任务时,就必须排队,等前面一个任务完成之后,再执行后面一个任务 缺点:任务耗时很长,后面的任务需要等待,拖延整个程序的执行.例 ...

  5. OpenCV实现图象翻转、滤波、锐化

    OpenCV实现图象翻转.滤波.锐化 注:以下代码,使用opencv库函数实现了对图片的翻转.灰度图转换.各种滤波.各种锐化. 库函数相关参数及说明参阅:OpenCV中文站=>opencv教程( ...

  6. Mycat详解及配置读写分离(Centos7)

    目录 一.理论概述 二.环境 三.部署 一.理论概述 原理简述 参考文档 MyCAT主要是通过对SQL的拦截,然后经过一定规则的分片解析.路由分析.读写分离分析.缓存分析等,然后将SQL发给后端真实的 ...

  7. c# 枚举和位标志

  8. 如何利用while语句根据用户输入要求打印菱形图案

    需求:如何利用while语句根据用户输入要求打印菱形图案 diamond.py代码如下: x=int(input('Please input number: ')) i=1 j=1 while i&l ...

  9. python_并发编程——进程池

    1.进程池 from multiprocessing import Pool def func(n): for i in range(10): print(n+1) if __name__ == '_ ...

  10. JAVA开发WEBSERVICE方式

    webservice的应用已经越来越广泛了,下面介绍几种在Java体系中开发webservice的方式,相当于做个记录. 1.Axis2方式 Axis是apache下一个开源的webservice开发 ...