
OTA是over-the-air的缩写。在“系统设置”中,我们可以通过点击“立即更新”按钮直接更新系统。
它用于小版本更新,通常每两个月更新一次。但是,如果苹果公司认为内核中存在紧急漏洞,并且已经被积极利用,并且无法通过RSR(快速安全响应)修复,则可能在几周内可用,OTA更新包从Apple CDN服务器下载。
例如,为了更新到12.6,12.5和12.4的软件包是不同的。更新过程是应用补丁码,所以不同的操作系统版本有不同的补丁码。在大多数情况下,系统越老,包就越大。
引导目录包含与引导过程相关的内容,增量更新的真正补丁代码位于名为payloadv2的目录中。有一个名为payload.bom的关键文件,它列出了OTA包中的所有项目及其校验和值。文件payload.bom.signature用于验证payload.bom文件的完整性。文件pre.bom和post.bom列出了更新前后系统上的所有项目及其校验和值。Info.plist文件提供了有关当前OTA包的一些基本信息,例如预版本、目标版本等。
在payloadv2文件夹中,有一些需要注意的重要文件。新系统中的新数据文件被压缩为名为data_payload的文件。ecc_data文件夹包含一些与文件权限相关的文件。links.txt文件列出了新系统的所有硬链接。removed.txt文件列出了需要从当前系统中删除的所有项目。
从这个文件中,我们可以看到基本URL和构建完整URL的相对路径。它还包含版本、发布日期、包大小v2rayng无法更新、SHA1值和其他有用的信息。
我们还应该注意的一点是,它是用标志库验证进行签名的。因此,我们不能通过将动态库注入到这项服务中来直接享受这些权限。
但在研究过程中,我意识到服务中的协议方法没有实现,所以我可能会在未来的版本中再次检查。
在xpc handler(Handler主要用于异步消息的处理:当发出一个消息之后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分在消息队列中逐一将消息取出,然后对消息进行处理,也就是发送消息和接收消息不是同步的处理。 )方法中,我们可以看到它通过一个全局数组来调度xpc请求:
如果xpc客户机具有相应请求所需的权限,则服务将相应地调用处理例程函数。
全局调度表有7个元素,每个元素有3个成员:操作的名称、所需的权限字符串和实际处理例程函数的地址。
因此,在mobileasseted进程移动到最终可信位置之前,有一个修改内容的时间窗口。因此,可信位置中的OTA包的内容是不可信的,需要进行验证。
当我尝试替换有效负载时。由于权限问题,mobileassetd进程无法调用文件API,因此拒绝移动到最终路径:
但事实是,一旦通过检测,它将调用API rename来移动包内容。所以我很早就替换了目标文件。
幸运的是,有一个关键字字符串(“Moving file in …”) 表明通过检查的时间窗口。因此,一旦从日志中监控到该关键字,我就可以替换目标文件。
监控日志,一旦检测到关键字“Moving file”,就立即从OTA包中替换目标文件。
此服务的职责是从可信位置验证不可信的OTA包的内容。那么,它如何验证OTA包呢?
如上所述,payload.bom文件列出OTA包中的所有项目及其校验和值:
它打开文件payload.bom并读取其内容。接下来,该函数将payload.bom文件中指定的文件摘要值与最终路径上的真实摘要值进行比较:
位于受信任位置的payload.bom文件不能直接修改,但我们可以在mobileassetd进程移动OTA包之前用符号链接替换它。因此,可以使用符号链接随时修改payload.bom文件。
接下来,在函数verify_package_signature中,它根据符号链接从受控位置读取BOM文件,因此我们使用原始payload.BOM来通过检查。
然后在函数verify_package_contents中,它也遵循符号链接并使用受控BOM文件验证OTA包中的所有其他项。所以现在,我们可以模拟payload.bom文件以替换OTA包中的所有其他项。
符号链接(/tmp/payload.bom)已成功移动到最终受信任的位置!
因此,我可以通过修改txt文件获得一个原语来删除任意受sip保护的路径。
最基本的事实是,苹果需要通过OTA更新来更新操作系统内核文件。因此,OTA更新过程必须具备突破SSV保护的能力。
macOS系统有一个隐藏的更新卷 (/System/Volumes/Update/mnt1),它是当前操作系统的快照。然后将所有补丁应用于该快照。如果更新过程成功,它将更新密封值并引导新的操作系统。如果更新失败,它将恢复到以前的快照。
在深入研究了UpdateBrainService之后,我总结了OTA更新过程中的关键工作流,如下所示:
在OTA更新过程中,按照预期将精心制作的data_payload提取到快照中。
我的第二种方法是滥用应用修复的copy_patched_files函数。这与OTA更新过程更新内核的方式相同。
然而,困难在于我必须自己创建修复文件,它是BXDIFF 5格式的,并且没有文档记录。所以,我必须先研究一下文件格式。
谷歌搜索这个文件格式后,我找到两个GitHub存储库,它们都用于将修复文件应用于旧文件,然后生成新文件。但是,我需要基于两个不同的文件生成一个修复文件。
但它们确实帮助我理解了文件格式,通过阅读代码,我知道BXDIFF 5文件由4部分组成:Header, Control, Diff和Extra。
红色的部分是未知的,似乎是无用的。绿色部分为修复前后的哈希值,用于验证修复是否成功。蓝色部分是以下部分的大小。
Control部分使用LZMA算法进行压缩,解压后的Control段数据为24字节,由3种控制命令组成:
第一个是混合长度,它指定从Diff部分混合多少字节。第二个是复制长度,第三个是查找长度。
Diff部分和Extra部分也是LZMA压缩的v2rayng百科。解压缩后,数据是一个原始字节数组,以前由Control部分使用。
我的目标是替换内核中系统命令uname的输出字符串。所以我应该修改Diff部分。
接下来,重写diffSeekPosition处的新字节,并使用LZMA算法压缩新创建的Diff 部分。我们可以直接重用Control部分和Extra部分。
最后,更新新Header 部分中的哈希值和大小在我为内核制作了一个修复文件之后,它就如预期的那样工作了!
虽然它只适用于没有T2芯片的英特尔Mac电脑,但我能够将恶意shellcode 注入内核,并在ring 0执行任意代码!Ring0是CPU工作在保护模式下的一种特权模式,也称为内核模式或系统模式。在这种模式下,CPU能够访问所有的系统资源,包括内存、设备、引导程序和所有进程的地址空间。
相对于其他环节,ring0级别具有最高权限。它拥有锁定内存、直接访问硬件、中断处理、定时器、缓存管理等很多特权。
ring0属于操作系统内核,只有操作系统内核可以运行在ring0级别,这使得操作系统可以对计算机硬件进行直接的管理和控制。
其他Mac平台(Intel Mac with T2 Chip & Apple Silicon Mac)面临的挑战是名为“安全启动”的硬件缓解措施。默认设置是“完全安全”,它提供了最高级别的安全。
在启动过程中,Mac会验证启动磁盘上操作系统的完整性,以确保它是合法的。如果操作系统是未知的或无法验证为合法的,你的Mac连接到苹果下载更新的完整性信息,它需要验证操作系统。这些信息是你的Mac所独有的,它可以确保你的Mac从一个受苹果信任的操作系统启动。
一个例子是名为AssetData的文件夹。因此,我们可以直接修改OTA包的内容,即使它们被移动到最终的可信位置!
所以验证OTA包的完整性是没有用的。我们可以在OTA包通过包验证后,通过修改包内容直接获得sip绕过原语。
它通过调用API moveItemAtURL:toURL:来移动OTA包内容,它本身保留了源文件标志和扩展属性。
如上所述,我们可以通过通过sip绕过原语替换内核修复文件来执行任意内核代码,就像上述利用2中所做的那样。
研究发现,如果更换得太晚,重启后它将无法工作。但是,如果我过早地替换它,新内核将被补丁覆盖。那么从快照替换内核文件的正确时间是什么时候呢?我怎样才能抓住这个时间呢?
所以我写了一个名为spin_for_log的函数来等待所有补丁启动的正确时刻:
如上所述,它只适用于没有T2芯片的英特尔mac电脑,而T2芯片没有安全启动缓解功能。
bootbase.efi文件采用Windows PE格式。我没有开发自己的EFI程序来改变操作系统的引导过程。为了快速验证概念,我刚刚将入口点代码修复为“0xEB 0xFE”,这是一个用于死循环的短跳转指令:
更换bootbase.efi文件并重新启动后,系统将陷入死循环,为了验证这一点,我设置了一个远程GDB存根,并在IDAPro中远程连接到它。因此,你可以看到我的shell代码确实按预期在EFI shell中执行!
为了有效地验证OTA包的完整性,有必要从payload.bom文件中列出OTA包中的所有项目。
因此,攻击者可以通过替换旧版本的dylib来执行降级攻击,旧版本的dylib由apple签名并通过库验证。
与OTA更新包类似,UpdateBrainService bundle包也可以由root用户修改。因此,攻击者可以在将UpdateBrainService移动到受信任位置之前用旧版本替换它,然后再次利用旧漏洞。
现在,苹果重构了整个流程。它确保整个过程是可信的,并且包的内容不被篡改: