iOS逆向记录(二)
4.Cycript工具介绍(作者:saurik,官网:http://www.cycript.org/)
-
Cycript是一款脚本语言,可以看作是Objective-JavaScript,它可以帮助我们轻松测试和验证函数效果。
-
在越狱手机中可以通过注入方式在第三方应用中运行
-
也可以用静态库的方式把cycript集成到自己的应用(MonkeyDev,可以给非越狱iOS第三方App写插件,但是权限受沙盒限制)
-
-
在越狱手机中安装Cycript
-
在Cydia上搜索Cycript进行安装
-
apt-get install cycript
-
-
Cycript使用(注入到第三方进程空间)
- 注入Cycript模块到第三方进程
//确认进程名或者进程PID Flongers-iPhone:/ root# ps -e | grep WeChat 1368 ?? 6:17.44 /var/mobile/Containers/Bundle/Application/749DC69A-3A8D-4B5C-9926-1220E69FC85F/WeChat.app/WeChat //打开方式1 Flongers-iPhone:/ root# cycript -p WeChat cy# //打开方式2 Flongers-iPhone:/ root# cycript -p 1368 cy#
-
退出cycript
Control+D -
实战演练
//WeChat cycript -p WeChat
[[UIApplication sharedApplication] setStatusBarHidden:YES] //隐藏状态栏
[[UIApplication sharedApplication] setStatusBarHidden:NO] //显示状态栏
[[[UIAlertView alloc]initWithTitle:@"Tanzhou" message:@"Hello luz" delegate:ni cancelButtonTitle:@"ok" otherButtonTitles:nil, nil] show] //弹框
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:1000] //设置badge数字
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:1]
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]
//SpringBroad cycript -p SpringBoard
[[SBScreenShotter sharedInstance] saveScreenshot:YES] 截屏,闪光
[[SBScreenShotter sharedInstance] saveScreenshot:NO] 截屏,不闪光
[[SBScreenFlash mainScreenFlasher] flashColor:[UIColor magentaColor] withCompletion:nil] 屏幕闪紫色光
5.逆向的基本思路
-
正向工程(Forward Engineering)
抽象的逻辑设计 => 具体的物理实现设计概念和算法 => 编写源代码 => 编译成二进制机器码
将想法和设计理念变成具体实现的过程
-
逆向工程(Reverse Engineering)
具体的物理实现 => 抽象的逻辑设计
反编译机器码 => 汇编代码(类似的高级语言代码) => 理解其算法和设计概念
从二进制码中提取设计概念和算法
-
程序的编译和反编译
高级语言(C/C++/Oc/Java/Python/C#) -> 中间语言(如:汇编等) -> 目标代码(exe/lib/dll/sys/dylib等二进制文件)编译链接 高级语言 -------> 机器码 <------ 机器码 反汇编/反编译
编译链接 高级语言 ===> 机器码 <=== 反汇编/反编译
-
逆向的思路
-
逆向必须是有目的的、有针对性的(明确你要做的事情)
-
先熟悉你要逆向的目标程序,从正向的思路去猜测他可能的实现方法(使用的框架、调用的系统API等)
-
定位关键代码
-
通过监控UI事件的响应定位关键代码
-
通过监控底层API的调用定位关键代码(如网络访问接口、文件读写接口等)
-
通过观察数据的变化来定位关键代码和地址
-
逆向是一个试错的过程,需要不停的猜测、查找和进行验证,既考验耐心也考验动手能力
6.程序、进程、线程、内存结构的概念
-
程序(静态的,磁盘上)
程序是完成某个功能的指令集。程序一般是指可执行的二进制文件。 -
进程(动态的,内存中)
- 进程的概念
进程是程序的运行实例,是系统进行资源分配和调度运行的基本单位。
换句话说进程是一个容器,包含程序执行需要的代码、数据还有资源等信息。多任务的操作系统,可以同时执行多个进程。
- 进程虚拟地址空间
多任务操作系统中的每一个进程都运行在一个属于它自己的内存沙盘中,这个沙盘就是虚拟地址空间
(virtual addressspace), 在32位经典模式下,它总是一个4GB的内存地址块。这些虚拟地址通过页表(pagetable)
映射到物理内存,页表由操作系统维护并被处理器引用。每个进程都拥有一套属于它自己的页表,但是还有一个隐情,
只要虚拟地址被使能,那么它将会作用于这台机器上运行的所有软件,包括内核本身,因此,有一部分虚拟地址必须保
留给内核使用。
- 进程的概念
-
线程
轻量级进程,是进程内一个相对独立的、可调度的执行单元,是CPU调度的基本单元。 -
函数
包含某个特定功能的代码块,可以叫做子程序。 -
典型的内存空间布局
-
从低地址到高地址依次为:代码区、只读常量区、全局区/数据区、BSS段、堆区、栈区。
代码区:存放可执行指令。 只读常量区:存放字面值常量、具有常属性且被初始化的全局和静态局部变量(如:字符串字面值、被const关键字修饰的全局变量和被const关键字修饰的静态局部变量)。 全局区/数据区:存放已初始化的全局变量和静态局部变量。 BBS段:存放未初始化的全局变量和静态局部变量,并把它们的值初始化为0。 堆区:存放动态分配的内存。 栈区:自动变量和函数调用时需要保存的信息(逆向分析的重点) 补充: 代码区和只读常量区一般统称为代码段 栈区和堆区之间相对生长的,堆区的分配一般按照地址从小到大进行,而栈区的分配一般按照地址从大到小进行分配。
7.逆向工具集和安装和使用
- iOS逆向工程的工具大致可分为四类:
-
检测工具
如:Reveal、tcpdump等 -
反编译工具(反汇编工具 - 分析二进制文件并得到一些信息)
如:IDA、Hopper Disassembler、classdump等 -
调试工具
如:lldb、Cycript等 -
开发工具
如:Xcode、theos等
- class-dump
可以将Mach-O文件中的Objective-C运行时的声明的信息导出,即编写OC代码时的 .h文件。class-dump只能导出未经加密的App的头文件。classdump是对"otool -ov" 信息的翻译,以一种我们熟悉的易读的方式呈现。官网http://stevenygard.com/projects/class-dump/
-
otool工具简介
otool(object file displaying tool) :目标文件的展示工具。可以用来发现应用中使用到了哪些系统库,调用了其中哪些方法,使用了库中哪些对象及属性,它是Xcode自带的常用工具。-f print the fat headers -a print the archive header -h print the mach header -l print the load commands -L print shared libraries used -D print shared library id name -t print the text section (disassemble with -v) -p <routine name> start dissassemble from routine name -s <segname> <sectname> print contents of section -d print the data section -o print the Objective-C segment -r print the relocation entries -S print the table of contents of a library -T print the table of contents of a dynamic shared library -M print the module table of a dynamic shared library -R print the reference table of a dynamic shared library -I print the indirect symbol table -H print the two-level hints table -G print the data in code table -v print verbosely (symbolically) when possible -V print disassembled operands symbolically -c print argument strings of a core file -X print no leading addresses or headers -m don't use archive(member) syntax -B force Thumb disassembly (ARM objects only) -q use llvm's disassembler (the default) -Q use otool(1)'s disassembler -mcpu=arg use `arg' as the cpu for disassembly -j print opcode bytes -P print the info plist section as strings -C print linker optimization hints --version print the version of /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/otool
-
依赖库的查询
如: otool -L WeChart -
是否加壳
如:otool -l WeChart | grep -B 2 crypt
-
-
classdump的使用
class-dump -s -S -H /Applications/Memenet/Memenet.app/Contents/MacOS/memenet -o ./MyHeaders查看某文件夹下文件的个数,包括子文件夹里的。 ls -lR|grep "^-"|wc -l 查看某文件夹下文件夹的个数,包括子文件夹里的。 ls -lR|grep "^d"|wc -l
- dumpdecrypted 砸壳工具
下载最新源码: git clone https://github.com/stefanesser/dumpdecrypted.git
编译动态库文件(dumpdecrypted.dylib): make
定位要砸壳的StoreApp的执行文件名字TargetApp (ps -e 可以得到全路径)
定位要砸壳的StoreApp的Document目录:
cycript -p TargetApp
[[NSFileManager defaultManager]URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0]
得到路径:#"file:///var/mobile/Containers/Data/Application/986376B5-EF08-4CAF-81FB-CAE48D1FE4AE/Documents/"
进入Document目录: cd /var/mobile/Containers/Data/Application/986376B5-EF08-4CAF-81FB-CAE48D1FE4AE/Documents/
拷贝dumpdecrypted.dylib: cp dumpdecrypted.dylib .
DYLD_INSERT_LIBRARIES=dumpdecrypted.dylib /var/mobile/Containers/Bundle/Application/749DC69A-3A8D-4B5C-9926-1220E69FC85F/WeChat.app/WeChat
- theos(作者:@DHowett)
越狱开发工具包
-
xcode工具集的路径需要设置正确
查看命令: xcode-select --print-path设置命令: xcode-select --switch /Applications/Xcode-beta.app/Contents/Developer
-
通过github安装theos
https://github.com/theos/theos/wiki/Installation -
修改所有者
sudo chown -R $(id -u):$(id -g) theostheos维基百科:
http://iphonedevwiki.net/index.php/Theos/Setup#For_Mac_OS_X
http://iphonedevwiki.net/index.php/Theos -
环境变量
export THEOS=/opt/theos可以写入~/.bash_profile
source ~/.bash_profileecho $THEOS
-
ldid(作者:saurik )
维基百科:http://iphonedevwiki.net/index.php/Ldid越狱iPhone下的签名工具(更改授权entitlements),可以为thos开发的程序进程签名(支持在OS X和iOS上运行)。
-
安装ldid
$ brew install ldid fakeroot -
加密算法
-
对称加密算法:RC4、DES、3DES、AES128、AES256等。加解密双方密钥相同。
-
非对称加密算法:RSA、Elgamal等。加解密双方使用密钥对。
-
哈希算法:MD5(16Byte)、SHA1(20Byte)等。任意长度的信息转换成到某一固定长度的信息摘要(具有唯一性,不可逆性),主要作用是对数据数据完整性校验。
-
数字签名 (苹果官方的私钥签名,公钥验证)
- 数字签名是非对称密钥加密技术与数字摘要技术的应用。对指定信息使用哈希算法,得到一个固定长度的信息摘要,然后再使用 私钥 (注意必须是私钥)对该摘要加密,就得到了数字签名。
-
数字证书
数字证书是一个文件,由苹果的 Apple Worldwide Developer Relations Certification Authority(WWDR)证书认证中心进行签名,其的主要作用是用来标示身份。证书文件主要包含两部分内容:证书信息和证书签名-
证书信息
包含用户的公钥、用户个人信息、证书颁发机构信息、证书有效期等信息。(这里的用户主要指开发者) -
证书签名
WWDR将上述证书本身内容的使用哈希算法得到一个固定长度的信息摘要,然后使用自己的私钥对该信息摘要加密生成数字签名。 -
证书的验证
iOS系统原本就持有WWDR的公钥,系统首先会对证书内容通过指定的哈希算法计算得到一个信息摘要;然后使用WWDR的公钥对证书中包含的数字签名解密,从而得到经过WWDR的私钥加密过的信息摘要;最后对比两个信息摘要,如果内容相同就说明该证书可信。在验证了证书是可信的以后,iOS系统就可以获取到证书中包含的开发者的公钥,并使用该公钥来判断代码签名的可用性了。 -
证书存在的意义
通过证书使用过程可以看出,证书本身只是一个容器,用来承载开发者的公钥。iOS通过验证证书的合法性来确保开发者公钥的合法性。
-
-
代码签名与验证(开发者的私钥签名,公钥验证)
打包过程中使用开发者私钥对应用进行签名。开发者的公钥被包含在数字证书里,数字证书又被包含在描述文件(Provisioning File)中,描述文件在应用被安装的时候会被拷贝到iOS设备中。iOS安全系统通过证书就能够确定开发者身份,就能够通过从证书中获取到的公钥来验证开发者用该公钥对应的私钥签名后的代码、资源文件等有没有被更改破坏,最终确定应用能否合法的在iOS设备上合法运行。
-
工具的使用
查看codesign load command otool -l WeChat | grep -A 5 SIGNATURE 查看签名信息 ➜ tmp codesign -dvvv WeChat Executable=/private/tmp/WeChat Identifier=com.tencent.xin Format=Mach-O universal (armv7 arm64) CodeDirectory v=20200 size=448783 flags=0x0(none) hashes=14017+5 location=embedded Hash type=sha256 size=32 CandidateCDHash sha1=6e2f8a93dbe63c17ea3b3a3dc032826b9eddf2b7 CandidateCDHash sha256=d6f1afe23b598a76301711a4a62a5505a749a12a Hash choices=sha1,sha256 CDHash=d6f1afe23b598a76301711a4a62a5505a749a12a Signature size=3925 Authority=Apple iPhone OS Application Signing Authority=Apple iPhone Certification Authority Authority=Apple Root CA Info.plist=not bound TeamIdentifier=88L2Q4487U Sealed Resources=none Internal requirements count=1 size=96 查看entitlement内容 codesign -d --entitlements - WeChat ldid -e WeChat 修改entitlement内容 ldid -Sentitlement.xml WeChat
-
dpkg工具
-
安装
$ brew install --from-bottle https://raw.githubusercontent.com/Homebrew/homebrew-core/7a4dabfc1a2acd9f01a1670fde4f0094c4fb6ffa/Formula/dpkg.rb
$ brew pin dpkg
- 使用
dpkg -i/-r deb包安装/卸载
dpkg -s com.iosre.myiosreproject 查看安装包信息