iOS逆向工程(九):ASLR

ASLR前言

以前我们用Xcode的LLDB指令打断点时,可以用方法名打断点,例如breakpoint set -n "[UIViewController touchBegin:]",但是我们想动态调试别人的App,就不能用方法名称了,需要用到方法的内存地址才能打,例如breakpoint set --address 0x123123123
而想知道方法的内存地址就需要学习ASLR
一、什么是ASLR?
    1. ASLR,全称是Address Spce Layout Randomization,翻译过来就是地址空间布局随机化,是一种针对缓冲区溢出的安全保护技术,通过对堆、栈、共享库映射等线性区布局的随机化,增加了攻击者预测目的地址的难度,防止攻击者直接定位代码位置,阻止溢出攻击。
    1. 苹果从iOS 4.3之后引入了ASLR技术,所以想要逆向别人的App,学会ASLR是必不可少的。
    1. ASLR的概念看着复杂,实际上非常简单,其实就是当Mach-O文件载入虚拟内存的时候,起始地址不从0x00000000开始了,而是随机增加一段,例如从0x50000开始,后面的函数地址都会增加0x50000
二、Mach-O文件的内部结构
    1. Mach-O文件的内部分为三个区域:HeaderLoad CommandsData,如下图所示:
      iOS逆向工程(九):ASLR_第1张图片
      Mach-O文件内部
    1. Header区,存放了CPU类型、Mach-O文件的具体类型、LoadCommands的数量、LoadCommands的大小等数据,如下所示:
      iOS逆向工程(九):ASLR_第2张图片
      Header.png
    1. Load Commands区,存放了各段的名称、各段的虚拟内存地址、各段的虚拟内存大小、各段的在Mac-O中的偏移量、各段的在Mac-O中的偏移大小等数据 ,如下图所示,重点注意看VM Address、VM SizeFile Offset、File Size这两组数据 。
    • VM Address、VM Size记录这此段在虚拟内存的位置和大小

    • File Offset、File Size记录着此段在Mach-O中的位置和大小。

iOS逆向工程(九):ASLR_第3张图片
image.png
    1. Data区,存放着各段数据
三、未使用ASLR时,Mach-O文件是如何载入内存的?
    1. 我们观察Mach-O文件的Load Commands各段的描述信息,重点观察VM Address、VM SizeFile Offset、File Size,就可以知道Mach-O在虚拟内存中是如何存放的了
    1. 例如下图中的LC_SEGMENT_64(__PAGEZERO)段,我们可以看出来,PAGEZERO段在虚拟内存中是从0x0开始,大小是0x100000000PAGEZERO段在Mach-O中是从0x0开始,大小是0x0,也就是说PAGEZERO在Mach-O中实际不存在数据 ,只有加载到内存后才会展开。
      iOS逆向工程(九):ASLR_第4张图片
      Load Commands.png
    1. 例如下图中的__TEXT段,我们可以看出来,TEXT段在虚拟内存中从0x10000000开始,大小是0x6B8C000TEXT段在Mach-O中从0x0开始,大小是0x6B8C000
      iOS逆向工程(九):ASLR_第5张图片
      TEXT段
    1. 例如下图中的__DATA段 ,我们可以看出来,DATA段在虚拟内存中从0x106B8C000开始,大小是0x1820000TEXT段在Mach-O中从0x6B8C000开始,大小是0x1350000
      iOS逆向工程(九):ASLR_第6张图片
      DATA段
    1. 综上所述 ,我们就可以绘制出比较直观的图来表示,如下图所示:
iOS逆向工程(九):ASLR_第7张图片
未使用ASLR时,Mach-O装载到内存
四、使用ASLR时,Mach-O文件是如何载入内存的?
    1. ASLR会在虚拟内存中的最开始的位置产生了随机偏移量,每次载入内存时,偏移量都会不同,导致后续各段的地址都会增加此偏移量,以增加攻击者预测地址的难度
    1. 例如:ASLR产生的随机偏移量是0x5000,那么Mach-O载入虚拟内存中后,就如下图所示:
      iOS逆向工程(九):ASLR_第8张图片
      使用ASLR后,Mach-O载入内存
    1. 苹果从iOS 4.3之后引入了ASLR技术,也就说把Mach-O载入内存后,所有的地址都会经过ASLR偏移
    1. 我们使用MachOView工具静态分析看到的VM Address,是未经过ASLR偏移的虚拟内存地址,也就是说MachOView中的VM Address加上ASLR偏移量才是虚拟内存中的真正地址
    1. 总结一下:
    • Hopper、IDA、MachOView等工具中的看到的地址都是未使用ASLR的VM Address,所以要想知道虚拟内存中真正地址,就需要再加上ASLR偏移量

    • 虚拟内存中的真正地址 = ASLR偏移量 + PAGEZERO的大小 + Mach-O中的偏移量 (其中PAGEZERO的大小就是VM Size,Mach-O中的偏移量就是Offset,因为PAGEZERO到内存中才会展开,所以要加上PAGEZERO的大小)

    • 虚拟内存中的真正地址 = ASLR偏移量 + 用工具看到的VM Address

    • 虚拟内存中的真正地址 = ASLR偏移量 + Mach-O文件中的VM Address

    • Mach-O文件中的File Offset = 虚拟内存中的真正地址 - ASLR偏移量 - PAGEZERO的大小

    1. 想要得到ASLR偏移量,可以在使用LLDB命令image list -o -f | grep Mach-O文件名称,来查看加载到内存中的ASLR偏移量。(注意:ASLR是随机的,每次加载到内存都不一样)
五、如何给别人的App打断点,进行调试
    1. 按照上一篇的方法,进入到WeChat的lldb环境
    1. 使用LLDB指令image list -o -f | grep Mach-O文件名称,获取ASLR偏移量,如下图所示,本次载入内存的偏移量是0x27c0000
      image.png
    1. 用Hopper等工具静态分析出某个函数在虚拟内存中的函数地址,这里的函数地址是静待分析出来的,也就是未经过ASLR偏移的地址,并不能直接用于打断点,如下图所示,-[BaseMsgContentViewController SendTextMessageToolView:]函数的未ASLR偏移的函数地址是0x1002aec90
      image.png
    1. 使用LLDB指令breakpoint set -a 函数地址,给某个函数打断点,这里的函数地址指的是虚拟内存中的真实函数地址,也就是说这里的函数地址,是ASLR偏移量+静待分析的函数地址,也就是0x1002aec90+0x27c0000,完整的LLDB指令就是 breakpoint set -a 0x1002aec90+0x27c0000,如下图所示:
      iOS逆向工程(九):ASLR_第9张图片
      image.png
    1. 打完断点之后,当App触发此断点时,就会卡住,以便我们输入LLDB调试,例如,我这里对微信的发送消息的方法-[BaseMsgContentViewController SendTextMessageToolView:]打了断点,之后每次发消息时都会卡主,以便我们继续输入LLDB指令调试
    1. 如果不想要断点了,可以用breakpoint delete 断点编号删除断点;可以通过breakpoint list命令,列出所有的断点编号

你可能感兴趣的:(iOS逆向工程(九):ASLR)