由于公司的业务主要是支付方面,所以之前有动力研究了些逆向相关的知识。
鉴于逆向涉及到的知识面既广且杂,而且操作流程也多,用到的工具也多。想着,不妨把操作流程
和相关知识
记录一遍,以备不时之需。(主要是被人问到了,虽然答完了,但也突然有了做这个记录的想法)
本来逆向的章节是打算等底层系列最后几篇文章结束后开始,可是既然被问到了,就没有不总结的道理。于是就有了这篇文章。
需要强调的是,逆向的初衷绝对是保护自己的app
1. 逆向涉及到的知识
涉及到的相关知识
主要从我自身学习的感受出发,觉得哪些重要,掌握了对逆向开发有帮助的我就在这里提一下。以下肯定会存在一些纰漏,望指出,后续及时更新,避免误导。
-
工具的使用(包括但不限于
砸壳工具
,dump工具
,静态分析工具
,动态调试工具
,界面分析工具
等),工具一定要会用,就算不知道对应原理只要会用也能逆向开发 -
dyld
,macho
,符号表
等包含了编译和链接相关的知识,需要分析macho
文件内容 -
ARM64
汇编的一些基础指令看得懂,部分关键方法名会被混淆,需要看汇编明白它在做什么 -
底层知识知道越多越好,主要是
hook
相关的,比如Method Swizzling
,FishHook
,InLineHook
三种hook
方法要懂 -
iOS
系统的文件结构,大概知道不同的文件目录下存储着哪些内容就行 -
动态库
的原理要知道,注入代码都是以动态库的形式 -
基本的终端操作和一点点
shell
基础,便于使用脚本快速执行 -
常见
加解密
手段和抓包
工具,网络传输数据通常会加密,获取到秘钥
是关键的步骤
2. 逆向开发流程
刚开始学的时候,也尝试搜了些相关资料,结果发现里面很多专有名词看的一头雾水,很多技术手段单看觉得还好,但不知道该怎么串起来使用,很影响学习下去的兴趣。
想来,大部分初学者多半也是会有这样的感受。我就把通常的逆向开发流程
整理下来,有兴趣的小伙伴可以对着流程一步一步的去找相关资料来研究,思路会清晰很多。(不含工具下载配置流程,这部分网上内容很多,只给出工具名和一些基本的讲解)
1.越狱
准备一台越狱手机是逆向开发的第一步。目前,越狱的方式众多,都基本都是傻瓜式操作。我个人目前使用的越狱手段是通过爱思助手
。
根据手机的系统版本选择对应的选项,如果版本较高,选择CheckRa1n
,按照提示一步步完成即可越狱。
越狱后,屏幕上多出CheckRa1n
应用程序,打开选择安装Cydia
,因为我已经安装过了,提示会不一样。
安装成功后,界面多出Cydia
应用程序。
打开Cydia
,如果正常运行说明已是越狱环境;如果闪退说明是非越狱环境。
需要注意的是,越狱分为
完美越狱
和非完美越狱
两种情况。
-
完美越狱:越狱很彻底,破解了操作系统的读写权限,完美越狱完成以后可以自由使用,开关机也不影响
-
非完美越狱:关机后会重新回到非越狱环境
目前,完美越狱只支持到iOS9
,所以大家手上的手机大部分肯定只能非完美越狱了。
但是鉴于目前越狱流程及其简单,就算是非完美越狱关机后也只要重新再越狱一次即可回到越狱环境。所以,并非要刻意的追求完美越狱。
然后需要去Cydia中安装一些插件,包括但不限于:
-
Apple File Conduit "2"
,可以获得根目录访问权限。 -
AppSync Unified
,可以绕过签名检测 -
adv-cmds
,命令行 -
OpenSSH
,远程登录 -
Frida
,砸壳
等..
2. Openssh
OpenSSH 是 SSH (Secure SHell) 协议的免费开源实现。 SSH协议可以用来进行远程控制, 或在计算机之间传送文件
逆向开发一般使用到手机和电脑两个终端,这两者使用Openssh
连接。
Openssh
的连接方式有:通过网络连接和通过USB
连接。
通过USB
连接会更稳定效率也更高,所以我常用的是USB
连接。这里连接的终端指令基本又臭又长,需要使用shell
适当简化下。
2.砸壳
分析应用的前提是要先获取应用的安装包。iOS
主要的下载渠道是appstore
,可是appstore
上下载的包苹果会对__TETX
段里面的内容进行加密,如果不解密无法做后续操作。
所以砸壳
技术就应运而生了。
砸壳分为静态砸壳和动态砸壳,主流的形式是动态砸壳。
动态砸壳的原理主要是:
虽然
macho
中的__TEXT
段被苹果加密了,但是系统如果要运行程序,肯定需要对内容进行解密。所以就不去主动的砸掉原有的加密壳,而是当应用程序运行后,壳被系统砸掉后,在内存中把砸壳后的数据取出来,也就达到了砸壳的目的。
砸壳的工具也比较多,我个人目前使用的是frida
。至于安装步骤配置啥的,网上教程也很多,这里就不说明了。
安装完来到frida-ios-dump
目录下,
通过dump.py
脚本执行对应的命令。
终端执行
./dump.py -l
会列出手上已经安装的app
,如果是运行状态,还有对应的pid
。
然后通过
./dump.py 应用名称
即可实现一行代码砸壳。
砸完壳后的包在frida-ios-dump
目录内。
区分是否砸壳的标志是
macho
中cryptid
的值是否为0
一般使用otool
指令查看对应的macho
的段和对应的值。
otool -l macho路径 | grep crypt
可以看到,cryptid
的值为0,说明这是砸壳后的macho
了。
当然也可以把macho
拖入MachoView
(查看macho
的软件)中直接查看:
来到LC_ENCRYPTION_INFO_64
段下,Crypt ID
同样是0
。
获取到包后,可以先查看包内容。里面有图片
文件,声音
文件,plist
文件,动态库信息,glsl
文件等,通过这些信息就可以对应用程序有个大致的了解了。
3. class-dump
class-dump
就是用来dump
头文件的工具,简单好用。
class-dump
的主要原理是:
编译后,
macho
中就存放着存放着类名和方法名等信息,通过内存地址的偏移,可以找到它们对应的段,然后依次输出内容,也就能获得头文件信息了。
通过指令:
class-dump -H app包路径或者app可执行文件路径 -o 输出的路径
一顿输出后,获取到了微信的头文件,有20000
多个..
随便打开一个文件看看内容,
头文件里面包括了这个类所有的属性
,方法
,协议
等关键信息,其中很多甚至可以见名知意。
有些app
会对关键属性名和方法名做混淆处理,这时候显示的就是混淆后的乱码了,遇到这种情况也不用慌,可以使用静态分析工具
大概查看它的实现逻辑,虽然麻烦些,但还是可以解决的。
4. 静态分析工具
静态分析工具是能够将macho
文件的机器语言代码反编译成汇编代码、OC伪代码或者Swift伪代码,同时可以快速查看关键字符串信息。
这就很强大了,意味着可以通过查看方法的执行流程,判断条件等信息明白它在做什么,如果本地字符串未做混淆,也可以直接被获取到(比如有些app秘钥明文存储本地,这就危险了)。
iOS主要使用的静态分析工具有Hopper
和IDA
。
IDA
更强大,它能够翻译成的伪代码更接近于高级语言,但是它的收费也是昂贵的。
Hopper
虽然不如IDA
强大,但也是够用的了,所以我个人使用的是Hopper
。
把macho文件直接拖入Hopper
,尝试搜索你感兴趣或者头文件中存在的字符,会得到如下界面:
如果你有汇编基础,能够直接分析最好,如果没有的话也不是束手无策。
或者有些经过混淆的方法名和字符串,通过静态分析是无法直接得到,这些时候就需要动态调试
的帮助了。
5. 动态调试工具
动态调试
就是将程序运行起来,通过打断点(LLDB
需要)、打印等方式,查看参数、返回值、函数调用流程等信息,通过输出界面信息迅速定位目标代码,还可以动态的修改内存和寄存器中的参数,达到绕过检测,更改执行流程等目的。
动态调试主要有LLDB
和CyCript
两种工具,两种都很好强大,也各有各的好,建议两种方式都需要学习。
LLDB
的原理是这样的:
用Xcode
启动程序的时候,就会在自动在手机上安装一个debugserver
程序,Xcode
的LLDB
工具会跟debugserver
进程进行交互,将lldb
指令传输给debugserver
进程,debugserver
进程又会将lldb
指令传输给App
,App
执行完之后,会将返回值传输给debugserver
进程,debugserver
程序又发给LLDB,在控制台显示出结果。
至于LLDB
和CyCript
的主要区别在于,LLDB
需要卡住进程进行调试,而CyCript
调试时需要进程处于活动状态。
二者也都可以提供一些高级用法,lldb
可以取别名和开发插件的形式使用,常用的指令也可以放入.lldbinit
文件;而cycript
也可以进行高级封装,对外提供简单易懂的调用名即可。
说实话,动态调试
占用逆向开发的流程的时间比重是很大的。因为逆向开发主要的工作就是分析和查找定位关键代码的行为。动态调试
的熟练程度基本决定了逆向开发的耗时。
当遇到某些内容被混淆甚至加密的情况下,掌握了动态调试
,混淆和加密基本上就失去了意义。
因为无论如何混淆和加密,在内存中总会有一个时刻需要解混淆和解密进行调用,只要捕获到这个时刻,通过动态调试
可以很轻松的获取这个时刻关键值,混淆和加密工作即使做得再花里胡哨也起不了作用。
退一步来说,比如app
里面使用了这些值做了流程判断,检测之类的,即使无法还原这些关键值,也完全可以动态调试
修改值查看不同的执行流程,如果是检测类的代码就更简单了,直接hook
后固定返回YES
。
当通过动态调试定位到关键代码,并且确定该如何修改后,就需要使用动态库写hook
代码并注入
了。
5. Hook
在ios系统中常用的hook技术有三种:
-
Cydia Substrate
-
Symbol Table
-
Method Swizzing
Cydia Substrate
的方式会修改被hook
的函数的前8个字节,使该函数跳转到我们设定的新的函数地址,这种方式叫做inline hook
,是在运行期间hook的,对应的框架是Dobby
。
Symbol Table
符号表的hook是修改符号表所指向的内存地址,在编译期就进行了交换,对应的框架是FaceBook
发布的fishHook
框架。
Method Swizzing
是ios开发常用的记录,但是逆向开发的 Method Swizzing
是有别于开发过程所使用的。开发时hook
基本是hook
系统已存在的类,而逆向开发hook
的一般是他人所写的方法,直接方法交换存在崩溃的风险,所以逆向开发底层一般使用getimp
和setimp
的处理方式。对应的是使用Theos
写tweak
的logos
语法。
iOS的代码一般包含:
-
oc方法
-
系统c函数
-
自定义c函数
这三种方式刚好对应使用上面三种hook
方式。
写好hook
代码的动态库,需要注入
到原目标应用里才能生效。
6. 代码注入
代码注入也有三种方式:
-
将动态库上传到
DynamicLibraries
目录下 -
使用
dyld
中的DYLD_INSERT_LIBRARIES
环境变量 -
使用
optool
或者yololib
工具给macho
新增Load command
需要注意的是,前两种方式必须在越狱环境才能使用;而对应用进行重签名后,就可以在非越狱环境下使用第三种方法了。
3. 总结
逆向开发的流程可以总结如下:
准备一台越狱
手机,对目标应用进行砸壳
,然后class-dump
出头文件,使用静态分析
工具对应用进行初步分析和关键内容提取,使用动态调试
工具通过界面信息等迅速定位目标代码,修改和调试关键值和流程,然后使用动态库写hook
代码,注入
目标应用,重签
应用。
越狱 --> 砸壳 --> class-dump --> 静态分析 --> 动态调试 --> hook --> 注入 --> 重签(非必须)
最后,介绍一款工具叫MonKeyDev
。它是对以上众多逆向开发工具和步骤的整合,可很快捷的实现上述一系列操作。
直接把目标应用包丢进TargetApp
目录下,写对应的logos
,就可以一步到位实现重签,注入,然后下载到手机的步骤。
以上是对逆向开发流程
和部分原理
,所涉及到的相关知识点
的整理。而涉及到具体的工具下载,配置和使用就不展开了,这些展开也有不少内容且网上教程也很多,本文的定位也只是逆向初探,了解逆向是在做什么即可,后续的章节可能会对这些内容做适当的补充。
敬请关注。