Cycript简介
Cycript是Objective-C++、ES6(JavaScript)、Java等语法的混合物
可以用来探索、修改、调试正在运行的Mac\iOS APP,通过Cydia安装Cycript,即可在iPhone上调试运行中的APP
官网和文档
Cycript的各种操作介绍
Cycript的开启和关闭
- 开启cycript
cycript -p 进程ID
cycript -p 进程名称 - 取消输入:Ctrl + C
- 退出:Ctrl + D
- 清屏:Command + R
ps命令
需要安装adv-cmds,是作者自己开发的
ps命令是process status的缩写,使用ps命令可以列出系统当前的进程
列出所有的进程
ps –A
ps aux
搜索关键词
ps –A | grep 关键词
常用语法
- UIApp == [UIApplication sharedApplication]
- 定义变量:var 变量名 = 变量值
- 用内存地址获取对象:#内存地址
- 已加载的所有OC类:ObjectiveC.classes
- 查看对象的所有成员变量:*对象
- 递归打印view的所有子控件(跟LLDB一样的函数):view.recursiveDescription().toString()
- 筛选出某种类型的对象:choose(UIViewController)、choose(UITableViewCell)
封装Cycript
.cy文件编写
我们可以将常用的Cycript代码封装在一个.cy文件中
exports参数名固定,用于向外提供接口存放和使用.cy文件
将.cy文件存放到/usr/lib/cycript0.9目录下
在Cycript中引用.cy文件,并使用它提供的接口
@import XXX
MJCript
具体用法参考mjcript.cy文件
利用python打印字符
$ python
>>> print u'\u767b\u5f55'
>>> unicode('登录','UTF-8')
Reveal
Reveal是一款调试iOS程序UI界面的神器官网-下载地址
建议下载至少Reveal4版本,支持USB连接调试,速度快。低版本的只能WiFi连接调试
iPhone上安装Reveal Loader
不要安装其他源的版本,有可能不支持新版Reveal
安装完Reveal Loader后,打开【设置】,选择需要调试的APP
找到Mac的Reveal中的RevealServer文件,覆盖iPhone的/Library/RHRevealLoader/RevealServer文件
重启SpringBoard或者重启手机,可以在iPhone上输入终端命令
重启SpringBoard:killall SpringBoard
重启手机:reboot
逆向APP的思路
- 界面分析
Cycript、Reveal - 代码分析
对Mach-O文件的静态分析
MachOView、class-dump、Hopper Disassembler、ida等 - 动态调试
对运行中的APP进行代码调试
debugserver、LLDB - 代码编写
注入代码到APP中
必要时还可能需要重新签名、打包ipa
class-dump
它的作用就是把Mach-O文件的class信息给dump出来(把类信息给导出来),生成对应的.h头文件官方地址
下载完工具包后将class-dump文件复制到Mac的/usr/local/bin目录,这样在终端就能识别class-dump命令了
常用格式
- class-dump -H Mach-O文件路径 -o 头文件存放目录
- -H表示要生成头文件
- -o用于制定头文件的存放目录
在同一种架构平台下,每一条汇编指令都有与之对应的唯一的机器指令
不同的OC代码,编译出来的汇编代码可能是一样的,所以从汇编到高级语言是不可逆的
Hopper Disassmbler
能够将Mach-O文件的机器语言代码反编译成汇编代码、OC伪代码或者Swift伪代码
常用快捷键
- Shift + Option + X:找出哪里引用了这个方法
动态库共享缓存(dyld shared cache)
从iOS3.1开始,为了提高性能,绝大部分的系统动态库文件都打包存放到了一个缓存文件中(dyld shared cache)
缓存文件路径:/System/Library/Caches/com.apple.dyld/dyld_shared_cache_armX
dyld_shared_cache_armX的X代表ARM处理器指令集架构
- v6
iPhone、iPhone3G
iPod Touch、iPod Touch2 - v7
iPhone3GS、iPhone4、iPhone4S
iPad、iPad2、iPad3(The New iPad)
iPad mini
iPod Touch3G、iPod Touch4、iPod Touch5 - v7s
iPhone5、iPhone5C
iPad4 - arm64
iPhone5S、iPhone6、iPhone6 Plus、iPhone6S、iPhone6S Plus
iPhoneSE、iPhone7、iPhone7 Plus、iPhone8、iPhone8 Plus、iPhoneX
iPad5、iPad Air、iPad Air2、iPad Pro、iPad Pro2
iPad mini with Retina display、iPad mini3、iPad mini4
iPod Touch6
所有指令集原则上都是向下兼容的
动态库共享缓存一个非常明显的好处是节省内存
现在的ida、Hopper反编译工具都可以识别动态库共享缓存
动态库的加载
在Mac\iOS中,是使用了/usr/lib/dyld程序来加载动态库
dyld dyld源码
dynamic link editor,动态链接编辑器
dynamic loader,动态加载器
从动态库共享缓存抽取动态库
可以使用dyld源码中的launch-cache/dsc_extractor.cpp
将#if 0前面的代码删除(包括#if 0),把最后面的#endif也删掉
编译dsc_extractor.cppclang++ -o dsc_extractor dsc_extractor.cpp
使用dsc_extractor
./dsc_extractor 动态库共享缓存文件的路径 用于存放抽取结果的文件夹
Mach-O
Mach-O是Mach object的缩写,是Mac\iOS上用于存储程序、库的标准格式
属于Mach-O格式的文件类型有
可以在xnu源码中,查看到Mach-O格式的详细定义
EXTERNAL_HEADERS/mach-o/fat.h
EXTERNAL_HEADERS/mach-o/loader.h
常见的Mach-O文件类型
MH_OBJECT
目标文件(.o)
静态库文件(.a),静态库其实就是N个.o合并在一起MH_EXECUTE:可执行文件
.app/xxMH_DYLIB:动态库文件
.dylib
.framework/xxMH_DYLINKER:动态链接编辑器
/usr/lib/dyldMH_DSYM:存储着二进制文件符号信息的文件
.dSYM/Contents/Resources/DWARF/xx(常用于分析APP的崩溃信息)
在Xcode中查看target的Mach-O类型:Build Setting 中 Mach-O Type
Mach-O的基本结构
官方描述
一个Mach-O文件包含3个主要区域
- Header
文件类型、目标架构类型等 - Load commands
描述文件在虚拟内存中的逻辑结构、布局(描述有哪些段) - Raw segment data
在Load commands中定义的Segment的原始数据
窥探Mach-O的结构
命令行工具
file:查看Mach-O的文件类型
file 文件路径otool:查看Mach-O特定部分和段的内容
lipo:常用于多架构Mach-O文件的处理
查看架构信息:lipo -info 文件路径
导出某种特定架构:lipo 文件路径 -thin 架构类型 -output 输出文件路径
合并多种架构:lipo 文件路径1 文件路径2 -output 输出文件路径
GUI工具:MachOView
Universal Binary(通用二进制文件)
同时适用于多种架构的二进制文件
包含了多种不同架构的独立的二进制文件
因为需要储存多种架构的代码,通用二进制文件通常比单一平台二进制的程序要大
由于两种架构有共同的一些资源,所以并不会达到单一版本的两倍之多
由于执行过程中,只调用一部分代码,运行起来也不需要额外的内存
因为文件比原来的要大,也被称为“胖二进制文件”(Fat Binary)
dyld和Mach-O
dyld用于加载以下类型的Mach-O文件
- MH_EXECUTE
- MH_DYLIB
- MH_BUNDLE
APP的可执行文件、动态库都是由dyld负责加载的
脱壳加壳
什么是加壳?
利用特殊的算法,对可执行文件的编码进行改变(比如压缩、加密),以达到保护程序代码的目的
什么是脱壳?
摘掉壳程序,将未加密的可执行文件还原出来(有些人也称为“砸壳”)
脱壳主要有2种方法:硬脱壳、动态脱壳
iOS中的脱壳工具
iOS中有很多好用的脱壳工具
- Clutch:https://github.com/KJCracks/Clutch(有时候会报错)
- dumpdecrypted:https://github.com/stefanesser/dumpdecrypted/(现在最好用的)
- AppCrackr、Crackulous(基本不用了)
如何验证可执行文件是否已经脱壳?
通过Hopper查看Load Commands -> LC_ENCRYPTION_INFO -> Crypt ID的值,0代表未加密
通过otool命令行也可以:otool -l 可执行文件路径 | grep crypt
Clutch - 配置
下载最新的Release版
建议去掉版本号,改名为Clutch
将Clutch文件拷贝到iPhone的/usr/bin目录
如果在iPhone上执行Clutch指令,权限不够,赋予“可执行的权限”
Clutch – 使用
列出已安装的APP:Clutch -i
输入APP序号或者Bundle Id进行脱壳操作:Clutch -d APP序号或BundleId
脱壳成功后会生成一个ipa文件
dumpdecrypted
下载源代码,然后在源代码目录执行make指令进行编译,获得dylib动态库文件
将dylib文件拷贝到iPhone上(如果是root用户,建议放/var/root目录)
终端进入dylib所在的目录
使用环境变量DYLD_INSERT_LIBRARIES将dylib注入到需要脱壳的可执行文件(可执行文件路径可以通过ps -A查看获取)
DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib 可执行文件路径
.decrypted文件就是脱壳后的可执行文件
在使用过程中,可能会遇到以下错误
原因:对dylib所在的文件夹权限不够
解决方案:将dylib放在用户所在文件夹,比如
如果是root用户,请将dylib放在/var/root目录
如果是mobile用户,请将dylib放在/var/mobile目录