IOS逆向(二)-绕过某租车app越狱和代理检测

IOS逆向(二)-绕过某租车app越狱和代理检测

因为日常使用shadowrocket,所以每次打开某租车app都会提示检测到手机开了代理,并且在越狱设备上打开还会直接闪退。如何绕过app的代理和越狱检测呢?

难度

★★☆☆☆

工具环境

  • 越狱IOS 14.4
  • frida-ios-dump
  • frida
  • frida-trace
  • IDA 7.7

IDA逆向分析

通过砸壳得到app的maco文件,直接扔进ida里面分析。既然app做了越狱检测,那么先直接搜索 jail 相关的函数名。

确实存在越狱检测的函数,通过检查一些特定的文件和目录是否存在来判断设备是否已经越狱。”Cydia.app”是一个在越狱设备上常见的应用商店,而”/bin/bash”和”/usr/sbin/sshd”则表示设备已经获得了全面的文件系统访问权限。

检测的过程是通过NSFileManager的fileExistsAtPath:方法来实现的。如果检测到任何一个文件或目录存在,函数就会返回1,表示设备已经越狱。如果所有的文件和目录都不存在,函数就会返回0,表示设备没有越狱。

frida-trace hook越狱函数

看到这里大家可能会想到,那我直接用frida来hook越狱检测函数 +[_priv_NBSProbe isJailBreak] 不就可以了?

一开始我也是这样想的,所以直接用frida-trace进行hook。

frida-trace -U -f  com.szzc.szzc -m "+[_priv_NBSProbe isJailBreak]"

修改hook代码如下,替换函数返回值为0绕过检测。

{
  onEnter(log, args, state) {
    log(`进入 +[_priv_NBSProbe isJailBreak] 检测函数`);
    log(args[0]);
  },
  onLeave(log, retval, state) {
    log('退出 +[_priv_NBSProbe isJailBreak] 检测函数');
    retval.replace(0);
  }
}

程序在进入该函数之前,已经退出了。说明是app还有其他的检测函数在该函数之前先执行并退出了。

定位程序退出的堆栈

如何定位程序退出时的堆栈?可以通过frida-trace来hook系统的exit或abort函数。

frida-trace -U -i "exit" -i "abort" -f com.szzc.szzc

并添加exit的js代码如下:

{
  onEnter(log, args, state) {
    log(`exit(status=${args[0]})`);
    log('exit() called from:\n' +
    Thread.backtrace(this.context, Backtracer.ACCURATE)
    .map(DebugSymbol.fromAddress).join('\n') + '\n');
  },
  onLeave(log, retval, state) {
  }
}

frida打印程序退出时的堆栈,可以看到是在0x275d4b8的偏移地址执行退出的。

IDA分析程序退出的堆栈

这里解释一下frida打印的三个地址的含义。

0x1047994b8 WCCApp!0x275d4b8 (0x10275d4b8)
  • 0x1047994b8 是程序在内存中实际的内存地址,因为存在地址空间布局随机化(ASLR),运行看到的地址都是相对于程序的基址的偏移,这个基址在每次运行时都会改变。
  • 0x275d4b8 是该函数相对于基址的偏移地址
  • 0x10275d4b8 是该函数在IDA中的地址,因为IDA的默认基址为0x100000000,0x10275d4b8 = 0x100000000 + 0x275d4b8

在IDA中来到0x10275d4b8的地址。

发现没有并不是判断异常的代码逻辑,来到堆栈的上一层0x100007464

这里有几十个判断逻辑,可以看到越狱检测的和代理检测都有,应该是所有的检测都放到了一起,依次检测判断。从字符串可以推断是app集成了爱加密的sdk。

frida 踩坑

那么是否直接hook 0x7464 地址就行呢?

frida -U -l wcc.js -f com.szzc.szzc

wcc.js 代码如下:

var baseAddr = Module.findBaseAddress('WCCApp');
var offsetAddr = 0x7464 // 0x100007464
var targetAddr = baseAddr.add(offsetAddr); 

console.log("WCCApp 基址: " + baseAddr);
console.log("目标函数地址: " + targetAddr);

Interceptor.attach(targetAddr, {
    onEnter: function(args) {
        console.log("函数hook成功!");
        console.log(' called from:\n' +
        Thread.backtrace(this.context, Backtracer.ACCURATE)
        .map(DebugSymbol.fromAddress).join('\n') + '\n');
        this.skip = true;
    },
    onLeave: function(retval) {
        console.log("Function execution finished.");
    }
});

这里frida执行没有打印出堆栈信息是为什么呢?

frida hook函数需要对函数名的偏移地址然后在基址上添加,而不是函数内部的偏移地址。

为什么用frida给的偏移地址hook不成功?

查看函数的交叉应用。

这里我推测是上层函数中调用里面用了异步方法导致的。

交叉应用定位外层函数调用

再往上查找一层,IDA能识别出这是一个objc的方法。

绕过越狱检测

到这一步思路就很清晰了,直接用frida 来hook这个函数然后把把sub_100007008替换成一个空函数就行。重新写一个frida脚本为wcc_jail.js

var baseAddr = Module.findBaseAddress('WCCApp');
console.log("WCCApp base address: " + baseAddr);
//0x7008是sub_100007008越狱检测函数的偏移地址
var targetFunctionAddr = baseAddr.add(0x7008); 
console.log("Target function address: " + targetFunctionAddr);

const targetFunction = new NativeFunction(targetFunctionAddr, 'void', []);

// 把sub_100007008替换成一个空函数
Interceptor.replace(targetFunctionAddr, new NativeCallback(function () {
    console.log("Skip the execution of sub_100007008");
}, 'void', []));
//0x8A24是-[RootViewController viewDidLoad]的偏移地址
const targetFunctionAddrRootVC = baseAddr.add(0x8A24); 

Interceptor.attach(targetFunctionAddrRootVC, {
    onEnter: function (args) {
        console.log('Entering -RootViewController viewDidLoad!');
    },
    onLeave: function (retval) {
        console.log('Leaving -RootViewController viewDidLoad!');
    }
});

执行命令如下:

frida -U -l wcc_jail.js -f com.szzc.szzc

效果演示

赞赏

微信赞赏支付宝赞赏

Zgao

愿有一日,安全圈的师傅们都能用上Zgao写的工具。

发表评论