美文网首页
iOS逆向工程(八):动态调试

iOS逆向工程(八):动态调试

作者: 冰雨9527 | 来源:发表于2020-10-24 07:56 被阅读0次

    动态调试

    一、什么是动态调试

    • 1.动态调试就是将程序运行起来,通过打断点、打印等方式,查看参数、返回值、函数调用流程等信息
    • 2.之前我们说的静态分析,就是程序不运行的时候,对程序的可执行文件进行分析,分析头文件、伪代码之类的信息
    • 3.学会动态调试之后,我们就可以分析某个程序的整体调用流程了,例如:分析微信抢红包的时候,就可以知道微信调用了哪些方法去抢红包,以便我们hook

    二、动态调试任意App

    第一步:将有权限的debugserver安装到手机

    1/进入目录
    /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport

    找到手机对应版本,点开dmg;拷贝debugserver备用
    /usr/bin/debugserver

    2/修改权限
    导出权限

    $ ldid -e debugserver > debugserver.entitlements
    

    修改内容

    温馨提示->
    最好整体copy

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>com.apple.backboardd.debugapplications</key>
        <true/>
        <key>com.apple.backboardd.launchapplications</key>
        <true/>
        <key>com.apple.frontboard.debugapplications</key>
        <true/>
        <key>com.apple.frontboard.launchapplications</key>
        <true/>
        <key>com.apple.springboard.debugapplications</key>
        <true/>
        <key>com.apple.system-task-ports</key>
        <true/>
        <key>get-task-allow</key>
        <true/>
        <key>platform-application</key>
        <true/>
        <key>run-unsigned-code</key>
        <true/>
        <key>task_for_pid-allow</key>
        <true/>
    </dict>
    </plist>
    

    编辑后将其合入debugserver【注意-S后面不要空格】

    $ ldid -Sdebugserver.entitlements debugserver
    

    3/将编辑完成的文件放入手机的/usr/bin目录

    电脑端操作->

    $ scp -r /Users/gn/Desktop/333/debugserver root@10.0.0.17:/usr/bin
    

    手机端操作->如果有过操作,需要删除debugserver

    iPhone-7:~ root# rm /usr/bin/debugserver
    

    第二步:让debugserver与App建立交互

    在Mac上打开命令行窗口,让10011端口与10011端口映射、10010与22端口映射

    新建命令行窗口
    $ iproxy 10011 10011
    新建命令行窗口
    $ iproxy 10010 22
    

    在Mac上新建命令行窗口,然后SSH登陆到手机

    gndeMacBook-Pro:~ gn$ ssh -p 10010 root@127.0.0.1
    

    提示
    server端密码或是其他发生改变的时候。
    解决方法一般就需要删除~/.ssh/known_hosts的东西,然后再登录即可。

    登录到手机后,启动手机的debugserver服务,让其与App建立交互

    iPhone-7:~ root# debugserver 127.0.0.1:10011 -a WeChat
    
    debugserver-@(#)PROGRAM:LLDB  PROJECT:lldb-900.3.106
     for arm64.
    Attaching to process WeChat...
    Listening to port 10011 for a connection from localhost...
    Waiting for debugger instructions for process 0.
    

    第三步:让debugserver与LLDB建立交互

    在Mac上新建命令行窗口

    $ lldb  
    (lldb) process connect connect://127.0.0.1:10011
    
    Process 1079 stopped
    * thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
        frame #0: 0x0000000189d2d198 libsystem_kernel.dylib`mach_msg_trap + 8
    libsystem_kernel.dylib`mach_msg_trap:
    ->  0x189d2d198 <+8>: ret    
    
    libsystem_kernel.dylib`mach_msg_overwrite_trap:
        0x189d2d19c <+0>: mov    x16, #-0x20
        0x189d2d1a0 <+4>: svc    #0x80
        0x189d2d1a4 <+8>: ret    
    Target 0: (WeChat) stopped.
    (lldb)  
    

    使用LLDB命令c,先让程序继续运行

    (lldb) c
    
    Process 1079 resuming
    (lldb) 
    

    测试

    (lldb) image list
    
    [  0] 12AE6955-466B-365D-B4AD-4414062D4AA0 0x0000000100e20000 /private/var/containers/Bundle/Application/155D1862-E927-4904-B513-B48BDA84DE08/WeChat.app/WeChat (0x0000000100e20000)
    [  1] D3BB8E91-0746-3426-8707-5B717D156B4E 0x000000010d2a0000 /Library/Caches/cy-B6mYK0.dylib (0x000000010d2a0000)
    [  2] BF3B96C2-BD3B-390E-BFCF-33656588C86E 0x000000010cf90000 /usr/lib/substrate/SubstrateBootstrap.dylib (0x000000010cf90000)
    [  3] 46F72B20-370B-352E-ABCA-3896633F251D 0x00000001b4191000 /Users/gn/Library/Developer/Xcode/iOS DeviceSupport/13.7 (17H35)/Symbols/System/Library/Frameworks/AuthenticationServices.framework/AuthenticationServices 
    [  4] 7602EB30-DE1D-3996-8D0E-024450B58325 0x000000019885d000 /Users/gn/Library/Developer/Xcode/iOS DeviceSupport/13.7 (17H35)/Symbols/System/Library/Frameworks/AVKit.framework/AVKit 
    [  5] E545F1E8-28B7-3580-9770-97D87896929B 0x00000001c08be000 /Users/gn/Library/Developer/Xcode/iOS DeviceSupport/13.7 (17H35)/Symbols/usr/lib/libresolv.9.dylib 
    

    第四步:动态调试建立好之后,我们就可以使用LLDB指令,来正式开始调试了

    LLDB指令
    LLDB指令的格式是:
    <command> [<subcommand> [<subcommand>...]] <action> [-options [option- value]] [argument [argument...]],其中,command代表命令,subcommand代表子命令,action代表命令的动作,- options 代表命令的选项,argument代表命令的参数,[]中的可以省略。
    help命令,用于查看指令的用法,例如:help breakpoint、help breakpoint set
    expression命令,执行一个表达式,例如:expression self.view.backgroundColor = [UIColor redColor],expression与print、p、call的效果一样
    thread backtrace命令,打印线程的堆栈信息,与bt命令效果一样
    thread return []命令,让函数直接返回某个值,不会执行断点后面的代码了,例如:thread return 3,返回了3
    frame variable []命令,打印当前栈帧的变量
    thread continue、continue、c命令,让程序继续运行
    thread step-over、next、n命令,单步执行,把子函数当做一个整体,不会进入子函数
    thread step-in、step、s命令,单步执行,遇到子函数会进入子函数内部
    breakpoint set命令,设置断点,参数主要有以下几种:
    breakpoint set -a 函数地址
    breakpoint set -n 函数名
    breakpoint set -r 正则表达式
    breakpoint set -s 动态库 -n 函数名
    breakpoint list命令,列出所有的断点,每个断点都有自己的编号
    breakpoint delete 断点编号命令,删除某个断点
    breakpoint command add 断点编号命令,给断点预先设置需要执行的命令,到触发断点时,就会按顺序执行
    breakpoint command list 断点编号命令,查看某个断点的预设命令
    watchpoint内存断点,就是当内存数据改变时,触发此断点,以便确认是谁修改了内存,子命令主要有以下几种:
    watchpoint set variable 变量,例如:watchpoint set variable self->_age,当age变量改变时,断点就会触发,以便找到修改age内存的代码
    
    watchpoint set expression 地址,例如:watchpoint set expression &self->_age
    
    watchpoint list,列出所有的内存断点
    
    watchpoint delete 断点编号,删除此内存断点
    
    watchpoint command add 断点编号,给此内存断点,增加预设命令
    
    image lookup,寻找模块信息,如果你想找某个类型、某个方法、某个地址在模块中的什么位置,就可以用这个命令,主要参数如下:
    image lookup -t 类型,查找某个类型的信息,例如image lookup -t NSInterger
    image lookup -a 地址,看看某个内存地址在模块中的位置
    image lookup -n 符号或者函数名,查找某个符号或者函数的位置
    image list,列出所加载的模块信息
    一些小技巧:敲Enter会自动执行上次的命令、绝大部分命令可以使用缩写
    

    lldb常用命令

    breakpoint使用

    1、下断点

    breakpoint set --name test1 
    
    

    breakpoint set -n test1 
    
    

    打印:

    Breakpoint 2: where = LLDB`-[ViewController test1] + 23 at ViewController.m:25:5, address = 0x0000000109de9f97
    
    

    断点位置信息,执行便能在该处断住。

    连续下多个断点:

    breakpoint set -n "-[ViewController save:]" -n "-[ViewController pause:]" -n "-[ViewController continues:]"
    
    

    运行c继续运行,n单步执行,s进入函数内部执行,finish执行到函数尾部。

    2、查看断点列表

    breakpoint list
    
    

    打印:

    1: file = '/Users/hibo/Documents/test/LLDB/LLDB/ViewController.m', line = 21, exact_match = 0, locations = 1 Options: disabled 
    
     1.1: where = LLDB`-[ViewController touchesBegan:withEvent:] + 70 at ViewController.m:22:6, address = 0x0000000109de9f46, unresolved, hit count = 2 Options: disabled 
    
    2: name = 'test1', locations = 1, resolved = 1, hit count = 7
    
     2.1: where = LLDB`-[ViewController test1] + 23 at ViewController.m:25:5, address = 0x0000000109de9f97, resolved, hit count = 7 
    
    

    3、禁用断点

    breakpoint disable  //禁用所有断点
    breakpoint disable 1.1 //禁用第一个断点
    
    

    4、启用断点

    breakpoint enable   //启用所有断点
    breakpoint enable 1.1  //启用1处断点  
    
    

    5、删除所有断点

    breakpoint delete
    breakpoint delete 1
    
    

    删除只能删除一组,不能单个删除

    6、设置selector

    breakpoint set --selector touchesBegan:withEvent:
    
    

    将为所有该方法设置断点

    7、设置文件中的selector断点

    breakpoint set --file ViewController.m --selector touchesBegan:withEvent:
    
    

    8、设置带有相同字符串的方法断点

    breakpoint set -r Game:
    
    

    打印:

    Current breakpoints:
    
    1: regex = 'Game:', locations = 3, resolved = 3, hit count = 0
    
     1.1: where = LLDB`-[ViewController pauseGame:] + 43 at ViewController.m:31:5, address = 0x00000001010dff0b, resolved, hit count = 0 
    
     1.2: where = LLDB`-[ViewController continueGame:] + 43 at ViewController.m:34:5, address = 0x00000001010dff5b, resolved, hit count = 0 
    
     1.3: where = LinkPresentation`-[LPGameCenterInvitationMetadata setGame:], address = 0x00007fff2733e5e9, resolved, hit count = 0 
    
    

    如上也给其他带有Game字符的类下了断点。

    给某一个文件下的带有相同字符串的方法下断点:

    breakpoint set --file ViewController.m -r Game
    
    

    简写:breakpoint->b
    打印列表需要写全:breakpoint list或者break list

    bt、frame命令

    1、查看函数相关信息,使用p、down追踪函数的调用和被调用关系

    frame select
    
    

    使用bt命令查看函数调用堆栈

    2、查找方法的调用者及方法名称

    frame variable
    
    

    methods、pviews

    1、methods打印当前对象的属性和方法

    methods self 
    
    

    2、pviews打印当前视图的层级结构

    以上两个命令是lldb插件名中的命令。chisel安装

    ……

    相关文章

      网友评论

          本文标题:iOS逆向工程(八):动态调试

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