ios逆向爬虫-入门保姆级-实战某博APP

查看 89|回复 8
作者:xiaoweigege   
ios逆向爬虫-入门保姆级-实战某博APP
设备
  • iPhone11,系统14.2
  • Windows11

    工具
  • Frida15.2.2
  • frida-ios-dump
  • Ida7.7

    流程
    [ol]
  • 手机越狱
  • 爱思助手安装目标APP
  • Cydia安装Frida
  • frida-ios-dump进行脱壳
  • app分析
  • ida+frida动静态分析
    [/ol]
    手机越狱
    采用爱思助手一键越狱
    爱思助手安装目标APP

    Cydia安装Frida
    [ol]

  • Cydia添加frida源
    [img][/img]

    7.png (164.53 KB, 下载次数: 0)
    下载附件
    2022-12-1 19:33 上传

    " alt="avatar" />

  • 在cydia添加frida源后,搜索frida,根据iOS设备版本安装对应的frida服务端,如下所示
    [img][/img]

    6.png (138.67 KB, 下载次数: 1)
    下载附件
    2022-12-1 19:33 上传

    " alt="avatar" />

  • frida一些简单的使用
  • frida-ls-devices 查看电脑链接设备信息
  • frida-ps -U 查看通过USB连接设备上运行的程序
  • frida-ps -Ua 查看正在运行的程序
  • frida-ps -Uai 查看iOS设备中已经安装的应用程序
  • frida-ps -D \[U] 通过iOS设备的UDID查看iOS设备中应用程序中的pid、进程名
  • frida-trace -U -f 包名 -i 'CC_MD5' 用于跟踪ios方法的调用

    [/ol]
    frida-ios-dump进行脱壳
    ios脱壳的方式有很多种:
    [ol]
  • frida-iod-dump
  • dumpdecrypted
  • flexdecrypt
  • Clutch
  • AppCrackr
  • Crackulous
    [/ol]
    个人觉得frida-ios-dump比较方便,快速。接下来讲解frida-ios-dump的使用步骤:
    [ol]
  • 拉取代码,地址: frida-ios-dump
  • 安装依赖: pip install -r requirements.txt
  • 手机端口转发 iproxy 2222 22; iproxy 本地端口 远程目标端口
  • ./dump.py 目标app名称, 会将ipa包拉取在本地当前目录
  • 将ipa文件中的主包文件拖进ida分析(app比较大,ida会分析好久好久好久);如图所示:
    [img][/img]

    5.png (26.76 KB, 下载次数: 1)
    下载附件
    2022-12-1 19:33 上传

    " alt="avatar" />
    [/ol]
    app分析
    抓包分析
    [img][/img]

    4.png (57.74 KB, 下载次数: 0)
    下载附件
    2022-12-1 19:33 上传

    " alt="avatar" />
    我们的目标是得到s值得算法,从s这个值得名称来看,大概是一个签名,那么根据以往的经验签名函数大概是一个hash操作。
    过程:
    [ol]
  • 合并请求数据
  • 加上盐值
  • hash计算得到签名
    [/ol]
    frida-trace 跟踪hash函数
    [ol]
  • 打开目标app
  • 输入命令: frida-trace -UF -i "CC_MD5" 跟踪ios的md5函数
  • 在当前目录下会生成 __headlers/xxx/CC_MD5.js 文件

  • 修改对应js更好的显示输出结果
    {
        onEnter(log, args, state)
        {
            log('CC_MD5():', args[0].readUtf8String());
        }
    ,
        onLeave(log, retval, state)
        {
            log('CC_MD5()--return--=');
            var md5_digest = hexdump(retval, {length: 16});
            var hexified = " ";
            var raw_array = md5_digest.split("\n");
            for (var a = 0; a
  • trace结果如下:
    [img][/img]

    3.png (55.35 KB, 下载次数: 1)
    下载附件
    2022-12-1 19:33 上传

    " alt="avatar" />
    [/ol]
    执行上述流程,并没有hook到关键数据,同理尝试 CC_SHA1, CC_SHA256, CC_SHA512, CCHmac。均没有结果
    接着使用FridaDev中的ios-trace.js 脚本进行跟踪。该脚本比较强大,可以模糊跟踪ios中的函数,入参,出参都有比较美观的输出。
    现在我们根据经验进行一些跟踪,脑海里面想到一些关键词 sign,crypt, Signature等等。使用该脚本得到结果如下:
    [img][/img]

    2.png (17.15 KB, 下载次数: 0)
    下载附件
    2022-12-1 19:33 上传

    " alt="avatar" />
    找到关键信息数据, 得到s的返回值。
    找到目标函数,现在需要耐心等待ida分析完成,我们要去看看c的伪代码了。
    ida+frida动静态分析
    ida一些基本操作
    [ol]
  • x快捷键获取函数,变量的调用处
  • shift + F12 获取字符串窗口
    ...
    [/ol]
    ida静态分析
    [ol]
  • ida静态分析目标函数
    [img][/img]

    2413663-20220922142152646-1712344710.png (51.82 KB, 下载次数: 0)
    下载附件
    2022-12-1 19:26 上传

    " alt="avatar" />
    sub_107717A5C 函数是sha256算法,为什么我们之前trace sha256函数的时候没有得到结果,因为这部分算法是C写的导致hook不到。
    [/ol]
    怎么分析出是sha256算法的?
    [ol]
  • 经验
  • 推荐一个hash计算的网站 hash计算, 把加密前内容拿去计算,对比计算出来的结果,推断是什么算法
    [/ol]
    frida hook obj-c的两种方法
    [ol]

  • oc方法
    //                      类名                方法
    var hook = ObjC.classes.NSMutableURLRequest["- setHTTPBodyStream:"];
    Interceptor.attach(hook.implementation, {
    onEnter: function(args) {
    // 转换 objc 对象
    var receiver = new ObjC.Object(args[0]);
    // 将选择器转换sel为 JavaScript 字符串
    var sel = ObjC.selectorAsString(args[1]);
    var data = ObjC.Object(args[2]);
    var string = ObjC.classes.NSString.alloc();
    send(" HTTP Request via [ "+receiver+" " +sel+" ] => DATA: " + string.initWithData_encoding_(data,4));
    }
    });

  • sub方法
    像上图这种无符号函数,我们需要根据地址来进行hook
    if (ObjC.available) {
    const baseOffset = 0x100000000;
    const base = Module.findBaseAddress('主包名称');
    console.log('Base:', base);
    const idaBase = base.add(-baseOffset);
    console.log('Real Base:', idaBase);
    const sub = base.add(0x107720938 - baseOffset);
    Interceptor.attach(sub, {
        onEnter: function (args) {
            console.log('进入:' + sub.toString() +':', args[0], args[1], args[3])
            print_dump(args[0], 100)
            // console.log('args[0]=', args[0].readCString())
            print_dump(args[1], 100)
            // console.log(args[3].readInt())
            // print_dump(args[2], 100)
        },
        onLeave: function (retval) {
            console.log('retval=', retval)
            print_dump(retval, 200)
        }
    })
    } else {
    console.log('非ios环境')
    }
    [/ol]
    常用的一些模板
    该脚本来自慕白
    [ol]
  • 打印堆栈,堆栈地址相对ida无偏移
    function logBacktrace(context, methodName = "", threadId = "") {
    log((methodName.length > 0 ? methodName + " " : "") + "Backtrace:");
    var backtraces = Thread.backtrace(context, Backtracer.ACCURATE);
    for (var backtrace of backtraces) {
        var symbol = DebugSymbol.fromAddress(backtrace);
        var memAddr = symbol.address;
        var subAddr = memAddr.add(baseOffset - base);
        log("\t" + threadId + " " + subAddr + " " + symbol.moduleName + "!" + symbol.name + " " + symbol.fileName + " " + (symbol.lineNumber > 0 ? symbol.lineNumber : ""));
    }
    }
    [/ol]
    function logInterceptor(interceptor, methodName = "") {
    var info = "[t" + interceptor.threadId + "] " + (methodName.length > 0 ? methodName : "");
    logBacktrace(interceptor.context, info, interceptor.threadId);
    }
    // 使用方法
    var A = eval('ObjC.classes.A["- A:"]');
    Interceptor.attach(A.implementation, {
    onEnter: function (args) {
    logInterceptor(this, "A:");
    }, onLeave: function (ret) {
    }
    });
    2. json2str
    ```js
    function jsonTostr(ocobj) {
        var NSString = ObjC.classes.NSString
        var str = NSString.alloc().initWithData_encoding_(ocobj, 4)
        return str
    }
  • 数组转16进制字符串
    function print_dump(addr, size, methodName = "") {
    if (addr == null || addr == 0 || size == 0) {
        return;
    }
    var buf = Memory.readByteArray(addr, size)
    log((methodName.length > 0 ? methodName + " " : "") + "[dump]: " + addr.toString() + " " + "length: " + size.toString() + "\n[data]")
    log(hexdump(buf, {offset: 0, length: size, header: true, ansi: false}));
    log("\n")
    }
  • 打印对象
    function print_obj(obj) {
    var description = "";
    for (var i in obj) {
        description += i + " = " + obj + "\n";
    }
    log(`info:\n${description}`);
    }
  • 打印原生bytes
    function print_raw_bytes(addr, size) {
    log("Reading from address: " + addr);
    var byteArray = addr.readByteArray(size);
    var int8Array = new Uint8Array(byteArray);
    var str = "";
    for (var i = 0; i  16 ? value.toString(16) : ("0" + value.toString(16)));
        str += " ";
    }
    return str;
    }
    [/ol]

    函数, 下载次数

  • 浅紫色的梦幻   


    Hmily 发表于 2022-11-16 10:41
    关于图片,你如果用图传得用markdown的语句,如果你上传本地应该用discuz的插入方式,现在的img方式不能用 ...

    感谢提醒,
    xiaoweigege
    OP
      

    关于图片,你如果用图传得用markdown的语句,如果你上传本地应该用discuz的插入方式,现在的img方式不能用于markdown状态下。
    q410226885   

    谢谢分享
    小洲   

    刚好要学习ios逆向编程
    feather_fox   

    是我网络问题吗,图片全部挂了?
    shudong8023   

    把图片归拢一下吧,别一开帖就成太监了。
    kyne   

    刚好学习一下,感谢分享
    koohik   

    把图片归拢一下吧。
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部