飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 3298|回复: 4

[iOS] [转载]使用Python脚本强化LLDB调试器

[复制链接]
  • TA的每日心情
    开心
    2019-3-17 22:44
  • 签到天数: 132 天

    [LV.7]常住居民III

    发表于 2016-10-20 22:02:19 | 显示全部楼层 |阅读模式
    本帖最后由 tree_fly 于 2016-10-20 21:57 编辑

    使用Python脚本强化LLDB调试器


    LLDB是Xcode自带的调试器,作为一个iOS应用开发程序员,平时我在开发应用时会使用LLDB来调试代码。在逆向应用时,也会用到LLDB来跟踪应用的执行过程。
    LLDB还内置了一个Python解析器,使用Python脚本可以方便LLDB的调试,比如自动化执行一些命令,或者自动化处理数据之类的,具体说明可以参考官方的文档:LLDB Python Reference

    以下就以一个具体的例子来演示一个Python脚本的编写过程:

    一、获取方法的偏移地址

    运行系统自带的计算器Calculator.app:


    可以看到计算器的菜单里有一个“关于计算器”的选项:


    如果我们要在点击“关于计算器”事件断下来的话,就要给这个方法设置一个断点。

    先找到计算器的可执行文件的路径,路径为:/Applications/Calculator.app/Contents/MacOS/Calculator。
    打开Hopper Disassembler反汇编调试器,将可执行文件拖进去,等待Hopper分析完成。

    在左侧的搜索框输入”showabout”,会搜索到一个结果:


    点击这个结果,会跳转到该方法的汇编代码处:

    [Asm] 纯文本查看 复制代码
                         -[CalculatorController showAbout:]:
    00000001000093dd         push       rbp                                         ; Objective C Implementation defined at 0x1000188d0 (instance)
    00000001000093de         mov        rbp, rsp
    00000001000093e1         mov        rdi, qword [ds:objc_cls_ref_NSDictionary]   ; objc_cls_ref_NSDictionary, argument "instance" for method imp___got__objc_msgSend
    00000001000093e8         mov        rsi, qword [ds:0x10001b6f0]                 ; @selector(dictionaryWithObject:forKey:), argument "selector" for method imp___got__objc_msgSend
    00000001000093ef         lea        rdx, qword [ds:cfstring_2000]               ; @"2000"
    00000001000093f6         lea        rcx, qword [ds:cfstring_CopyrightStartYear] ; @"CopyrightStartYear"
    00000001000093fd         call       qword [ds:imp___got__objc_msgSend]
    0000000100009403         mov        rdi, rax
    0000000100009406         pop        rbp
    0000000100009407         jmp        imp___stubs__NSShowSystemInfoPanel
                            ; endp

    由汇编代码可知[CalculatorController showAbout:]方法在文件中的偏移地址为0x00000001000093dd。

    二、使用LLDB调试器设置断点

    接下来运行终端,执行以下命令,让LLDB调试器依附计算器的进程:

    [Bash shell] 纯文本查看 复制代码
    Jobs: ~$ ps aux | grep Calculator
    Jobs            79888   0.0  0.1  2781792  11620   ??  S     6:21下午   0:01.07 /Applications/Calculator.app/Contents/MacOS/Calculator
    Jobs            80204   0.0  0.0  2432772    568 s002  R+    6:26下午   0:00.00 grep Calculator
    Jobs: ~$ lldb -p 79888
    (lldb) process attach --pid 79888
    Process 79888 stopped
    * thread #1: tid = 0x6030af, 0x00007fff912d34de libsystem_kernel.dylib`mach_msg_trap + 10, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
        frame #0: 0x00007fff912d34de libsystem_kernel.dylib`mach_msg_trap + 10
    libsystem_kernel.dylib`mach_msg_trap:
    ->  0x7fff912d34de <+10>: retq
        0x7fff912d34df <+11>: nop
    
    libsystem_kernel.dylib`mach_msg_overwrite_trap:
        0x7fff912d34e0 <+0>:  movq   %rcx, %r10
        0x7fff912d34e3 <+3>:  movl   $0x1000020, %eax
    
    Executable module set to "/Applications/Calculator.app/Contents/MacOS/Calculator".
    Architecture set to: x86_64h-apple-macosx.
    (lldb) continue
    Process 79888 resuming
    (lldb)

    接着执行以下命令获取应用的ASLR偏移地址:

    [Bash shell] 纯文本查看 复制代码
    (lldb) image list -o
    [  0] 0x000000000cafa000
    [  1] 0x00007fff93d51000
    [  2] 0x000000010cb1e000
    ......
    (lldb)

    第一行数据的16进制地址0x000000000cafa000就是应用的ASLR偏移地址,之前我们已经找到了[CalculatorController showAbout:]方法的偏移地址是0x00000001000093dd,那么该方法在内存中的地址就是0x000000000cafa000 + 0x00000001000093dd。

    所以我们可以执行下面的命令来给这个方法设置断点,注意加号两边不要有空格:

    [Bash shell] 纯文本查看 复制代码
    (lldb) br set -a "0x000000000cafa000+0x00000001000093dd"
    Breakpoint 1: where = Calculator`___lldb_unnamed_function161$$Calculator, address = 0x000000010cb033dd
    (lldb)

    这时点击菜单的“关于计算器”选项,程序就会断下来:

    [Bash shell] 纯文本查看 复制代码
    Process 79888 stopped
    * thread #1: tid = 0x6709de, 0x000000010cb033dd Calculator`___lldb_unnamed_function161$$Calculator, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
        frame #0: 0x000000010cb033dd Calculator`___lldb_unnamed_function161$$Calculator
    Calculator`___lldb_unnamed_function161$$Calculator:
    ->  0x10cb033dd <+0>:  pushq  %rbp
        0x10cb033de <+1>:  movq   %rsp, %rbp
        0x10cb033e1 <+4>:  movq   0x12b98(%rip), %rdi       ; (void *)0x00007fff78684488: NSDictionary
        0x10cb033e8 <+11>: movq   0x12301(%rip), %rsi       ; "dictionaryWithObject:forKey:"
    (lldb)

    三、编写Python脚本

    那么问题来了,我们每次调试应用都要先手动获取ASLR偏移地址,如果要给多个地址打断点的话,就要写很多遍”ASLR偏移地址+方法偏移地址”,操作比较繁琐。如果这些重复性的操作可以自动完成的话,在平时的使用过程中应该能节省不少时间。

    用Python就可以很方便地实现这个功能,接下来我们就来写一个简单的脚本,以简化设置断点的操作。脚本的主要功能是自动获取应用的ASLR地址,用户设置断点时只需输入方法在文件中的的偏移地址,脚本会自动把ASLR偏移地址和方法偏移地址相加,再设置断点。

    新建一个Python文件,保存至~/sbr.py,代码如下:

    [Python] 纯文本查看 复制代码
    #!/usr/bin/python
    #coding:utf-8
    
    import lldb
    import commands
    import optparse
    import shlex
    import re
    
    
    # 获取ASLR偏移地址
    def get_ASLR():
        # 获取'image list -o'命令的返回结果
        interpreter = lldb.debugger.GetCommandInterpreter()
        returnObject = lldb.SBCommandReturnObject()
        interpreter.HandleCommand('image list -o', returnObject)
        output = returnObject.GetOutput();
        # 正则匹配出第一个0x开头的16进制地址
        match = re.match(r'.+(0x[0-9a-fA-F]+)', output)
        if match:
            return match.group(1)
        else:
            return None
    
    # Super breakpoint
    def sbr(debugger, command, result, internal_dict):
    
        #用户是否输入了地址参数
        if not command:
            print >>result, 'Please input the address!'
            return
    
        ASLR = get_ASLR()
        if ASLR:
            #如果找到了ASLR偏移,就设置断点
            debugger.HandleCommand('br set -a "%s+%s"' % (ASLR, command))
        else:
            print >>result, 'ASLR not found!'
    
    # And the initialization code to add your commands 
    def __lldb_init_module(debugger, internal_dict):
        # 'command script add sbr' : 给lldb增加一个'sbr'命令
        # '-f sbr.sbr' : 该命令调用了sbr文件的sbr函数
        debugger.HandleCommand('command script add sbr -f sbr.sbr')
        print 'The "sbr" python command has been installed and is ready for use.'


    然后在LLDB中执行下面的语句就可以把脚本导入到LLDB:

    [Bash shell] 纯文本查看 复制代码
    (lldb) command script import ~/sbr.py
    The "sbr" python command has been installed and is ready for use.
    (lldb)


    输出结果表示名为sbr的Python命令已经装载好并可以使用了。
    sbr是Super breakpoint的意思,只需接收一个方法偏移地址作为参数。
    接下来验证一下效果,先清除断点列表,再用sbr命令来设置断点。

    [Bash shell] 纯文本查看 复制代码
    (lldb) br delete
    About to delete all breakpoints, do you want to do that?: [Y/n] y
    All breakpoints removed. (1 breakpoint)
    (lldb) sbr 0x00000001000093dd
    Breakpoint 2: where = Calculator`___lldb_unnamed_function161$$Calculator, address = 0x000000010cb033dd
    (lldb)


    这时点击菜单的“关于计算器”选项,方法也成功断下来了。

    四、启动LLDB时自动加载Python脚本

    对于经常要使用到的脚本,可以在LLDB的初始化文件里添加命令加载脚本,这样LLDB启动后就能使用自定义的命令了。
    修改~/.lldbinit文件,在文件里加入一行:

    command script import ~/sbr.py
    重新进入LLDB,可以看到脚本已经自动加载了:

    [Bash shell] 纯文本查看 复制代码
    Jobs: ~$ lldb
    The "sbr" python command has been installed and is ready for use.
    (lldb) command source -s 1 '/Users/Jobs/./.lldbinit'
    The "sbr" python command has been installed and is ready for use.
    (lldb)


    PS:感谢作者分享,原文地址:http://www.cnblogs.com/yuanxiaoping_21cn_com/p/5433286.html

    评分

    参与人数 5威望 +64 飘云币 +60 收起 理由
    orz + 4 很给力!
    0xcb + 8 + 8 很给力!
    EvilNing + 4 + 4 很给力!
    GeekCat + 40 + 40 飞博士牛X~~
    smallhorse + 8 + 8 很给力!

    查看全部评分

    PYG19周年生日快乐!
  • TA的每日心情
    开心
    3 天前
  • 签到天数: 1372 天

    [LV.10]以坛为家III

    发表于 2016-10-20 22:40:10 | 显示全部楼层
    飞树表哥牛犇!膜拜!
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2021-9-29 15:05
  • 签到天数: 114 天

    [LV.6]常住居民II

    发表于 2016-10-21 10:39:51 | 显示全部楼层
    666,脚本助力效率
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2022-12-4 17:48
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    发表于 2016-10-22 10:01:15 | 显示全部楼层
    谢谢分享   
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情

    2017-12-31 15:45
  • 签到天数: 120 天

    [LV.7]常住居民III

    发表于 2016-10-22 10:33:22 | 显示全部楼层
    (话说我有地板坐吗?)
    感谢楼主分享!
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表