美文网首页
iOS逆向-LLDB(VII)

iOS逆向-LLDB(VII)

作者: 鼬殿 | 来源:发表于2019-10-26 13:33 被阅读0次

    LLDB(Low Lever Debug),默认内置于Xcode中的动态调试工具。标准的 LLDB 提供了一组广泛的命令,旨在与老版本的 GDB 命令兼容。 除了使用标准配置外,还可以很容易地自定义 LLDB 以满足实际需要。

    如果逆向别人的代码可以通过暂停程序执行来使程序进入LLDB状态

    LLDB有很多指令,如果忘了相关指令,我们可以通过help命令查看

    (lldb) help
    Debugger commands:
      apropos           -- List debugger commands related to a word or subject.
      breakpoint        -- Commands for operating on breakpoints (see 'help b' for
                           shorthand.)
    ...
    

    也可以通过apropos列出与某个单词或主题相关的调试器命令

    (lldb) apropos breakpoint
    The following commands may relate to 'breakpoint':
      _regexp-break                           -- Set a breakpoint using one of
                                                 several shorthand formats.
      _regexp-tbreak                          -- Set a one-shot breakpoint using
                                                 one of several shorthand formats.
      breakpoint                              -- Commands for operating on
                                                 breakpoints (see 'help b' for
                                                 shorthand.)
      breakpoint clear                        -- Delete or disable breakpoints
                                                 matching the specified source file
                                                 and line.
    ...
    

    常用命令

    • 给所有名为xxx的C函数设置一个断点
    (lldb) breakpoint set -name xxx
    (lldb) br s -n xxx
    (lldb) b xxx
    
    • 给一个OC函数[objc msgSend:]设置一个断点
    (lldb) breakpoint set -n "[objc msgSend:]"
    (lldb) b -n "[objc msgSend:]"
    
    • 给所有名为xxx的OC方法设置一个断点
    (lldb) breakpoint set -selector xxx:
    
    • 给指定文件的某个OC方法设置一个断点
    (lldb) breakpoint set --file ViewController.m --selector touchesBegan:withEvent:
    
    • 给所有包含xxx的字段设置断点
    (lldb) breakpoint set -r xxx
    
    • 给指定文件F的某一行L设置一个断点
    (lldb) breakpoint set --file F -line L
    
    • 断点查看
    (lldb) breakpoint list
    (lldb) br l
    
    • 断点删除
    (lldb) breakpoint delete index//index是组号
    (lldb) breakpoint delete //删除所有断点
    (lldb) br del index
    
    • 禁用/开启断点
    (lldb) breakpoint disable index
    (lldb) breakpoint enable index
    

    断点的流程控制

    • 继续
    (lldb) process continue
    (lldb) continue
    (lldb) c
    
    • 单步运行,将子函数当做整体一步执行
    (lldb) thread step -over
    (lldb) next
    (lldb) n
    (lldb) ni //单步运行汇编级别
    
    • 单步运行,遇到子函数会进去
    (lldb) thread step -in
    (lldb) step
    (lldb) s
    (lldb) si //单步运行可跳转指令内部,汇编级别
    
    • 跳出方法,返回上层调用栈
    (lldb) thread step -out
    (lldb) finish
    (lldb) f
    

    expression

    expression其实是p的缩写,它的主要作用是在当前线程执行一个表达式,并将结果按照LLDB的默认格式返回。

    (lldb) help p
         Evaluate an expression on the current thread.  Displays any returned value
         with LLDB's default formatting.  Expects 'raw' input (see 'help
         raw-input'.)
    
    Syntax: p <expr>
    
    Command Options Usage:
      p <expr>
    
    
    'p' is an abbreviation for 'expression --'
    

    下面是这个例子,可以看到expression执行了表达式,给属性变量name赋值,并返回了新赋的值,它可以动态的修改变量在内存中的值。

    (lldb) po self.name
    xiaoli
    
    (lldb) p self.name = @"David"
    (NSTaggedPointerString *) $5 = 0xc2f9f48bff645c0d @"David"
    (lldb) p self.name
    (NSTaggedPointerString *) $6 = 0xc2f9f48bff645c0d @"David"
    (lldb) 
    

    查看堆栈信息

    在一个函数的断点出,输入bt可查看调用堆栈信息

    (lldb) bt
    * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
      * frame #0: 0x000000010056e1c0 002--LLDB调试`-[ViewController test3:](self=0x0000000151e07750, _cmd="test3:", str=@"hook") at ViewController.m:64:20
        frame #1: 0x000000010056e180 002--LLDB调试`-[ViewController test2:](self=0x0000000151e07750, _cmd="test2:", str=@"hook") at ViewController.m:60:5
        frame #2: 0x000000010056e11c 002--LLDB调试`-[ViewController test1:](self=0x0000000151e07750, _cmd="test1:", str=@"hook") at ViewController.m:56:5
        frame #3: 0x000000010056e258 002--LLDB调试`-[ViewController touchesBegan:withEvent:](self=0x0000000151e07750, _cmd="touchesBegan:withEvent:", touches=1 element, event=0x00000002806d0fa0) at ViewController.m:71:5
        frame #4: 0x0000000193692b64 UIKitCore`forwardTouchMethod + 328
        frame #5: 0x0000000193692a08 UIKitCore`-[UIResponder touchesBegan:withEvent:] + 60
        frame #6: 0x00000001936a0af0 UIKitCore`-[UIWindow _sendTouchesForEvent:] + 1692
        frame #7: 0x00000001936a20a8 UIKitCore`-[UIWindow sendEvent:] + 3352
        frame #8: 0x000000019367eae8 UIKitCore`-[UIApplication sendEvent:] + 336
        frame #9: 0x00000001936f623c UIKitCore`__dispatchPreprocessedEventFromEventQueue + 5880
        frame #10: 0x00000001936f8798 UIKitCore`__handleEventQueueInternal + 4924
        frame #11: 0x00000001936f160c UIKitCore`__handleHIDEventFetcherDrain + 108
        frame #12: 0x000000018f5d67e0 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
        frame #13: 0x000000018f5d6738 CoreFoundation`__CFRunLoopDoSource0 + 80
        frame #14: 0x000000018f5d5ed0 CoreFoundation`__CFRunLoopDoSources0 + 180
        frame #15: 0x000000018f5d101c CoreFoundation`__CFRunLoopRun + 1080
        frame #16: 0x000000018f5d08bc CoreFoundation`CFRunLoopRunSpecific + 464
        frame #17: 0x000000019943c328 GraphicsServices`GSEventRunModal + 104
        frame #18: 0x00000001936666d4 UIKitCore`UIApplicationMain + 1936
        frame #19: 0x000000010056e518 002--LLDB调试`main(argc=1, argv=0x000000016f8978c8) at main.m:14:16
        frame #20: 0x000000018f45b460 libdyld.dylib`start + 4
    

    可以通过updown指令跟进堆栈的调用信息

    (lldb) up
    frame #1: 0x000000010056e180 002--LLDB调试`-[ViewController test2:](self=0x0000000151e07750, _cmd="test2:", str=@"hook") at ViewController.m:60:5
       57   }
       58   
       59   -(void)test2:(NSString *)str{
    -> 60       [self test3:str];
                ^
       61   }
       62   
       63   -(void)test3:(NSString *)str{
    (lldb) down
    frame #0: 0x000000010056e1c0 002--LLDB调试`-[ViewController test3:](self=0x0000000151e07750, _cmd="test3:", str=@"hook") at ViewController.m:64:20
       61   }
       62   
       63   -(void)test3:(NSString *)str{
    -> 64       NSLog(@"!!!%@",str);
                               ^
       65   }
    

    也可以通过frame select index(堆栈的序号)命令来查看具体序号堆栈的调用信息

    (lldb) frame select 3
    frame #3: 0x000000010056e258 002--LLDB调试`-[ViewController touchesBegan:withEvent:](self=0x0000000151e07750, _cmd="touchesBegan:withEvent:", touches=1 element, event=0x00000002806d0fa0) at ViewController.m:71:5
      68   
      69   -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
      70   {
    -> 71       [self test1:@"hook"];
               ^
      72       //Person * p1 = self.models.firstObject;
      73   }
      74   - (IBAction)save:(id)sender {
    

    通过frame variable命令查看具体序号堆栈的参数

    (lldb) frame variable
    (ViewController *) self = 0x0000000151e07750
    (SEL) _cmd = "touchesBegan:withEvent:"
    (__NSSetM *) touches = 0x00000002837f34a0 1 element
    (UITouchesEvent *) event = 0x00000002806d0fa0
    

    回滚thread return命令,会回到上一层调用堆栈,但是不会向下继续执行

    (lldb) thread return
    2019-10-26 16:24:54.495174+0800 002--LLDB调试[13707:437713] XPC connection interrupted
    

    内存断点watchpoint

    watchpoint可以对方法或者对象的内存地址设置断点,如果对属性操作,类似KVO观察者,如下是对一个属性变量设置的内存断点,如果属性变量的值发生改变了,程序就会自动中断

    (lldb) po self
    <ViewController: 0x1033040d0>
    
    (lldb) n
    (lldb) watchpoint set variable self->_name
    Watchpoint created: Watchpoint 1: addr = 0x103304428 size = 8 state = enabled type = w
        watchpoint spec = 'self->_name'
        new value: 0x0000000102c10098
    (lldb) c
    Process 14669 resuming
    
    Watchpoint 1 hit:
    old value: 0x0000000102c10098
    new value: 0x0000000102c10158
    2019-10-28 10:52:01.935109+0800 002--LLDB调试[14669:514790] !!!hook
    (lldb) po 0x0000000102c10098
    lilei
    
    (lldb) po 0x0000000102c10158
    David
    

    也可以通过如下方式操作

    (lldb) p &self->_name
    (NSString **) $0 = 0x0000000103303b48
    (lldb) watchpoint set expression 0x0000000103303b48
    Watchpoint created: Watchpoint 1: addr = 0x103303b48 size = 8 state = enabled type = w
        new value: 4343234712
    (lldb) c
    Process 14731 resuming
    
    Watchpoint 1 hit:
    old value: 4343234712
    new value: 4343234872
    (lldb) po 4343234712
    lilei
    
    (lldb) po 4343234872
    David
    

    watchpoint类似breakpoint也有listdelete等相关命令,可以通过help watchpoint命令来熟悉

    (lldb) help watchpoint
         Commands for operating on watchpoints.
    
    Syntax: watchpoint <subcommand> [<command-options>]
    
    The following subcommands are supported:
    
          command -- Commands for adding, removing and examining LLDB commands
                     executed when the watchpoint is hit (watchpoint 'commands').
          delete  -- Delete the specified watchpoint(s).  If no watchpoints are
                     specified, delete them all.
          disable -- Disable the specified watchpoint(s) without removing it/them. 
                     If no watchpoints are specified, disable them all.
          enable  -- Enable the specified disabled watchpoint(s). If no watchpoints
                     are specified, enable all of them.
          ignore  -- Set ignore count on the specified watchpoint(s).  If no
                     watchpoints are specified, set them all.
          list    -- List all watchpoints at configurable levels of detail.
          modify  -- Modify the options on a watchpoint or set of watchpoints in
                     the executable.  If no watchpoint is specified, act on the
                     last created watchpoint.  Passing an empty argument clears the
                     modification.
          set     -- Commands for setting a watchpoint.
    
    For more help on any particular subcommand, type 'help <command> <subcommand>'.
    

    command

    command可以用来给一个断点添加命令,如下所示,先给test1方法设置断点,然后用command添加命令,当再一次调用test1方法的时候,程序就会执行test1方法添加的指令

    (lldb) breakpoint set -n "[ViewController test1:]"
    Breakpoint 3: where = 002--LLDB调试`-[ViewController test1:] + 48 at ViewController.m:57:6, address = 0x0000000104b86100
    (lldb) breakpoint command add 3
    Enter your debugger command(s).  Type 'DONE' to end.
    > po self
    > p self.view
    > DONE
    (lldb) c
    Process 14830 resuming
     po self
    <ViewController: 0x105107580>
    
     p self.view
    (UIView *) $1 = 0x0000000105209550
    
    (lldb) breakpoint command list 3
    Breakpoint 3:
        Breakpoint commands:
          po self
          p self.view
    (lldb) breakpoint command delete 3
    (lldb) breakpoint command list 3
    Breakpoint 3 does not have an associated command.
    

    target stop-hook

    target stop-hook让每个断点都去执行一些命令,可以把它当作初始化的配置,如下所示,在每个断点处添加target stop-hook add -o "frame variable"查看每个断点的参数信息,当断点触发的时候,该断点的参数信息就会打印出来

    (lldb) breakpoint list
    Current breakpoints:
    1: file = '/Users/niujf/Desktop/ios逆向/007--LLDB/代码/002--LLDB调试/002--LLDB调试/ViewController.m', line = 56, exact_match = 0, locations = 1, resolved = 1, hit count = 0
    
      1.1: where = 002--LLDB调试`-[ViewController test1:] + 48 at ViewController.m:57:6, address = 0x00000001027ba100, resolved, hit count = 0 
    
    2: file = '/Users/niujf/Desktop/ios逆向/007--LLDB/代码/002--LLDB调试/002--LLDB调试/ViewController.m', line = 70, exact_match = 0, locations = 1, resolved = 1, hit count = 0
    
      2.1: where = 002--LLDB调试`-[ViewController touchesBegan:withEvent:] + 80 at ViewController.m:72:6, address = 0x00000001027ba240, resolved, hit count = 0 
    
    (lldb) target stop-hook add -o "frame variable" //查看每个断点的参数信息
    Stop hook #1 added.
    (lldb) c
    Process 14962 resuming
    (ViewController *) self = 0x0000000143e06f90
    (SEL) _cmd = "touchesBegan:withEvent:"
    (__NSSetM *) touches = 0x00000002800e5a20 1 element
    (UITouchesEvent *) event = 0x00000002831f8c80
    
    (lldb) c
    Process 14962 resuming
    (ViewController *) self = 0x0000000143e06f90
    (SEL) _cmd = "test1:"
    (__NSCFConstantString *) str = 0x00000001027bc138 @"hook"
    

    image

    image lookup -t xxxx可以查看文件的详细信息

    (lldb) image lookup -t ViewController
    Best match found in /Users/niujf/Library/Developer/Xcode/DerivedData/002--LLDB调试-hblhlghervytczgywjtrdblfcdga/Build/Products/Debug-iphoneos/002--LLDB调试.app/002--LLDB调试:
    id = {0x10000002b}, name = "ViewController", byte-size = 24, decl = ViewController.h:11, compiler_type = "@interface ViewController : UIViewController{
        NSMutableArray * _models;
        NSString * _name;
    }
    @property ( getter = models,setter = setModels:,readwrite,nonatomic ) NSMutableArray * models;
    @property ( getter = name,setter = setName:,readwrite,copy,nonatomic ) NSString * name;
    @end"
    

    image list查看调用的库

    (lldb) image list
    [  0] EE92FCA2-C78B-31CC-8C2C-C7A123E92F28 0x00000001029b8000 /Users/niujf/Library/Developer/Xcode/DerivedData/002--LLDB调试-hblhlghervytczgywjtrdblfcdga/Build/Products/Debug-iphoneos/002--LLDB调试.app/002--LLDB调试 
    [  1] 571392A7-E1E6-369F-8805-C1A141F3C1C5 0x0000000102cdc000 /Users/niujf/Library/Developer/Xcode/iOS DeviceSupport/13.1.3 (17A878)/Symbols/usr/lib/dyld 
    ...
    

    相关文章

      网友评论

          本文标题:iOS逆向-LLDB(VII)

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