iOS 逆向(三)逆向工具

2,106 阅读5分钟

这个系列,是很早听 MJ 课程时的整理,现在分享出来。 其中一些参考资料有些有引用,有些可能忘记添加了,如果有引用部分资料,可以联系我。

iOS 逆向(一)环境搭建
iOS 逆向(二)Cycript
iOS 逆向(三)逆向工具
iOS 逆向(四)脱壳
审核中 iOS 逆向(五)Theos工具 iOS 逆向(六)动态调试
iOS 逆向(七)重签名

一、逆向流程

1.1 界面分析

  1. Cycript:界面分析语言,使用Objective-C 和 Javascript调试App。这部分已经在上一篇逆向(二)Cycript中作过论述。
  2. Reveal:界面分析工具,非常强大和方便。

1.2 代码分析

对Mach-O文件的静态分析,有以下工具:

  1. class-dump:脱壳工具,将在下一篇逆向(四)脱壳中讲述。
  2. MachOView:Mach-O查看工具
  3. Hopper Disassembler、ida是反汇编工具。能直接进行代码的改写。

1.3 动态调试

对运行中的APP进行代码调试,工具包括:

  1. debugserver:iPhone内动态调试命令行工具,将在逆向(六)动态调试
  2. LLDB:Xcode提供的调试工具。

1.4 代码编写

注入代码到APP中,必要时还可能需要重新签名、打包ipa。

具体实现,参考逆向(五)Theos工具逆向(六)动态调试

二、界面分析

Cycript在上篇文章中已经介绍。所以此处着重介绍Reveal。

2.1 软件

Mac版本

官网:revealapp.com   通过邮箱可获得14天试用期.

手机版

添加源:apt.so/codermjlee

Reveal Loader

一定要安装该源的loader。

2.2 调试

2.2.1 设置-Reveal

安装完Reveal Loader后,打开【设置】,找到Reveal,选择需要调试的APP

2.2.2 加载库

找到Mac的Reveal中的RevealServer文件,覆盖iPhone的/Library/RHRevealLoader/RevealServer文件

之后,最好重启桌面,可以在iPhone上输入终端命令

  • 重启SpringBoard:killall SpringBoard
  • 重启手机:reboot

2.2.3 调试

打开Mac版本Reveal,在手机上开启允许Reveal调试的APP,Reveal mac就会出现调试APP。

如图按照上述步骤没有连上app,问题解决 1)安装 Reveal2Loader 2) 打开Reveal选择顶部菜单Help->Show Reveal Library in Finder->iOS Library,把RevealServer.frameworkr拷贝到手机Device->Library->Frameworks文件夹下,拷贝方式可以通过iFunBox手动操作 3)重新启动手机之后可以看到app显示出来

三、代码分析

3.1 class-dump

顾名思义,它的作用就是把Mach-O文件的class信息给dump出来(把类信息给导出来),生成对应的.h头文件

下载地址见文末,下载完成后,将class-dump文件复制到Mac的/usr/local/bin目录,这样在终端就能识别class-dump命令了

常用格式

//直接在控制台输出
$ class-dump ~/Desktop/jike
//-H 表示要生成头文件
//-o 用于制定头文件的存放目录
$ class-dump  -H  Mach-O文件路径  -o  头文件存放目录
  • 注:假如在加壳应用中进行导出,只会导出一个头文件,先要进行脱壳才能导出完整的头文件列表。

3.2 Hopper Disassmbler

Hopper Disassmbler能够将Mach-O文件的机器语言代码反编译成汇编代码、OC伪代码或者Swift伪代码

另外,IDA同样是反汇编工具,作用同Hopper类似。

3.2.1  代码编译过程

不同的OC代码,编译出来的汇编代码可能是一样的

但是在同一种架构平台下,每一条汇编指令都有与之对应的唯一的机器指令

3.2.2 使用

常用快捷键

Shift + Option + X  找出哪里引用了这个方法

3.3 MachOView

MachOView是查看Mach-O文件的工具,Mach-O是苹果平台的可执行文件格式,其具体可以参考Mach-O(一)结构Mach-O(二)内存分布

该工具是开源工具,可从Github下载。

MachOExploer和MachOView功能一样,也是开源工具。Github地址

四、共享库缓存提取

在iOS中,系统库,如UIKit、Foundation等,苹果为了提高效率,将这些库都打包成一个动态库,并在系统启动的时候加载,这个集合库,就叫做共享库缓存。

我们在逆向时,为了分析代码,需要将该共享库提取出来。

4.1  dsc_extractor提取

在macOS/iOS中,是使用了/usr/lib/dyld程序来加载动态库。

dyld,dynamic link editor(动态链接编辑器),也叫dynamic loader(动态加载器)。

所以第一种方式,直接以dyld的方式提取。dyld源码地址参考文末。

下载最新代码,本文更新时,最新版本是dyld-635.2

4.1.1 编译dsc_extractor

可以使用dyld源码中的launch-cache/dsc_extractor.cpp

将#if 0前面的代码删除(包括#if 0),把最后面的#endif也删掉

最后只剩下:

#include <stdio.h>
#include <stddef.h>
#include <dlfcn.h>

typedef int (*extractor_proc)(const char* shared_cache_file_path, const char* extraction_root_path,
													void (^progress)(unsigned current, unsigned total));

int main(int argc, const char* argv[])
{
	if ( argc != 3 ) {
		fprintf(stderr, "usage: dsc_extractor <path-to-cache-file> <path-to-device-dir>\n");
		return 1;
	}
	
	//void* handle = dlopen("/Volumes/my/src/dyld/build/Debug/dsc_extractor.bundle", RTLD_LAZY);
	void* handle = dlopen("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/usr/lib/dsc_extractor.bundle", RTLD_LAZY);
	if ( handle == NULL ) {
		fprintf(stderr, "dsc_extractor.bundle could not be loaded\n");
		return 1;
	}
	
	extractor_proc proc = (extractor_proc)dlsym(handle, "dyld_shared_cache_extract_dylibs_progress");
	if ( proc == NULL ) {
		fprintf(stderr, "dsc_extractor.bundle did not have dyld_shared_cache_extract_dylibs_progress symbol\n");
		return 1;
	}
	
	int result = (*proc)(argv[1], argv[2], ^(unsigned c, unsigned total) { printf("%d/%d\n", c, total); } );
	fprintf(stderr, "dyld_shared_cache_extract_dylibs_progress() => %d\n", result);
	return 0;
}

编译dsc_extractor.cpp,获得dsc_extractor

$ clang++ -o dsc_extractor dsc_extractor.cpp

或者

    1. 直接将if 0修改为if 1
    1. 编译代码
$ clang++ -o dsc_extractor ./dsc_extractor.cpp dsc_iterator.cpp

4.1.2 使用dsc_extractor

动态库共享缓存在iPhone的目录为:/System/Library/Caches/com.apple.dyld,将其拷贝到电脑上:

然后解析出动态库:

// dsc_extractor 缓存 输出文件夹
$ dsc_extractor dyld_shared_cache_armv7s armv7s

4.2 jtool提取

工具地址:JTool

用法

//提取UIKit动态库
$ jtool -extract UIKit path/to/dyld_shared_cache

//提取全部动态库,注意,该提取动作会产生超大的文件,10G+
$ jtool -lv cache_armv7 | cut -c 24- | tail +5 | while read line ; do jtool -extract $line cache_armv7 ; done

4.3 dyld_cache_extract

dyld_cache_extract 是一个GUI工具,蛮方便的工具。

五、动态调试

5.1 MJAppTools

【越狱-逆向】处理iOS APP信息的命令行工具。MJAppTools有详细说明。

5.2 其他命令

其它常用命令,比如lldb、otool、nm、codesign。

参考

链接

  1. class-dump官网
  2. Reveal 软件
  3. dyld源码
  4. lldb
  5. MJAppTools