越狱检测攻防

在应用开发中,APP除了体验好之外,安全也很重要,特别是涉及到金钱的。iOS7相比之前的版本系统而言,升级了沙盒机制,封锁了几乎全部应用沙盒可以共享数据的入口。即使在越狱情况下,限制也非常多,大大增加了应用层攻击难度。比如,在iOS7之前,我们可以尝试沙盒外写文件判断是否越狱,但iOS7越狱后也无该权限,在使用老方法检测就会导致误判。那么该如何检测呢?请往下看:

首先,你可以尝试使用NSFileManager判断设备是否安装了如下越狱常用工具: /Applications/Cydia.app /Library/MobileSubstrate/MobileSubstrate.dylib /bin/bash /usr/sbin/sshd /etc/apt

但是别写成BOOL开关方法,很容易被hook

objectivec 复制代码
+(BOOL)isJailbroken{  
    if ([[NSFileManager defaultManager] fileExistsAtPath:@"/Applications/Cydia.app"]){  
        return YES;  
    }  
    // ...  
}  

攻击者可能会改变这些工具的安装路径,躲过你的判断。 那么你可以尝试打开Cydia应用注册的URL scheme:

lua 复制代码
if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"cydia://package/com.example.package"]]){  
     NSLog(@"Device is jailbroken");  
}  

但是,并不是所有的工具都会注册URL scheme,而且攻击者可以修改任何应用的URL scheme。那么你可以尝试读取下应用列表,看看有无权限获取(越狱设备是可以获取到):

objectivec 复制代码
if ([[NSFileManager defaultManager] fileExistsAtPath:@"/User/Applications/"]){  
        NSLog(@"Device is jailbroken");  
        NSArray *applist = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@"/User/Applications/"  
                                                                               error:nil];  
        NSLog(@"applist = %@",applist);  
}  

但是攻击者,也可能会hook NSFileManager的方法,让你的想法不能如愿: 那么你可以回避NSFileManager,使用stat系列函数检测Cydia等工具:

arduino 复制代码
#import <sys/stat.h>  
  
void checkCydia(void)  
{  
    struct stat stat_info;  
    if (0 == stat("/Applications/Cydia.app", &stat_info)) {  
        NSLog(@"Device is jailbroken");  
    }  
}  

但是,攻击者 又可能会利用Fishhook原理,hook了stat。 那么你可以看看stat看看是不是出自系统库,有没有被攻击者换掉:

c 复制代码
#import <dlfcn.h>  
  
void checkInject(void)  
{  
    int ret ;  
    Dl_info dylib_info;  
    int (*func_stat)(const char *, struct stat *) = stat;  
    if ((ret = dladdr(func_stat, &dylib_info))) {  
        NSLog(@"lib :%s", dylib_info.dli_fname);  
    }  
}  

如果结果不是/usr/lib/system/libsystem_kernel.dylib 的话,那么就可以肯定被攻击了。 但是,如果libsystem_kernel.dylib都是被攻击者替换掉的。。。那么你就让他随便攻击吧。。。

你可能会想,我检索一下自己的应用程序是否被链接了异常动态库。列出所有已链接的动态库:

ini 复制代码
#import <mach-o/dyld.h>  
  
void checkDylibs(void)  
{  
    uint32_t count = _dyld_image_count();  
    for (uint32_t i = 0 ; i < count; ++i) {  
        NSString *name = [[NSString alloc]initWithUTF8String:_dyld_get_image_name(i)];  
        NSLog(@"--%@", name);  
    }  
}  

通常情况下,包含越狱机的输出结果会包含字符串:Library/MobileSubstrate/MobileSubstrate.dylib

但攻击者可能会给MobileSubstrate改名,但是原理都是通过DYLD_INSERT_LIBRARIES注入动态库。 那么你可以通过检测当前程序运行的环境变量:

javascript 复制代码
void printEnv(void)  
{  
    charchar *env = getenv("DYLD_INSERT_LIBRARIES");  
    NSLog(@"%s", env);  
}  

未越狱设备返回结果是null,越狱设备就各有各的精彩了,尤其是老一点的iOS版本越狱环境。

相关推荐
腾讯TNTWeb前端团队32 分钟前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰4 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪4 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪4 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy5 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom5 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom6 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom6 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom6 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom6 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试