iOS进阶

从MachO、DYLD到安全防护

2020-05-24  本文已影响0人  Miss_QL
1、MachO

其实MachO是一种文件格式,它包含了可执行文件、动态库、静态库、目标文件、dyld等。
对于我们编写的应用程序,在编译后的app右键显示包内容,就能看到与包名一样的可执行文件,可以通过file 可执行文件指令查看该文件的具体信息。

file指令.png

上图可执行文件是arm64架构的,而有的应用可执行文件是胖二进制文件(也叫通用二进制文件格式的),会包含多种架构,比如arm64、armv7。我们也可以通过lipo命令实现拆分架构(通过-thin指令)和合并架构(通过-create指令),一般在拆分和合并静态库的时候用到。

MachO结构

  • Header 用于快速确认文件,比如cpu类型、文件类型
  • LoadCommands 用于指示加载器如何加载二进制文件
  • Data 用于存放数据,比如代码、字符串常量、类、方法等
2、DYLD

dyld,动态链接器,用来加载所有的库和可执行文件。
dyld源码是苹果开放出来的,感兴趣的小伙伴可以下载源码查看分析下。

dyld加载流程

  • 程序执行从_dyld_start 开始
  • 进入dyld:main函数(这里做了很多工作)
    • 配置环境变量
    • 加载共享缓存库(一开始就判断是否是禁用,iOS无法被禁用)
    • 实例化主程序
    • 加载动态库
      • 最先加载插入的动态库,通过判断环境变量DYLD_INSERT_LIBRARIES是否为空。
      • 然后加载系统的动态库
      • 再加载weak动态库
    • 初始化主程序
    • 初始化方法(这里是最关键的地方)
      • 经过一系列初始化,调用notifySingle函数,该函数会执行一个回调。通过断点调试可以发现,这个回调是_objc_init 初始化的时候赋值的一个函数load_images,在load_images里面会执行call_load_methods函数,而call_load_methods函数内部会循环调用各个类的load方法。
      • doModInitFunctions函数。内部会调用带atrribute((constructor))的c++函数。
      • 返回主程序的入口函数。开始进入主程序的main函数。
3、安全防护

(1)RESTRICT
通过对dyld源码的分析,可以找到一个安全防护的突破口,就是在加载动态库的第一步,通过判断环境变量DYLD_INSERT_LIBRARIES是否为NULL,来决定是否加载插入的动态库,通常越狱插件都是在这个时候加载的。那我们只要想办法把环境变量DYLD_INSERT_LIBRARIES移除掉,就可以解决这种类型的进攻。系统也确实给我们提供了一个入口,就是通过RESTRICT段,具体操作如下:
打开自己要做防护的应用程序,选择Target -> Build Settings -> Other Linker Flags -> 添加-Wl,sectcreate,__RESTRICT,__restrict,/dev/null(友情提示:Xcode11中编译会报错,旧版本Xcode可用,跑不通的小伙伴表打我😂)。添加完成后,编译一下,把可执行文件拖到MachOView里面看一下,就会发现神奇的多了一个__RESTRICT段,你再Tweak一下试试😏

RESTRICT防护Tweak.png

(2)反调试Ptrace
ptrace(PT_DENY_ATTCH,0,0,0)拒绝进程被附加

(3)反调试sysctl
sysctl这个函数的作用是去检测程序的状态。

(4)其他方法

防护的手段千千万,这里只是提供给小伙伴一个做防护的思路,毕竟进攻技术在发展,防护也一样😊

上一篇下一篇

猜你喜欢

热点阅读