Shadow包地址:https://github.com/jjolano/shadow/releases/download/v2.0.x%40old/me.jjolano.shadow_2.0.20_iphoneos-arm.deb
分析工具:IDA 7.0
基本思路
在分析越狱工具shadow之前,所有越狱工具都是对进程进行注入挂钩来实现。注入从作用范围来看,分为两类:
-
用户态注入,通过动态库
-
内核态注入,通过驱动
根据https://developer.apple.com/documentation/driverkit/requesting_entitlements_for_driverkit_development 来看,在苹果系统开发驱动,需要苹果授权,所以,越狱工具是没办法走这条路,只可能进行用户态注入。
那么,分析它就需要对进程启动时如何加载动态库了解,这就涉及到iOS进程启动模型。
本文的思路如下:
-
iOS进程启动模型
-
依赖分析
-
钩子点分析
-
检测
iOS进程启动模型
iOS也是Unix族的衍生类。在Unix族里,进程启动模型的都大致如下:
-
加载执行文件:从绝对路径或相对路径或从环境变量指定搜索的路径搜索出来
-
根据执行文件依赖(导入表)来加载动态库文件:从绝对路径或相对路径或从环境变量和系统配置指定的搜索路径搜索出来
-
完成所有符号匹配,启动进程
-
进程处理输入参数和相应配置文件
从上面来看,只有1,2两步才可能进行注入。
在Unix族里,和执行文件加载相关的环境变量一般是**PATH
** ,它一般是执行路径的列表,如/bin
, /usr/bin
, 和/usr/local/bin
等,这个环境变量一般可以设置。搜索顺序是按照列表元素先后顺序进行,一旦找到,立马停止搜索。假设这个环境变量设置是这样的
PATH=/bin:/usr/bin:/usr/local/bin
这些路径都有一个ls
执行文件,当执行ls
时,只会执行/bin/ls
。
如果越狱工具要在这一步注入,它必须构建一个沙箱,接管所有程序执行。这种方式,所有用户态进程都可以变成它的子进程,这个沙箱可以任意更改子进程的环境变量,完成静态注入,甚至可以通过ptrace之类的系统调用来进行动态注入。这种方式可以非常好地绕过各种越狱检测工具的检测。
在Unix族,和动态库加载相关的环境变量和系统配置,就各有各的不同。Linux的可以看一下https://man7.org/linux/man-pages/man8/ld.so.8.html, 而iOS则可见https://web.archive.org/web/20160409091449/https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/dyld.1.html
从上面可以看到iOS依次对下面这些环境变量包含的路径列表按照先后顺序遍历,一旦找到相应动态库,立马停止该次遍历,查找下一个:
-
DYLD_INSERT_LIBRARIES
-
DYLD_VERSIONED_FRAMEWORK_PATH
-
DYLD_FRAMEWORK_PATH
-
DYLD_LIBRARY_PATH
-
DYLD_FALLBACK_FRAMEWORK_PATH
-
DYLD_FALLBACK_LIBRARY_PATH
目前不少APP检测iOS是否越狱,都是做下列动作:
-
访问root才能够访问的目录和文件,执行读或写
-
执行root才能够执行的命令
-
访问或更改root才能够访问的环境变量
-
调用root才能够调用的系统调用
-
访问root才能够访问的系统参数
根据上面进程启动模型分析,越狱工具要具有反检测的能力,必须要做这样事情:
-
保护环境变量的访问
-
禁止某些命令的执行
-
禁止某些路径访问
-
禁止某些系统参数访问
-
挂钩某些系统调用
依赖分析
根据上面的探究后,我们实际上看一下这个越狱工具是怎样的。
把me.jjolano.shadow_2.0.20_iphoneos-arm.deb
解压的目录大致如下
PS D:\Library> Get-ChildItem -Recurse
目录: D:\Library
Mode LastWriteTime Length Name
---- ------------- ------ ----