从这一篇文章开始,我么就要开搞iOS相关的东西了,包括正向开发和逆向分析,因为不能仅仅局限于Android的世界,iOS的世界依然很美,同时我也是经常使用iPhone的,一直都想用上自己开发的插件,不过越来越觉得iOS不如Android好用了,本文主要介绍一下后续开搞的基本知识点。看看开发iOS需要知道哪些东西和需要准备哪些工具,具体和Android做比对。
一、应用开发和发布
关于应用发布已经账号开发,iOS和Android有着很大的区别,有这么大的区别应该是iOS整个生态系统比Android完善吧,Android我们都知道只要有AndroidStudio和一个设备就可以入门开发了,当然这里忽略模拟器效果哈。但是iOS不行,iOS不是说只要有一个Xcode和一个iPhone就可以开发了,还需要设置证书啥的。还有发布的时候也是,对于Android国内是免费的,只要你能够过了各个市场的审核就可以,国外GooglePlay需要开通账号我记得我当时是给了29美金,但是这个是终生的哦,所以还觉得可以,但是iOS就恶心了,只要购买就必须每年是99美金,记得是每年哦,说实话为了个人学习购买的话我是不愿意的,不过他也有免费的但是限制很恶心。下面来看一下iOS中应用发布和开发账号类型的区别
看到这张表格很好的诠释了iOS中开发者账号的几个类型,这里更多的关注是个人账号和公司企业账号:
1》其中个人账号有免费的也有交钱的,区别在于本地Xcode中项目的bundleid没有限制,在我开发学习过程中一直都是用免费的个人账号的,但是有一天我遇到这么个错误:
当时遇到这个问题很郁闷也问了很多人,最后发现原来是个人免费开发者账号他创建的工程配发的bundleid是有限制的,可能这个bundleid就是我最后一个了,具体这个限制数量好像官方也没说是多少个。当然免费的和付钱的还有一个最大的区别在于你开发完的应用是否可以发布到AppStore上,其实一直没搞懂苹果为啥在开发的过程中要把付钱的和没付钱的区分那么细,觉得上传发布到市场上区分付钱还可以理解。但是本地开发为啥还要区分,当然还有其他区别,这里就不在列举了。
2》公司账号和企业账号的最大的区别在于,公司账号和付费的个人账号都是可以发布应用到AppStore上的,这两个的区别是发布之后再AppStore里面显示的开发者名称不一样,而对于企业账号是不允许发布到AppStore市场中的和个人免费开发者账号类似,但是他有个好处就是没有设备限制,企业账号最常用的就是公司里面的应用内侧版本,就是不能泄露出去的版本,一般我们都是通过扫描二维码然后浏览器中提示安装,而且这种安装之后需要去 设置->通用->描述文件与设备管理 手动信任这个应用的,因为苹果认为从非AppStore中安装的应用都是不安全的,当然也有一些公司开发的应用不符合AppStore审核被拒的时候也是采用这种方式发布应用的,一般我们经常看一些网站上就是弹出一个提示让你安装,然后在让你去设置手动信任一下。
我们只要开发不管是发布还是不发布,都需要先去官网申请一个账号:https://developer.apple.com/account 这个主要用于后续开发用哪个账号进行app签名然后安装到真机中方便测试,其实如果你有iPhone设备了,肯定就有账号了,因为现在用iPhone的都需要用账号激活设备,然后iCould啥的,AppStore里面安装应用都需要账号的,没有账号其实设备是几乎用不了的。
关于账号这里还有一些区别,就是和我们后期出包类型有很大关系,比如我们现在用Xcode导出一个ipa包:
选择菜单Product->Archive:
然后这里选择Distrute App:
到这里就出现了四种类型的的打包方式了:
1、App Store Connect
保存到本地,准备上传App Store或者在越狱的iOS设备上使用,很明显的需要发布到App Store上的,那么结合上面的那张图,需要是付费的个人账号以及公司账号和政府账号才可以。
2、Ad Hoc
保存到本地,准备在已添加账号的可使用设备上使用(具体为在开发者账户下添加可用设备的UDID),该app包是发布证书编译的,安装测试用的但是有udid限制,那么可以理解是没有上传的AppStore的,那么除了一个免费的个人账号,其他类型账号都可以,有的同学好奇了免费的账号为啥不可以呢,其实直接点击next就知道了:
看到了这个就是我的免费账号被侮辱的结果,所以做人一定要有钱!
3、Enterprise
这种主要针对企业级账户下,可以本地服务器分发的app,这个一看就是没有任何udid设备数量限制,那么只有企业账号可以做到
4、Deployment
针对内部测试使用,主要给开发者的设备(具体也为在开发者账户下添加可用设备的UDID)。该app包是开发证书编译的,其实这个和第二Ad Hoc很类似,唯一区别是这个用开发证书编译的,而Ad Hoc用的是发布证书编译的。
其实后面大家会经常看到这两种类型的的发布包方式(ipa):
第一、In-House 企业应用发布
1》不能提交到AppStore
2》发布应用的具体内容不需要苹果官方审核(因为提交不了AppStore所以也不需要苹果审核哈哈哈)
3》安装设备的数量没有任何限制
4》把程序放到网站中,提供给用户一个链接,他们就能直接下载并且自动安装
只有企业账号可以做这种类型的应用分发
第二、Ad Hoc 应用发布方式
1》不能提交到AppStore
2》不需要经过苹果的评审
3》限制每个应用不能发布到超过100个设备上
4》把程序放到网站中,提供给用户一个链接,他们就能直接下载并且自动安装
除了个人免费的账户以外,其他类型的账户类型都可以进行分发
其实上面两种发布方式一般用于App因为不合规的内容被苹果商店拒绝了,或者是公司开发的应用内侧包等,所以就用这方式搞个链接到网站上引导用户下载,不过这种下载安装之后是直接打不开的,需要进行设备证书授权的:
苹果为了安全不允许任何从非不可以发布应用的账号打出来的包直接打开的,就是如果这个ipa包是你用不可以发布app的类型账号打出来的都必须要授权信任:
我们去 设置->通用->设备描述文件管理 找到信任选项直接信任即可打开使用了。不过我们知道Ad-Hoc这种形式因为设备有数量限制,所以大部分公司分发应用都会用企业账户进行打包。其实这里还有应用签名的区别,后面会介绍。
二、应用文件说明(ipa/app)
这里说的文件种类不包括我们正向开发里面的程序文件比如代码是.h和.m呀,我们说的是逆向中或者说程序应用的文件,比如我们知道Android中最终编译出来的是apk文件,apk其实是一个压缩包格式,他内部包含了dex文件主要是代码编译后的东西,还有资源编译后的文件arsc格式等,这个格式都可以用010Editor按照指定模板打开,那么iOS编译后的应用包是ipa格式,其实ipa也是一个压缩包格式,我们可以直接用解压软件打开即可,打开之后就是app文件了,这个我们可以直接右键->显示包内容就可以看到整个应用的所有资源文件了,比如这里我们从爱思助手或者PP助手上下载一个ipa下来解压看到,一般都是Payload目录包含了xxx.app内容
这里其实MTPotal.app是一个文件夹,我们可以右键->显示包内容:
我们可以用命令行看到这个其实就是一个文件夹:
其实就是一个文件夹而已,我们看到的.app文件,包括我们Mac中的安装的程序在Applications中也是如此:
这里也可以看到其实Mac和iPhone采用的很多机制都一样的,整个苹果的生态系统也是很完整的,所以如果我们对iOS逆向比较了解了,Mac中的逆向也是没啥难度。
到这里看到这里有很多内容了,不过这里不会介绍那么多,因为其他文件暂时用不到,等后面有具体场景会具体分析,这个有点类似Android的apk解压后的可以看到这么信息,当然这里最重要的就是二进制可以执行文件文件了:
我们一般打开.app目录之后可以看到这种二进制可执行文件的,其实这个文件就是整个程序的运行代码内容,已经被编译成二进制文件了,类似于Android中的dex文件,但是这类文件有个统称叫做:Mach-O,关于这个文件是整个苹果生态系统中的二进制文件:
Mach-O格式全称为Mach Object文件格式的缩写,是mac上可执行文件的格式,类似于Windows上的PE格式或者是Linux上的elf格式,Mach-o文件类型分为:
1、Executable:应用的主要二进制
2、Dylib Library:动态链接库(又称DSO或DLL)
3、Static Library:静态链接库
4、Bundle:不能被链接的Dylib,只能在运行时使用dlopen( )加载,可当做macOS的插件
5、Relocatable Object File :可重定向文件类型
拓展说明:在iOS中静态库以.a和.framework的形式存在,动态库以.dylib和.framework的形式存在。之所以.framework既可能是动态库又可能是静态库,是因为苹果公司禁止用户级App使用动态库,而自己却又堂而皇之的使用动态库,这就造成了iOS中系统级的.framework是动态库,用户级的.framework是静态库
.a与.framework的区别
.a是纯二进制文件,.a文件不能单独使用,至少要有.h文件配合,而.framework除了二进制文件外,还包含一些资源文件(头文件,plist等),由于自身包含了头文件,所以.framework可以单独使用。
FatFile/FatBinary文件格式:
简单来说,就是一个由不同的编译架构后的Mach-O产物所合成的集合体。一个架构的Mach-O只能在相同架构的机器或者模拟器上用,为了支持不同架构需要一个集合体。
了解了Mach-O文件之后,就应该有类似的工具可以查看他的内容格式,比如Android中如果想查看so文件,可以用命令readelf,或者用010Editor借助模板可以UI功能查看等,这里也不例外,如果想用UI功能查看的工具MachOview:
MachOView下载地址:http://sourceforge.net/projects/machoview
MachOView源码地址:https://github.com/gdbinit/MachOView
比如上面我们打开应用的可执行文件,看到他最外层是一个Fat Binary格式,可以看到,Fat文件只是对各种架构文件的组装,点开 “Fat Header”可以看到支持的架构,图中显示的支持ARM_V7 、ARM_64 :
其实这里还有很多元信息,比如系统支持等,这里就不多介绍了,但是这里我们需要重点看一个重要信息就是,应用是否加壳了:
我们通过查看Load Commads->LC_ENCRYPTION_INFO 然后可以看到有个字段Crypt ID 这个值如果是1表示这个应用被加壳的,如果是0表示未加密的,所以我们看到iOS中的加壳其实对可执行的二进制文件进行加密的。当然我们可以用Mac中自带的otool工具直接查看二进制文件信息,不过信息很多如果想直接查看是否加壳直接过滤即可:
通过这样我们就可以看到应用是否加壳了。当然这个工具不仅可以看iOS的可执行文件,也可以看dylib,a,framework等文件都可以的。
三、应用加壳/砸壳
iOS中为了安全在所有应用上传到AppStore的时候都会进行一次加密操作,这个加密是苹果后台进行操作的,不可否认苹果在安全方面始终都会重点考虑比Android这方面,说到这里我们可以反观GooglePlay上的盗版应用泛滥,因为应用没有任何安全防护,国内安全公司搞了自己的一套加壳结果发布的应用会被拒绝,自己又不搞安全防护。虽然苹果的加密很容易砸壳掉,但是至少人家做了这么一点还是很好的(以下三张图片来源于网络):
其实他加壳通过上面的分析知道其实是对可执行的二进制文件进行加密操作的:
看到这里是否突然觉得和Android中的第一代应用加密原理很类似,Android国内第一代加密原理就是把源apk进行一层加密成一个指定文件,然后外部在套一个壳apk,运行的时候进行解密源apk然后动态加载运行的。所以通过这个原理就知道了脱壳或者是砸壳是多么容易的一件事:
iOS中已经有了现成的砸壳工具了:Clutch,dumpdecrypted,frida-ios-dump;我试了这三个工具,最后感觉最好用的还是frida-ios-dump,前面两个工具也用过,但是总是出现 Kill -9 的错误,网上说dylib没签名,也有的说要执行su mobile,但是都试了也还是不行,所以最终用最后一个工具了,不过我们在实际砸壳过程中会发现,Clutch,dumpdecrypted 这两个工具呀一直是-9,据说是因为不完全越狱导致的,而frida-ios-dump的确是可以砸壳,但是他的原理是需要ssh链接设备,会经常出现砸大型应用的时候直接卡住不动特别恶心,虽然可以中断再来一次但是的确效率低,所以就找到了一个更加方便的工具,这个工具直接是在手机中就可以砸壳:CrackerXI 这个需要添加软件源然后在Cydia中安装,这里直接添加了多米诺软件源:https://apt.wxhbts.com :
所以现在我一般都是用frida-ios-dump和CrackerXI 这两个工具具体用法在后面文章会具体介绍到,所以到这里我们就知道iOS为了安全会把上传到AppStore上的ipa文件进行加壳操作,我们下载下来的是已经加壳的,如果想逆向第一步先砸壳获取更多逆向信息,因为有了自己家的加壳算法,所以iOS应用很难在自己搞一套加壳算法了,不然后台检测失败直接拘审下架应用,没有哪家公司愿意承担这样的风险,但是Android国内暂时没这个限制,但是也不是所有的公司都愿意给应用加壳的。
四、OC/Swift语言介绍
关于iOS开发现在是OC和Swift语言,苹果官方建议使用Swift语言因为性能等方面还是有很大优势的,但是一些公司早起都用的是OC语言写的代码,现在要切换Swift成本有点大,同时Swift是有系统版本限制的,这个对于现在很多应用是个难题,所以会发现都几年了Swift还没有普及开。通过后面的逆向脚本操作来看,OC也是占据很大优势所以总体大家还是先看看学习OC语法吧,如果有时间可以再看看Swift语法,逆向虽然不需要写很多正向的代码,但是在任何时候如果不了解这一块的话就很难逆向下去了,反观Android有Java和Kotlin语法,通过现有的操作看也是Java占据主动地位在逆向过程中来看,关于OC语法介绍:
http://www.520monkey.com/archives/category/oc%e5%ad%a6%e4%b9%a0%e7%af%87
五、应用签名证书说明
第一、签名流程
和Android一样作为应用必须要签名才能安装使用,Android中在使用AndroidStudio的时候是用了默认的debug.keystore进行签名然后安装的,主要有第一代签名和第二代签名为主,在安装应用的时候会先校验设备中是否已经安装了相同的包名应用,如果安装了就需要获取签名信息进行比对,不符合就不让安装,在iOS中也是类似:
先来一张图,这个是iOS中最经典的签名流程图(图片和以下解释来源于网络):
1、在你的 Mac 开发机器生成一对公私钥,这里称为公钥L,私钥L。L:Local
2、苹果自己有固定的一对公私钥,跟上面 AppStore 例子一样,私钥在苹果后台,公钥在每个 iOS 设备上。这里称为公钥A,私钥A。A:Apple
3、把公钥 L 传到苹果后台,用苹果后台里的私钥 A 去签名公钥 L。得到一份数据包含了公钥 L 以及其签名,把这份数据称为证书。
4、在开发时,编译完一个 APP 后,用本地的私钥 L 对这个 APP 进行签名,同时把第三步得到的证书一起打包进 APP 里,安装到手机上。
5、在安装时,iOS 系统取得证书,通过系统内置的公钥 A,去验证证书的数字签名是否正确。
6、验证证书后确保了公钥 L 是苹果认证过的,再用公钥 L 去验证 APP 的签名,这里就间接验证了这个 APP 安装行为是否经过苹果官方允许。(这里只验证安装行为,不验证APP 是否被改动,因为开发阶段 APP 内容总是不断变化的,苹果不需要管。)
看到整体流程有点复杂,主要是在于它把Mac也参与进来了校验,这个图片大家没事在地铁里面可以慢慢的看几遍就记住了,相比较Android的一代签名校验还是很复杂的,Android中直接是 MANIFEST.MF,CERT.RSA,CERT.SF 文件中记录每个文件的MD5信息,如果篡改了任何apk中的资源包括改代码和资源都是需要重新签名的。比如Android中可能有以下改了apk资源之后的情况:
第二、签名文件信息
首先,如果你改变了apk包中的任何文件,那么在apk安装校验时,改变后的文件摘要信息与MANIFEST.MF的检验信息不同,于是验证失败,程序就不能成功安装。其次,如果你对更改的过的文件相应的算出新的摘要值,然后更改MANIFEST.MF文件里面对应的属性值,那么必定与CERT.SF文件中算出的摘要值不一样,照样验证失败。最后,如果你还不死心,继续计算MANIFEST.MF的摘要值,相应的更改CERT.SF里面的值,那么数字签名值必定与CERT.RSA文件中记录的不一样,还是失败。具体Android中的签名校验机制看这里:http://www.520monkey.com/archives/571 Android中签名信息一般都存放在这里:
对于iOS中也是类似,我们解压ipa然后查看.app中的内容:
1、资源文件:例如图片、html等。
2、_CodeSignature/CodeResources:这是一个plist文件,可用文本查看,其中的内容就是是程序包中(不包括Frameworks)所有文件的签名。注意这里是所有文件。意味着你的程序一旦签名,就不能更改其中任何的东西,包括资源文件和可执行文件本身。iOS系统会检查这些签名。
3、app:可执行文件。此文件跟资源文件一样需要签名。
4、embedded.mobileprovision:打包时候使用的,从Mac上生成的。授权文件后面会介绍
5、Frameworks:程序引用的非系统自带的Frameworks,每个Frameworks其实就是一个app,其中的结构应该和app差不多,也包含签名信息CodeResources文件。
而这里和签名有关系的就是CodeResources文件了,其中CodeResources:
看到这里发现这个文件就是一个plist,里面是对每个资源item用签名进行hash操作了之后,就可以防止篡改内容,CodeResources文件中的data是源文件先后经过SHA1摘要算法、RSA私钥教秘、BASE64编码后形成的,在安装活运行app的时候,系统会用公钥来一般验证这个app有没有被修改过,这个和Android中的MANIFEST.MF,CERT.RSA,CERT.SF文件内容的作用是一样的。
第三、查看签名信息
我们逆向改包之后一般肯定需要重新签名的,那么iOS重重新签名有手动和工具签名,这里主要有这些命令:
我们用security命令查看Mac设备中的证书信息:security find-identity -v -p codesigning
然后用命令查看ipa签名信息:codesign -vv -d example.app
如果发现没有签名,就用codesign进行签名:codesign -s [证书的MD5] example.app
codesign命令必须要注意是针对于.app文件的,不是ipa文件的,不然会发现获取签名信息失败
这里需要说明一下之前提到的各个账户类型以及两种分发方式的包签名有什么区别:
首先看一下Ad Hoc分发的包签名信息:
然后看一下In-House分发的包签名信息:
通过第一条就可以区分是Ad Hoc还是In-House分发的包了,然后我们在来看一下AppStore商店上下载的包签名信息:
看到这三条看着就很官方很正规,所以我们可以通过一个包的签名信息来区分他的分发方式。有的同学好奇为啥Xcode运行没有授权呢?用免费账号应该也需要设备证书授权呢?其实是需要的只是Xcode帮我们做了,就和AndroidStudio帮我们用debug.keystore进行apk的签名安装一样。同时Ad Hoc和In-House和正式的商店包有一个很大的区别:
Ad Hoc和In-House分发的ipa包我们解压之后查看.app包中的内容,是有和签名有关系的两个_CodeSignature/CodeResources和embedded.mobileprovision 文件,而商店下载的ipa包中只有_CodeSignature/CodeResources文件,所以有的同学从商店中下载下来的ipa没发现embedded.mobileprovision文件会觉得很奇怪,其实这里或者说的更权威一点,iOS中的签名相关的文件只有_CodeSignature/CodeResources这一个!而embedded.mobileprovision可以认为是为了证书设备管理授权的,也就是我们需要去设置->通用->描述文件和设备管理中手动信任用的。为什么要有授权描述文件?因为iOS设备默认只信任苹果签名(就是可以发布到AppStore上的账号类型签名的)的App(其他签名的App是安装不到手机上的),但是为了避免开发者真机Debug App、企业分发自己的App等需求,引入了授权描述文件,它的作用是让iOS可以安装运行来自非AppStore的App(比如公司内侧、RD在真机进行调试等)
整理我们可以了解到iOS通过_CodeSignature/CodeResources文件内容对每个包中的资源做校验看看是否有人篡改过内容,每个资源都用证书做了hash操作,同时对于代码在Mach-O文件中的签名信息:
通过上述分析可以发现,整个iOS的包签名信息分为资源和代码,对每个资源做了签名hash操作,对于可执行的二进制文件内部也有个代码签名校验,这样就可以保证应用不会被篡改了。当然我们还可以依赖于MonkeyDev这个工具自动签名,只需要把ipa放到指定目录下就可以签名安装了,具体这个工具的用法后面会介绍到。签名工具:https://github.com/maciekish/iReSign
六、开发常用工具命令
不管是正向开发还是逆向开发我们如果有一些命令会非常方便的操作,比如Android中有adb这些命令会提高很大的工作效率,关于adb常用的命令可以看这里:http://www.520monkey.com/archives/1013 当然在iOS中也是,比如我们要安装或者卸载一个应用的时候怎么操作?快速截图怎么操作?查看应用的bundleid怎么操作?这里主要用到了ideviceinstaller和libimobiledevice工具,比如安装一个ipa操作:ideviceinstaller -i xxx.ipa 还要查看应用的信息:ideviceinstaller -l
当然这里只能看到第三方安装的应用,比如要看全部的应用包括系统的,可以用frida-ios-dump命令:
还有我们需要快速截图:idevicescreenshot 查看过滤系统日志:idevicesyslog 当然这里可能没有Android中的查看当前页面信息找逆向入口的命令,需要越狱后借助Cycript工具写脚本代码获取了,这个后面会详细说明怎么用这个工具。
本文的目的只有一个就是学习逆向分析技巧,如果有人利用本文技术进行非法操作带来的后果都是操作者自己承担,和本文以及本文作者没有任何关系,本文涉及到的代码项目可以去编码美丽小密圈自取,欢迎加入小密圈一起学习探讨技术
七、总结
本文主要介绍了iOS逆向的一些基础信息,这些信息是后面逆向操作的基础,可能有的地方细节说的不清楚,但是大家大致了解一下,也有可能有的地方说的不对的地方也请指正,后面继续开始逆向操作。
《Android应用安全防护和逆向分析》
点击立即购买:京东 天猫
更多内容:点击这里
关注微信公众号,最新技术干货实时推送
转载请注明:尼古拉斯.赵四 » iOS安全逆向之旅—逆向基本知识概要介绍