越狱开发1-基础工具使用

简单介绍一下常用的越狱开发时使用的工具

2016-11-12 | 阅读

越狱开发的一些工具和基础知识的介绍

为了提升APP的安全性, 需要学习一下越狱开发, 了解在越狱环境下,开发者能够做到什么样的效果, 有哪些常用的工具与攻击 , 以及相应的应对方法. 这两篇文章,本篇介绍一些基础的工具与知识, 下一篇介绍最常见的攻击方式,二次打包的细节.

OpenSSH

对于越狱手机, 可以直接通过 ssh登录设备,直接运行,ssh root@ip , 而默认密码是 alpine

OpenSSH的安装,可以在Cydia上搜索,直接安装.

连接到手机后, 就可以用 unix的命令去查询用户信息了。如使用ps aux来查看当前进程信息.

Class-Dump-z 导出头文件

下载class-dump-z,该可执行文件, 可以放在手机中, 也可以放在电脑中。 一般使用方式为 :

$ class-dump-z ktv > ktv.txt       //导出所有内容到文件
$ class-dump-z -H ktv -o ktvdir/   //导出所有内容目录到文件夹(首先要创建ktvdir文件夹)

但,如果直接去dump appstore下载的应用,出现的是乱码,因为appstore上得应用,会被加密以加上一层壳, 所以,我们需要去砸壳。

使用Clutch 进行解密

下载Clutch

一般在越狱手机上使用,原理是运行时注入动态库,以获取app解密后的可执行文件。

然后先使用

Clutch -i  # 查看所有安装应用

然后使用

Clutch -d xx # 来破解 xx对应上述序号的APP, 并输出到指定位置。 

输出完 ,会提示破解后的文件位置, 下载下来就可以使用dump查看头文件了。

Cycript

Cycript 是一个能够理解Objective-C语法的javascript解释器, 它能够挂钩正在运行的进程, 以在运行时修改很多东西, 一般我们用于动态调试应用, 一般来说如果要调试的代码是用OC编写的,用cycript调试会很方便, 如果是用C编写的,就得通过lldb来调试了.

在官网 http://www.cycript.org 下载Cycript , 将文件传送到手机上,同时也需要将 Cycript.lib传到相同路径。 然后就可以使用了。

我们尝试去挂钩桌面 : cycript -p SpringBoard , SpringBoard就是系统的桌面, 挂钩上桌面后, 我们就可以做任何操作了, 如我们弹一个框 :

iPhone:/usr/bin root# cycript -p SpringBoard
cy# var alert = [[UIAlertView alloc] initWithTitle:@"biaoti" message:@"Hello World" delegate:nil cancelButtonTitle:@"quxiao" otherButtonTitles:nil]
#"<UIAlertView: 0x1413633a0; frame = (0 0; 0 0); layer = <CALayer: 0x174a2bce0>>"
cy# [alert show]

这个时候, 我们就发现桌面上突然弹出了一个莫名其妙的弹框 。

cycript的原理是动态库注入,但是其动态库注入的原理,与我们常见的通过LC_LOAD_DYLIB在可执行文件中注入动态库不同. cycript的操作是 : 抓取到要挂载的应用, 由于越狱机上拥有权限,所以直接在挂载的进程上创建一个挂起的线程, 然后在这个线程里申请一片用于加载动态库的内存,然后恢复线程,动态库就被注入。

一般使用 ps aux | grep XXAPP 来查找到APP ,然后根据pid来进行依附。

cycript是一个极其强大且便利的工具,下面是一些在cycript中常用的命令 :

  • choose : a = choose(MyClass) ,返回值是一个 数组,表示在当前堆栈中查找到的所有MyClass类的对象数据。
  • #address : 根据地址获取对象。
  • MS.HookMessage : hook OC函数, 这个函数的实现是调用MSHookMessageEx ,用法如下 :

      cy# @import com.saurik.substrate.MS
      cy# var oldm = {};
      cy# MS.hookMessage(NSObject, @selector(description), function() {
              return oldm->call(this) + " (of doom)";
          }, oldm)
      cy# [new NSObject init]
      #"<NSObject: 0x100203d10> (of doom)"
    
  • MS.hookFunction : 替换C函数 :

      cy# @import com.saurik.substrate.MS
      cy# extern "C" void *fopen(char *, char *);
      cy# var oldf = {}
      cy# var log = []
      cy# MS.hookFunction(fopen, function(path, mode) {
              var file = (*oldf)(path, mode);
              log.push([path.toString(), mode.toString(), file]);
              return file;
          }, oldf)
      cy# fopen("/etc/passwd", "r");
      (typedef void*)(0x7fff774ff2a0)
      cy# log
      [["/etc/passwd","r",(typedef void*)(0x7fff774ff2a0)]]
    

使用 KeyChain Dumper 导出KeyChain中的数据

iOS的keychain提供了一种安全的保存私密信息(密码,序列号,证书等)的方案, 但是,在越狱环境下并不安全, 事实上, 非越狱环境, 普通存储区域就已经足够安全了。

从Keychain中导出数据的最流行工具是Keychain dumper。下载地址

使用该工具,需要确保 保存在 /private/var/Keychains/keychain-2.db 的文件可以被读取。

使用Snoop-it分析应用

Snoop-it允许我们进行运行时分析和对iOS应用进行黑盒安全评估。官网为 https://code.google.com/p/snoop-it/

添加源 http://repo.nesolabs.de ,以直接在越狱手机上下载安装snoop-it

打开应用, 进入设置页面, 通过这个网址,我们就可以在电脑上的浏览器去监控应用, 我们可以将验证关闭。

然后打开应用在前台,在浏览器上访问这个网站。

但不支持64位系统, 所以最新的手机,都不能使用了。

使用 introspy 追踪应用

下载 https://github.com/iSECPartners/Introspy-iOS/releases ,然后上传到设备, 使用 dpkg -i 来安装。

安装后,需要重启一下设备, 然后进入设置页面, 就可以看到两个多出来的选项, 一个是 Introspy-Apps 一个是Introspy-Settings

选择需要监控的 APP, 重启该APP 就可以进行监控。 在设置中,有说明打日志到Console, 但并未发现日志,只能去文件目录去寻找日志。

应用程序在/var/mobile/Containers/Data/Application ,让在这个路径下查找 find -name "introspy*" 以列出所有收集的日志。 但是日志是db形式, 不方便直观的查看。

我们使用Introspy-Analyzer 把数据库解析成一个直观的 report.html打开。这个工具 : https://github.com/iSECPartners/Introspy-Analyzer

安装 :

sudo  pip install git+https://github.com/iSECPartners/Introspy-Analyzer.git

然后使用命令

python -m introspy -p ios -o output -f 10.75.94.118

这个时候会以 mobile账号进行登录, 密码依旧是 alpine , 直接就可以从设备分析数据, 输出html分析报告到output文件夹下, 如 :

这个的原理也是动态库注入。

Reveal 安装与使用

Reveal是一个界面调试工具,可以让我们直接查看APP的界面布局结构,界面分析对于逆向工程也是极其重要的。

使用方式:直接在cydia中搜索和安装Reveal Loader,然后在设置中打开开关。 去官网下载最新的APP,然后将手机和电脑置于一个网络中,就可以查看其他APP的界面结构了。

Mach-o 文件结构

windows下可执行文件是 PE格式, 而OSX和iOS下可执行文件是 Mach-O格式。逆向工程必须要熟悉Mach-o文件结构。

Mach-O文件包括三个区域 :

  • 头部 header structure
  • 加载命令 load command
  • segment 。 可以拥有多个段, 每个段拥有多个 section。 每个segment 都有一段虚拟地址映射到进程的地址空间。

完整的Mach-o文件的末端是链接信息, 其中包含了动态加载器,用来链接可执行文件或者依赖库所需要的符号表,字符串表等等。

我们可以用 otool查看Mach-o的头部 ,也可以用-V获取翻译版。

 otool -h class-dump-z 
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
 0xfeedface       7          3  0x00           2    12       1564 0x00018085
 otool -h -V class-dump-z
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
   MH_MAGIC    I386        ALL  0x00     EXECUTE    12       1564   NOUNDEFS DYLDLINK TWOLEVEL WEAK_DEFINES BINDS_TO_WEAK
  • magic : 是mach-o文件的魔数, 0xfeedface 表示32位,0xfeedfacf表示64位 , 0xcafebabe 表示跨处理架构的通用格式,即fat版本。
  • cputypecpusubtype表示 CPU的类型和子类型
  • filetype ,2 , 表示可执行文件
  • ncmds 表示 load commands数量
  • sizeofcmds 表示 load commands的总字节大小。
  • flags 表示各种标记。

load commands

头部之后,就是load commands , 其数量和大小已经在header中给出。我们通过 otool -lv 整个文件,有 :

load command的结构,可能包含以下信息 :

1.cmd 是load command的类型 2.cmdsize 代表load command的大小。 3.segname 16字节的段名字。 4.vmaddr 段的虚拟内存起始地址 5.vmsize 段的虚拟内存大小 6.fileoff 段在文件中的偏移量 7.filesize 段在文件中的大小 8.maxprot 段页面所需要的最高内存保护(4=r,2=w,1=x) 9.initprot 段页面初始的内存保护 10.nsects 段中包含section的数量 11.flags 其他杂项标志位

segment

结构为 :

struct section { 
    char sectname[16];  // `__test`表示是主程序代码
    char segname[16];  // 表示section所属 `segment`名,第一个是 `__TEXT` 。 
    uint32_t addr; // 内存中开始位置
    uint32_t size;  // section大小
    uint32_t offset;  // 偏移
    uint32_t align;  // 字节对齐大小
    uint32_t reloff;  // 重定位入口的文件偏移
    uint32_t nreloc; // 重定位入口数量
    uint32_t flags;  
    uint32_t reserved1; // 最后两项保留用。
    uint32_t reserved2;
};

segment的命名是 双下划线,加大写字母。 而section是双下划线加小写字母。

然后通过otool -s来查看某个segmentsection otool -s __TEXT __text class-dum

使用otool -t查看代码段的反汇编代码

我们可以发现, 在mach-o ,有两个结构 __objc_classname__objc_methname

分别存放了类名和方法名的数据。可以看到整个应用中所有的类名和方法名 :

每一个类的虚拟地址保存在 __objc-classlist中。

虚拟地址,相对虚拟地址 和文件偏移地址。这些地址的概念是在PE或者Mach-o这样的可执行文件中存在的。

  • 虚拟地址 VA : 表示 可执行文件的一条数据或者命令 被映射到内存后的地址
  • 相对虚拟地址 RVA : 表示映射到内存后的地址相对于 映射基址的偏移量, 即 VA减去映射基址的差值。
  • 文件偏移地址 FileOffset : 可执行文件存储在磁盘上时, 存储地址相对于可执行文件头的偏移量。

上述中还有一个特殊的地址,是 映射基址 Image Base :表示 可执行文件装入内存的期望基地址, 如EXE文件的基址是 0x00400000 而DLL文件的基址为 0x10000000 。