越狱检测/越狱检测绕过——xCon
一直忽略了越狱检测与越狱检测绕过的问题,因为我认为在app争抢装机率的环境下,是不会在乎对方的设备越狱与否的。但很显然,我忽略了一个问题,app在设计的时候或许会依照设备是否越狱而采取不同的流程,比如说对越狱的设备采取更多的安全措施,在这种场景下,越狱检测是否可靠就成为了关键问题。本篇文章主要介绍越狱检测的常见方法(并配有相应的测试代码),以及最流行的越狱检测绕过插件xCon(会分析该工具会绕过哪些检测方法),最后总结了个人认为的比较可靠的越狱检测方法。
一、越狱检测
(一)《Hacking and Securing iOS Applications》这本书的第13章介绍了以下方面做越狱检测
1. 沙盒完整性校验
xCon对此种方法有检测
。

2. 文件系统检查
(1)检查常见的越狱文件是否存在
stat函数
来判断以下文件是否存在
/Library/
MobileSubstrate
/
MobileSubstrate
.
dylib
最重要的越狱文件,几乎所有的越狱机都会安装
MobileSubstrate
/
Applications
/
Cydia
.
app
/
/
var
/
lib
/
cydia
/
绝大多数越狱机都会安装
/
var
/
cache
/
apt
/
var
/
lib
/
apt
/
etc
/
apt
/
bin
/
bash
/
bin
/
sh
/
usr
/
sbin
/
sshd
/
usr
/
libexec
/
ssh
–
keysign
/
etc
/
ssh
/
sshd_config
代码如下
:
错误代码:
ENOENT 参数file_name指定的文件不存在
ENOTDIR 路径中的目录存在但却非真正的目录
ELOOP 欲打开的文件有过多符号连接问题,上限为16符号连接
EFAULT 参数buf为无效指针,指向无法存在的内存空间
EACCESS 存取文件时被拒绝
ENOMEM 核心内存不足
ENAMETOOLONG 参数file_name的路径名称太长
struct stat {
dev_t st_dev; //文件的设备编号
ino_t st_ino; //节点
mode_t st_mode; //文件的类型和存取的权限
nlink_t st_nlink; //连到该文件的硬连接数目,刚建立的文件值为1
uid_t st_uid; //用户ID
gid_t st_gid; //组ID
dev_t st_rdev; //(设备类型)若此文件为设备文件,则为其设备编号
off_t st_size; //文件字节数(文件大小)
unsigned long st_blksize; //块大小(文件系统的I/O 缓冲区大小)
unsigned long st_blocks; //块数
time_t st_atime; //最后一次访问时间
time_t st_mtime; //最后一次修改时间
time_t st_ctime; //最后一次改变时间(指属性)
};
使用底层的
c
函数
stat
函数
来判断以下路径名,路径名做编码处理(不要使用
base64
编码),千万不要使用
NSFileManager
类,会被
hook
掉
(2) /etc/fstab文件的大小
stat函数
获得该文件的大小。在iOS 5上,未越狱的该文件大小未80字节,越狱的一般只有65字节。
代码如下
:

803705776 ;
卸载xCon后在越狱设备上运行,result的大小为
66
xCon对此种方法有检测,不能采用这种办法
(3)检查特定的文件是否是符号链接文件
lstat函数
,检测/Applications的属性,看是目录,还是符号链接。如果是符号链接,则能确定是越狱设备。

代码如下:

(二)http://theiphonewiki.com/wiki/index.php?title=Bypassing_Jailbreak_Detection 给出了以下6种越狱监测方法
1、检测特定目录或文件是否存在
或者采用底层的C函数,例如fopen(),
stat()
or access()
与
《Hacking and Securing iOS Applications》
的方法2文件系统检查相同
xCon对此种方法有检测
2、检测特定目录或文件的文件访问权限
检测文件系统中特定文件或目录的unix文件访问权限(还有大小),越狱设备较之未越狱设备有太多的目录或文件具备写权限
xCon对此种方法有检测
3、检测是否能创建子进程
与
《Hacking and Securing iOS Applications》
的方法1
沙盒完整性检查
相同
4、检测能否执行ssh本地连接
xCon对此种方法有检测
5、检测system()函数的返回值

6、检测dylib(动态链接库)的内容
这种方法是目前最靠谱的方法,调用
_dyld_image_count
()和
_dyld_get_image_name()来看当前有哪些dylib被加载
#include
<string.h>
#import
<mach-o/loader.h>
#import
<mach-o/dyld.h>
#import
<mach-o/arch.h>
void
printDYLD
()
{
//Get count of all currently loaded DYLD
uint32_t
count
=
_dyld_image_count
();
for
(
uint32_t
i
=
0
;
i
<
count
;
i
++)
{
//Name of image (includes full path)
const
char
*
dyld
=
_dyld_get_image_name
(
i
);
//Get name of file
int
slength
=
strlen
(
dyld
);
int
j
;
for
(
j
=
slength
–
1
;
j
>=
0
;
—
j
)
if
(
dyld
[
j
]
==
‘/’
)
break
;
printf
(
“%s\n”
,
dyld
);
}
printf
(
“\n”
);
}
int
main
(
int
argc
,
char
*
argv
[])
{
printDYLD
();
NSAutoreleasePool
*
pool
=
[[
NSAutoreleasePool
alloc
]
init
];
int
retVal
=
UIApplicationMain
(
argc
,
argv
,
nil
,
nil
);
[
pool
release
];
return
retVal
;
}
下图显示了我的iOS设备当前加载的dylib的路径,最下面就可以看到xCon

二、越狱检测绕过——xCon
/Library/MobileSubstrate/DynamicLibraries目录下

DANI
–
LEE
–
2
:
iostools danqingdani$ otool
–
tV xCon
.
dylib
>
xContextsection
可以根据文件中的函数名,同时结合该工具的原理以及越狱检测的一些常用手段
(文章第一部分有介绍)
来猜其逻辑,例如越狱检测方法中的文件系统检查,会根据特定的文件路径名来匹配,我们可以使用strings查看文件中的内容,看看会有哪些文件路径名。
DANI
–
LEE
–
2
:
IAP tools danqingdani$ strings xCon
.
dylib
>
xConReadable
以下是xCon中会匹配的文件名
/usr/
bin
/
sshd
/
usr
/
libexec
/
sftp
–
server
/
usr
/
sbin
/
sshd
/
bin
/
bash
/
bin
/
sh
/
bin
/
sw
/
etc
/
apt
/
etc
/
fstab
/
Applications
/
blackra1n
.
app
/
Applications
/
Cydia
.
app
/
Applications
/
Cydia
.
app
/
Info
.
plist
/
Applications
/
Cycorder
.
app
/
Applications
/
Loader
.
app
/
Applications
/
FakeCarrier
.
app
/
Applications
/
Icy
.
app
/
Applications
/
IntelliScreen
.
app
/
Applications
/
MxTube
.
app
/
Applications
/
RockApp
.
app
/
Applications
/
SBSettings
.
app
/
Applications
/
WinterBoard
.
app
/
bin
/
bash
/
Applications
/
Cydia
.
app
/
Library
/
LaunchDaemons
/
com
.
openssh
.
sshd
.
plist
/
Library
/
Frameworks
/
CydiaSubstrate
.
framework
/
Library
/
MobileSubstrate
/
Library
/
MobileSubstrate
/
/
Library
/
MobileSubstrate
/
DynamicLibraries
/
Library
/
MobileSubstrate
/
DynamicLibraries
/
/
Library
/
MobileSubstrate
/
DynamicLibraries
/
LiveClock
.
plist
/
Library
/
MobileSubstrate
/
DynamicLibraries
/
Veency
.
plist
/
Library
/
MobileSubstrate
/
DynamicLibraries
/
xCon
.
plist
/
private
/
var
/
lib
/
apt
/
private
/
var
/
lib
/
apt
/
/
private
/
var
/
lib
/
cydia
/
private
/
var
/
mobile
/
Library
/
SBSettings
/
Themes
/
private
/
var
/
stash
/
private
/
var
/
tmp
/
cydia
.
log
/
System
/
Library
/
LaunchDaemons
/
com
.
ikey
.
bbot
.
plist
/
System
/
Library
/
LaunchDaemons
/
com
.
saurik
.
Cydia
.
Startup
.
plist
NzI0MS9MaWJyYXJ5L01vYmlsZVN1YnN0cmF0ZQ
==
(
对应
7241
/
Library
/
MobileSubstrate
)
通过分析,xCon会绕过以下越狱检测方法
(1)
根据是否存在特定的越狱文件,及特定文件的权限是否发生变化来判断设备是否越狱
fileExistsAtPath:
fileExistsAtPath:isDirectory:
filePermission:
fileSystemIsValid:
checkFileSystemWithPath:forPermissions:
mobileSubstrateWorkaround
detectIllegalApplication:
(2)
根据
沙箱完整性检测设备是否越狱
canUseFork
(3)
根据文件系统的分区是否发生变化来检测设备是否越狱
partitionsModified
(4)
根据是否安装
ssh
来判断设备是否越狱
ssh
root@127.0.0.1
(1)检查常见的越狱文件是否存在,使用stat(),检查以下文件是否存在
/Library/
MobileSubstrate
/
MobileSubstrate
.
dylib
最重要的越狱文件,几乎所有的越狱机都会安装
MobileSubstrate
/
Applications
/
Cydia
.
app
/
/
var
/
lib
/
cydia
/
绝大多数越狱机都会安装
/
var
/
cache
/
apt
/
var
/
lib
/
apt
/
etc
/
apt
/
bin
/
bash
/
bin
/
sh
/
usr
/
sbin
/
sshd
/
usr
/
libexec
/
ssh
–
keysign
/
etc
/
ssh
/
sshd_config
(2)检查特定的文件是否是符号链接文件,使用lstat(),检查以下文件是否为符号链接文件
/Applications
/
Library
/
Ringtones
/
Library
/
Wallpaper
/
usr
/
include
/
usr
/
libexec
/
usr
/
share
(3)检差dylib(动态链接库)的内容,使用
_dyld_image_count与
_dyld_get_image_name,检查是否包含越狱插件的dylib文件