美文网首页
iOS逆向实战--031:越狱调试

iOS逆向实战--031:越狱调试

作者: 帅驼驼 | 来源:发表于2021-06-01 18:27 被阅读0次

    调试一款应用,使用重签名方案,很容易被第三方察觉。在越狱环境中,我们可以在不污染App的情况下,对第三方程序进行动态调试。

    Reveal

    Reveal是一款UI调试神器,对iOS逆向开发非常有帮助。这里使用Version 4(8796)版本

    Mac电脑中,安装Reveal软件

    在手机中,安装Reveal插件

    打开Cydia,安装Reveal Loader插件

    导入dylib文件

    在手机上,进入/Library,创建RHRevealLoader目录

    mkdir RHRevealLoader
    

    Mac电脑上,打开Reveal,找到iOS Library选项

    找到RevealServer路径

    打开终端,将RevealServer拷贝到手机的/Library/RHRevealLoader目录下,重命名为libReveal.dylib

    scp -P 12345 ./RevealServer root@localhost:/Library/RHRevealLoader/libReveal.dylib
    -------------------------
    RevealServer                                                                                                                           100% 9100KB  35.5MB/s   00:00
    

    开启允许调试的应用

    打开设置,找到Reveal选项

    开启允许调试的应用,例如WeChat

    使用Reveal进行UI调式

    Mac电脑上,打开Reveal软件。手机上,重新启动WeChat

    在电脑的Reveal中,出现两个WeChat,分别是WiFi连接和USB连接

    点击USB连接的WeChat,可进行UI调式,并且不会阻塞WeChat的进程

    debugserver

    在越狱环境中,使用Xcode进行lldb附加

    打开Xcode,随意打开一个项目,空工程也可以

    选择真机,在Debug菜单中,选择Attach to Process,选择WeChat进程

    显示Running,表示附加成功

    使用lldb将应用暂停

    使用Debug View进行UI调试

    lldb原理

    Xcode中的lldb可以调试手机中的应用,是因为手机中的debugserver开启了相关服务

    所以在越狱环境中,我们只需要开启debugserver服务,就可以利用lldb远程调试三方应用了

    探索debugserver

    找到Mac电脑中的debugserver,进入以下目录:

    /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport
    

    可以找到不同iOS系统版本,所对应的镜像文件

    进入设备对应的系统目录,找到dmg文件

    打开dmg文件,进入usr/bin目录可以看到debugserver。这就是Xcode安装到真机中的文件

    手机设备中的debugserver

    在手机系统中,已经存在一个debugserver。当Xcode第一次连接手机,就会将对应版本的debugserver安装到手机系统中

    进入手机的/Developer/usr/bin目录下

    将手机中的debugserver拷贝到Mac电脑中

    scp -P 12345 root@localhost:/Developer/usr/bin/debugserver ./
    -------------------------
    debugserver                                   100% 9505KB  33.8MB/s   00:00
    

    将拷贝后的debugserver生成md5

    md5 debugserver
    -------------------------
    MD5 (debugserver) = b771aad8917de2ff41feb5acfe4a9b15
    

    找到Mac电脑中的debugserver

    cd /Volumes/DeveloperDiskImage/usr/bin
    

    Mac电脑中的debugserver生成md5

    md5 debugserver
    -------------------------
    MD5 (debugserver) = b771aad8917de2ff41feb5acfe4a9b15
    

    两个文件的Hash一致,说明手机中的debugserver,就是Mac电脑中指定系统目录下的debugserver

    USB启动debugserver

    iPhone中开启debugserver服务

    Mac电脑中的lldb连接手机上的debugserver,需要配置IP和端口号

    在手机中,查看debugserver命令

    ./debugserver
    -------------------------
    debugserver-@(#)PROGRAM:LLDB  PROJECT:lldb-900.3.87
    for arm64.
    Usage:
     debugserver host:port [program-name program-arg1 program-arg2 ...]
     debugserver /path/file [program-name program-arg1 program-arg2 ...]
     debugserver host:port --attach=<pid>
     debugserver /path/file --attach=<pid>
     debugserver host:port --attach=<process_name>
     debugserver /path/file --attach=<process_name>
    
    • debugserver 主机地址:端口号 –a 应用进程
    • 由于主机地址是当前手机,可以使用localhost代替
    • 端口号:启动server服务,开放端口,让远程的lldb通过sever调试进程

    使用手机上的debugserver,附加WeChat应用

    找到WeChat进程

    9651 ??         0:08.88 /var/containers/Bundle/Application/454EA887-EB3B-43B3-ABFD-B9B2CA006981/WeChat.app/WeChat
    

    使用debugserver附加WeChat应用

    ./debugserver localhost:12346 -a 9651
    -------------------------
    debugserver-@(#)PROGRAM:LLDB  PROJECT:lldb-900.3.87
    for arm64.
    Attaching to process 9651...
    Listening to port 12346 for a connection from localhost...
    Failed to get connection from a remote gdb process.
    Exiting.
    

    遇到错误:Failed to get connection from a remote gdb process.

    解决办法:使用ldiddebugserver配置权限

    进入手机中debugserver拷贝到Mac电脑的目录

    导出debugserver的权限

    ldid -e debugserver > debugserver.entitlements
    

    删除三项权限

    seatbelt-profiles
    com.apple.security.network.server
    com.apple.security.network.client
    

    添加四项权限

       <key>task_for_pid-allow</key>
       <true/>
       <key>get-task-allow</key>
       <true/>
       <key>platform-application</key>
       <true/>
       <key>run-unsigned-code</key>
       <true/>
    

    修改后的debugserver.entitlements文件

    导入权限文件到debugserver

    ldid -Sdebugserver.entitlements debugserver
    

    手机中的/Developer/usr/bin目录,有权限问题,不能直接拷贝

    debugserver拷贝到手机的/usr/bin目录,拷贝后可全局使用

    scp -P 12345 ./debugserver root@localhost:/usr/bin/debugserver
    -------------------------
    debugserver                                   100% 9544KB  35.9MB/s   00:00
    

    找到WeChat进程

    ps -A | grep WeChat
    -------------------------
    9727 ??         0:07.27 /var/containers/Bundle/Application/454EA887-EB3B-43B3-ABFD-B9B2CA006981/WeChat.app/WeChat
    

    使用debugserver,附加WeChat应用

    debugserver localhost:12346 -a 9727
    -------------------------
    debugserver-@(#)PROGRAM:LLDB  PROJECT:lldb-900.3.87
    for arm64.
    Attaching to process 9727...
    Listening to port 12346 for a connection from localhost...
    

    使用lldb连接debugserver

    Mac电脑上,进入lldb环境

    lldb
    

    连接debugserver

    process connect connect://10.165.45.19:12346
    

    遇到错误:error: Failed to connect port

    解决办法:使用USB端口映射

    修改usbConnect.sh脚本

    python /Users/zang/Zang/Tools/python-client/tcprelay.py -t 22:12345 12346:12346
    
    • 增加12346的端口映射

    使用USB连接

    usbConnect.sh
    -------------------------
    Forwarding local port 12345 to remote port 22
    Forwarding local port 12346 to remote port 12346
    

    手机上,使用debugserver,附加WeChat应用

    ./debugserver localhost:12346 -a 9727
    

    Mac电脑上,进入lldb环境

    lldb
    

    使用lldb连接debugserver

    process connect connect://localhost:12346
    -------------------------
    Process 9752 stopped
    * thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
       frame #0: 0x00000001a3e740f4 libsystem_kernel.dylib`mach_msg_trap + 8
    libsystem_kernel.dylib`mach_msg_trap:
    ->  0x1a3e740f4 <+8>: ret
    
    libsystem_kernel.dylib`mach_msg_overwrite_trap:
       0x1a3e740f8 <+0>: mov    x16, #-0x20
       0x1a3e740fc <+4>: svc    #0x80
       0x1a3e74100 <+8>: ret
    Target 0: (WeChat) stopped.
    

    连接成功,输入c,继续运行

    c
    -------------------------
    Process 9752 resuming
    

    输入process interrupt,暂停

    process interrupt
    

    使用command + w,停止WeChat附加,但不杀掉应用

    class-dump

    class-dump是一个命令行工具,最高版本为class-dump 3.5 (64 bit),已经停止更新

    查看class-dump的路径

    which class-dump
    -------------------------
    /Users/zang/Zang/Tools/MonkeyDev/bin/class-dump
    
    • 来自MonkeyDev框架

    MonkeyDev中,class-dump的使用

    搭建MonkeyDev项目

    Build Settings中,将MONKEYDEV_CLASS_DUMP默认为NO

    将其修改为YES

    编译项目,主工程下生成Headers目录,自动导出头文件

    工程目录下不要包含中文,否则Headers目录以及头文件无法生成

    命令行工具

    搭建自定义的命令行工具

    创建App项目,命名FuncDemo

    打开main.m文件,写入以下代码:

    #import <UIKit/UIKit.h>
    #import "AppDelegate.h"
    
    int main(int argc, char * argv[]) {
       
       for (int intIndex=0; intIndex<argc; intIndex++) {
           printf("参数%i:%s\n",intIndex, argv[intIndex]);
       }
       
       return 0;
    }
    
    • argc:参数个数
    • argv:参数数组

    编译项目,将MachO文件,拷贝到手机上

    scp -P 12345 ./FuncDemo root@localhost:~/
    -------------------------
    FuncDemo                                    100%  150KB   5.9MB/s   00:00
    

    USB连接手机设备

    usb-6p.sh
    

    使用自定义命令行工具

    ./FuncDemo -v
    -------------------------
    参数0:./FuncDemo
    参数1:-v
    
    • 参数0为默认,显示当前MachO
    lldb手动砸壳

    逆向分析一个应用,第一步就是应用砸壳

    查看MachO文件中的crypt信息

    otool -l WeChat | grep crypt
    -------------------------
        cryptoff 16384
       cryptsize 178356224
         cryptid 0
    
    • cryptid:为0表示应用已砸壳
    • cryptoff:表示开始加密的偏移位置
    • cryptsize:表示加密长度

    将应用砸壳后,才能使用class-dump导出头文件

    查看加壳的MachO文件

    USB连接手机设备,找到WeChat的沙盒路径

    ps -A | grep WeChat
    -------------------------
    9806 ??         0:03.88 /var/containers/Bundle/Application/454EA887-EB3B-43B3-ABFD-B9B2CA006981/WeChat.app/WeChat
    

    WeChat拷贝到Mac电脑

    scp -P 12345 root@localhost:/var/containers/Bundle/Application/454EA887-EB3B-43B3-ABFD-B9B2CA006981/WeChat.app/WeChat ./
    -------------------------
    WeChat                                        100%  184MB  39.0MB/s   00:04
    

    查看MachO文件中的crypt信息

    otool -l WeChat | grep crypt
    -------------------------
        cryptoff 16384
       cryptsize 154255360
         cryptid 1
    

    尝试不砸壳,只修改cryptid,能否使用class-dump导出头文件

    使用MachOView打开WeChat

    Load Commands中,找到LC_ENCRYPTION_INFO_64,修改Crypt ID0

    使用class-dump导出头文件

    class-dump -H WeChat -o ./header
    -------------------------
    2021-05-31 17:59:37.344 class-dump[70836:43071318] Warning: Parsing method types failed, ¨
    ...
    

    导出失败。不砸壳,仅修改cryptid,无法导出头文件。所以砸壳的关键,并不是cryptid,而是将加密的代码段进行解密

    使用lldb手动砸壳

    砸壳的逻辑,从内存中,读取cryptoff位置到cryptsize长度的数据,然后将其覆盖原始MachO文件

    使用Xcode打开工程,选择设备,附加WeChat进程

    获取MachO的首地址

    image list
    -------------------------
    [  0] 2B07ABCB-9885-3FF1-943C-B88A763C03C5 0x00000001008e0000 /var/containers/Bundle/Application/454EA887-EB3B-43B3-ABFD-B9B2CA006981/WeChat.app/WeChat (0x00000001008e0000)
    ...
    
    • MachO首地址为0x1008e0000

    从内存中,将加密部分的代码段,导出到WeChat.bin文件。因为已读取到内存中,相当于已解密

    memory read --force --outfile ~/Downloads/WeChat.bin --binary --count 154255360 0x00000001008e0000+16384
    -------------------------
    154255360 bytes written to '/Users/zang/Downloads/WeChat.bin'
    
    • 代码段加密的开始位置:MachO首地址 + 加密偏移地址

    WeChat.bin文件,写入到MachO文件中相同位置,相当于用解密后的数据,覆盖原始的加密数据

    dd seek=16384 bs=1 conv=notrunc if=./WeChat.bin of=WeChat
    -------------------------
    154255360+0 records in
    154255360+0 records out
    154255360 bytes transferred in 768.025931 secs (200847 bytes/sec)
    
    • seek:从输出文件开头跳过x个块后再开始复制
    • bs:同时设置读入/输出的块大小为x个字节
    • conv=notrunc:不截断输出文件
    • if:输入文件名,默认为标准输入。即指定源文件
    • of:输出文件名,默认为标准输出。即指定目的文件

    文件写入成功,将MachO文件的cryptid修改为0,成功导出头文件

    Tweak修改系统行为

    搭建Tweak插件,屏蔽应用的红点气泡

    屏蔽应用的红点气泡,需要附加的应用是系统的桌面程序SpringBoard

    USB连接手机,找到SpringBoard进程

    ps -A | grep SpringBoard
    -------------------------
    10262 ??         0:10.04 /System/Library/CoreServices/SpringBoard.app/SpringBoard
    

    SpringBoard拷贝到Mac电脑

    scp -P 12345 root@127.0.0.1:/System/Library/CoreServices/SpringBoard.app/SpringBoard ./
    -------------------------
    SpringBoard                                   100% 7374KB  38.9MB/s   00:00
    

    查看MachO文件中的crypt信息

    otool -l SpringBoard | grep crypt
    -------------------------
    
    
    • MachO中找不到加密信息,说明SpringBoard原本就没有加壳

    使用class-dump导出头文件

    class-dump -H SpringBoard -o ./header
    

    成功导出SpringBoard应用的头文件

    动态调试

    我们可以使用的动态调试工具有三种:

    • Reveal
    • Cycript
    • lldb

    使用Reveal无法动态调试,因为在手机设置页的Reveal选项中,并没有SpringBoard应用

    使用Cycript,可以成功附加SpringBoard进程,但定位红点UI,并不直观

    最简单的方式,使用lldb附加SpringBoard进程,通过Debug View找到红点对象

    • 红点对象:SBIconParallaxBadgeView

    cy环境中验证

    导入自定义cy脚本

    @import com.zang.cur_vc
    currentVC()
    #0x10145e3a0.view.recursiveDescription() .toString ()
    

    在结果中搜索SBIconParallaxBadgeView

    3个红点,刚好对应3个控件

    选择其中一个对象,将其设置为隐藏

    #0x10a623710.hidden=YES
    

    App Store上的红点被成功隐藏

    在导出的头文件中,找到SBIconParallaxBadgeView.h文件

    • SBIconParallaxBadgeView进行HOOK,破坏它的init方法,即可隐藏红点气泡

    搭建Tweak插件

    使用nic.pl15,创建Tweak插件

    Makefile文件中,增加IP和端口

    为了一劳永逸,将这两项配置在环境变量中

    vim ~/.zshrc
    export THEOS_DEVICE_IP=localhost
    export THEOS_DEVICE_PORT=12345
    

    打开Tweak.x文件,写入以下代码:

    %hook SBIconParallaxBadgeView
    
    - (id)init {
      return nil;
    }
    
    %end
    

    编译、打包、安装插件

    cd reddemo
    make
    make package;make install
    

    成功安装Tweak插件,红点气泡全部隐藏

    MonkeyDev搭建Tweak插件

    使用MonkeyDev创建Tweak插件

    项目命名:BadgeTweakDemo

    • BadgeTweakDemo.xm:代码
    • control:配置信息,版本号、作者名称等
    • BadgeTweakDemo.plist:附加应用的包名称

    Build Settings中,搜索Monkey,找到Tweak的设置

    • MonkeyDevBuildPackageOnAnyBuild:每次编译时打包
    • MonkeyDevClearUiCacheOnInstall:安装时清除缓存
    • MonkeyDevCopyOnBuild:编译时拷贝包到目录
    • MonkeyDevDeviceIP:设备IP
    • MonkeyDevDevicePassword:设备密码
    • MonkeyDevDevicePort:设备端口
    • MonkeyDevInstallOnAnyBuild:每次编译时安装
    • MonkeyDevkillProcessOnInstall:安装成功后杀掉的进程

    设置IP和端口,同样将这两项配置在环境变量中

    vim ~/.zshrc
    export MonkeyDevDeviceIP=localhost
    export MonkeyDevDevicePort=12345
    

    打开BadgeTweakDemo.xm文件,写入以下代码:

    #import <UIKit/UIKit.h>
    
    %hook SBIconParallaxBadgeView
    
    - (id)init {
       return nil;
    }
    
    %end
    

    Build Settings中,搜索signing,设置签名

    • Code Signing Identity:设置为iOS Developer

    编译项目时,如果遇到CydiaSubstrate.tbdbuilt for iOS Simulatorfor architecture arm64问题,按目录找到CydiaSubstrate.tbd文件,删除里面的i386x86_64

    编译项目,成功安装Tweak插件,红点气泡全部隐藏

    总结

    Reveal

    • iOS安装插件
    • Mac安装App
    • 将动态库导入iPhone

    USB启动debugserver

    • 终端附加
      ◦ 手机,使用debugserver 主机名称:端口 -a 进程id
      Mac电脑,启动lldb,使用process connect connect://主机名称:端口
      USB端口映射

    • Xcode附加
      ◦ 打开工程
      ◦ 选择设备
      ◦ 附加进程

    debugserver权限问题

    • 导出权限文件,查看文件
      ldid -e debugserver > debugserver.entitlements

    • 删除权限
      seatbelt-profiles
      com.apple.security.network.server
      com.apple.security.network.client

    • 添加权限
      task_for_pid-allow设置为YES
      get-task-allow设置为YES
      platform-application设置为YES
      run-unsigned-code设置为YES

    • 设置权限
      ldid -Sdebugserver.entitlements debugserver

    class-dump

    • class-dump -H MachO文件路径 -o 头文件路径
    • MonkeyDev中,可以快速使用class-dump

    命令行工具

    • argc:参数个数
    • argv:参数数组

    lldb手动砸壳

    • memory read命令
      ◦ 通过--outfile参数,导出文件。lldb的环境在Mac
      ◦ 通过--count参数,指定导出的大小

    • dd命令
      ◦ 写入源文件
      seek指定偏移,也就是跳过多少开始写入
      conv保留没有替换的部分

    Tweak修改系统行为

    • Reveal无法使用,在手机设置页的Reveal选项中,没有SpringBoard应用
    • Cycript可以使用,但定位UI不直观
    • lldb可以使用,最简单的方式

    MonkeyDev搭建Tweak插件

    • Build Settings中,配置参数
    • 设置签名
    • 编译项目并安装插件

    相关文章

      网友评论

          本文标题:iOS逆向实战--031:越狱调试

          本文链接:https://www.haomeiwen.com/subject/bwvvsltx.html