美文网首页逆向学习
iOS逆向实战--019:符号的剥离与恢复

iOS逆向实战--019:符号的剥离与恢复

作者: 帅驼驼 | 来源:发表于2021-05-11 12:38 被阅读0次
    剥离符号

    strip:移除指定符号。在Xcode中默认strip是在Archive的时候才会生效,移除对应符号

    strip命令的使用:

    • strip -x:除了全局符号都可以移除 (动态库使用)
    • strip -S:移除调试符号(静态库使用)
    • strip:除了间接符号表中使用的符号,其他符号都移除(上架App使用)

    案例1:

    剥离符号在Xcode中的设置

    来到Build Setting,设置Deployment Postprocessing

    • 打开后在编译阶段就会运行strip

    设置Strip Debug Symbols During Copy

    • 当应用在编译阶段copy了某些二进制文件时,打开该选项会脱掉该二进制的调试符号。但是不会脱去链接的最终产物(可执行文件\动态库)的符号信息。要脱去链接的产物(App的可执行文件)的符号信息

    设置Strip Linked Product

    • 如果没有打开Deployment Postprocessing,则会在Archive处理链接的最终产物(可执行文件)的符号信息。否则,在链接完成之后就会处理符号信息

    设置Strip Style(符号剥离级别),它会在生成可执行文件后进行优化,相当于对Mach-O文件进行修改

    • All Symbols:除了间接符号表中使用的符号,其他符号都移除(上架App使用)
    • Non-Global Symbols:除了全局符号都可以移除 (动态库使用)
    • Debugging Symbols:移除调试符号(静态库使用)

    Strip Style原理

    • App:可以剥离除间接符号表以外的所有符号
    • 动态库:可以剥离除全局符号以外的所有符号
    • 静态库:静态库是.o文件的合集,符号都存储在重定位符号表中。静态库只能剥离调试符号

    Debugging Symbols:剥离.o/静态库的调试符号

    Debugging Symbols:剥离动态库/可执行文件的调试符号

    All Symbols:剥离除间接符号表以外的所有符号

    Non-Global Symbols:剥离除全局符号以外的所有符号

    案例2:

    剥离除间接符号之外的所有符号

    查看未剥离符号时的MachO

    • 包含本地符号、全局符号、间接符号

    Xcode中设置All Symbols,编译项目

    • 多出.bcsymbolmap文件,用于Bitcode线上崩溃,恢复符号使用

    查看剥离符号之后的MachO

    • 只剩下间接符号

    使用MachOView查看

    • 粉色:本地符号
    • 橙色:全局符号
    • 绿色:间接符号
    • 符号的Value值,代表函数实现地址,即:isa。间接符号此时还无法确定实现地址,所以全部为0

    案例3:

    对剥离调式符号的程序,设置Xcode断点

    touchesBegan方法上设置断点

    真机运行项目,点击屏幕,不会触发断点,直接输出结果

    symbolDemo[4798:893531] 第二次外部函数的调用!
    

    因为调试符号已经被剥离,所以Xcode断点不会触发

    案例4:

    对上述案例,设置符号断点

    NSLog设置符号断点

    真机运行项目,点击屏幕,触发NSLog断点

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

    bt
    -------------------------
    * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
     * frame #0: 0x000000019d9327f0 Foundation`NSLog
       frame #1: 0x0000000100f95e44 symbolDemo`___lldb_unnamed_symbol2$$symbolDemo + 32
       frame #2: 0x0000000100f95e78 symbolDemo`___lldb_unnamed_symbol3$$symbolDemo + 40
       frame #3: 0x0000000100f95eec symbolDemo`___lldb_unnamed_symbol4$$symbolDemo + 104
       frame #4: 0x000000019eefe774 UIKitCore`forwardTouchMethod + 316
       frame #5: 0x000000019eefe624 UIKitCore`-[UIResponder touchesBegan:withEvent:] + 60
       frame #6: 0x000000019ef0c9cc UIKitCore`-[UIWindow _sendTouchesForEvent:] + 640
       frame #7: 0x000000019ef0e550 UIKitCore`-[UIWindow sendEvent:] + 3824
       frame #8: 0x000000019eee9934 UIKitCore`-[UIApplication sendEvent:] + 744
    

    由于调试符号被剥离,自定义的方法和函数,都会显示为_unnamed_symbol。在逆向过程中,动态调试这样的符号不利于分析

    动态调试剥离符号后的App,如果是OC方法,会调用objc_msgSend函数,通过分析x0x1寄存器,查看selfcmd也能找到名称

    但此时不知道自定义函数的名称,符号断点只能设置在系统函数上,然后计算自定义函数在调用时的偏移地址

    在下一次运行时,使用程序首地址 + 偏移地址计算出函数地址,最后对函数地址设置断点

    使用以上方式,过于繁琐,所以应该想办法恢复符号

    恢复符号

    符号表中的符号被剥离,但对于OC的类和方法,MachO中还是会保留它们的名称,以供runtime使用

    __TEXT,__objc_methname中,保留方法列表

    __TEXT,__objc_classname中,保留类的列表

    所以OC的类和方法,可以通过分析代码段,重新生成一份符号表

    案例1:

    使用restore-symbol恢复符号表

    MachO文件,拷贝到restore-symbol同级目录

    恢复符号表

    ./restore-symbol symbolDemo -o symbolDemo2
    -------------------------
    2021-05-08 18:40:55.494 restore-symbol[89516:35801034] Unknown load >command: 0x00000032
    Scan OC method in mach-o-file.
    Scan OC method finish.
    
    • 第一个参数:将要恢复的MachO文件
    • 第二个参数:恢复符号表后,导出的MachO文件

    使用MachOView,查看恢复符号表后的MachO文件

    • 恢复的符号添加到符号表的最后面
    • 静态函数的符号无法恢复

    恢复符号表后的MachO文件,可以使用重签名技术,进行动态调式

    总结

    剥离符号

    • strip:移除指定符号。在Xcode中默认strip是在Archive的时候才会生效,移除对应符号

    strip命令的使用:

    • strip -x:除了全局符号都可以移除 (动态库使用)
    • strip -S:移除调试符号(静态库使用)
    • strip:除了间接符号表中使用的符号,其他符号都移除(上架App使用)

    XcodeStrip Style的设置:

    • All Symbols:除了间接符号表中使用的符号,其他符号都移除(上架App使用)
    • Non-Global Symbols:除了全局符号都可以移除 (动态库使用)
    • Debugging Symbols:移除调试符号(静态库使用)

    恢复符号

    • 符号表中的符号被剥离,但对于OC的类和方法,MachO中还是会保留它们的名称,以供runtime使用
    • OC的类和方法,可以通过分析代码段,重新生成一份符号表
    • 使用restore-symbol工具,可恢复符号表

    相关文章

      网友评论

        本文标题:iOS逆向实战--019:符号的剥离与恢复

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