快捷搜索:  1898  创意文化园  as  1880  1856  1838  1832  1864

usdt不用实名交易(caibao.it):Project Zero 对近几年 iOS 内核破绽行使手艺的总结

我最近希望获得一个在线参考,以简要概述近年来每种公共iOS内核行使程序的行使思绪。由于不存在此类文档,因此我决议自己确立一个。

这篇文章总结了针对iOS 10到iOS 13的内陆应用程序上下文中的原始iOS内核行使,重点是从破绽初始原语到内核读/写的高级行使流程。在本文的末端,我们将简要先容iOS内核破绽行使缓解措施(包罗硬件和软件),以及它们若何映射到破绽行使中使用的手艺。

这篇文章没有0 day破绽行使,也没有新颖的破绽行使研究或令人兴奋的恶意软件的逆向。由于我需要这些信息,并以为其他人也可能会以为有用,因此这篇文章可以被被用作参考。

0x01 术语说明

不幸的是,没有称为“平安研究人员的手艺黑客术语”的权威词典,这使得很难准确形貌我想转达的一些高级观点。为此,我决议将以下术语赋予本文特定的寄义。若是这些界说中的任何一个与你对这些术语的明白不一致,请随时提出改善的术语。

破绽行使原语:在破绽行使历程中开发的,对照通用的函数。

常见破绽行使原语的一些示例包罗:n 字节线性堆溢出,在受控地址处的整数溢出,在那边写入,随便存储器读/写,PC控制,随便函数挪用等。

特定于iOS内核行使的常见行使原语是具有对伪造的Mach端口(结构ipc_port )的发送权,该伪造的Mach端口可直接从用户空间读取和写入其字段。

破绽行使计谋:一种特定于破绽的低级方式,用于将破绽转变为有用的破绽行使原语。

例如,这是Ian Beer的iOS 11.1.2的async_wake攻击中使用的攻击计谋:

信息泄露用于发现随便Mach端口的地址。将分配端口页面,并凭据其地址从该页面中选择特定端口。所述IOSurfaceRootUserClient 破绽被触发以排除分配端口,发生一个吸收到端口的已知地址。

最后一部门是与通用/破绽无关的原语,我将其注释为特定于破绽的行使计谋的终结。

通常,行使计谋的目的是发生高度可靠的行使基元。

破绽行使手艺:一种可重用且合理的通用计谋,用于将一个破绽行使原语转换为另一个(通常更有用)的破绽行使原语。

破绽行使手艺的一个示例是面向返回的编程(ROP),它通过重用可执行代码gadget将随便PC控制转换为(险些)随便代码执行。

针对iOS内核开发的一种行使手艺是通过挪用pid_for_task()使用伪造的Mach端口读取4字节的内核内存(将对伪造的Mach端口的发送权转换为随便内核内存读取原语)。

破绽行使流:破绽行使手艺的高级方式,与破绽无关的链,用于将破绽授予的破绽行使原语转变为最终目的(在本文中,内核从内陆应用程序上下文举行读取/写入)。

0x02 自iOS 10起公然的iOS内核破绽

本节将简要概述从针对iOS 10到iOS 13的内陆上下文iOS内核破绽行使。我将形貌高级破绽行使流程,并列出用于实现该破绽的破绽行使原语和手艺。虽然我试图追踪每个原始的(即在破绽行使代码公布之前开发的)公共破绽行使,它们既可以作为源代码使用,也可以作为完整的文稿使用。

对于每种破绽行使,我都概述了破绽细节,破绽行使计谋(特定于该破绽)以及随后的破绽行使流程(通用)。破绽的哪些部门特定于该破绽与哪些部门的通用水平足以被视为总体流程的一部门之间的界线是主观的。在每种情形下,我都强调了我以为足够通用的破绽所授予的特殊行使原语。

mach_portal-iOS 10.1.1

由Google Project Zero(@ i41nbeer)的Ian Beer提供。

破绽:CVE-2016-7644是XNU的set_dp_control_port()中的竞争条件,导致Mach端口被过分释放。

行使计谋:set_dp_control_port()分配了许多Mach端口,并删除了对它们的引用,通过删除隐藏的引用来释放端口,从而使处置历程拥有吸收权以悬挂Mach端口填充内存页面。

后续行使流程:通过挪用mach_zone_force_gc()强制举行区域垃圾接纳,并使用包罗指向主机端口的指针的离线(OOL)端口数组重新分配悬空端口的页面。在一个悬挂端口之一上挪用mach_port_get_context()以公然主机端口的地址。使用此值,可以预测内核义务端口所在的页面,每个悬挂端口的上下文值设置为包罗内核义务端口的页面上每个潜在ipc_port 的地址,而且OOL端口在用户空间中被吸收回去,以向内核义务端口提供发送权限。

参考:mach_portal行使代码。

iOS破绽行使链1-iOS 10.1.1

由Google威胁剖析小组的ClémentLecigne(@ _clem1)在野外发现。由Google Project Zero 的Ian Beer和SamuelGroß(@ 5aelo)剖析。

破绽:破绽是IOKit函数AGXAllocationList2 :: initWithSharedResourceList()中IOAccelResource 指针的线性堆越界写入。

行使计谋:要溢出的缓冲区直接放置在recv_msg_elem 结构之前,这样越界写操作将使用IOAccelResource 指针笼罩uio 指针。所述IOAccelResource 指针被释放并用重新分配的 UIO 在最先结构OSDATA 数据缓冲器来治理IOSurface 。该UIO 被释放,留下一个悬空OSDATA 数据经由缓冲接见IOSurface 。

后续的行使流程:悬空的OSData 数据缓冲区通过IOSurfaceRootUserClient 实例重新分配,而且数据内容通过IOSurface 属性读取,以提供KASLR珍爱,当前义务的地址以及悬空数据缓冲区/ IOSurfaceRootUserClient 的地址。然后,释放数据缓冲区并使用IOSurfaceRootUserClient 的patch版本举行重新分配,这样,在修改的用户客户端上挪用外部方式将返回从内核的__DATA 段读取的内核义务的地址。数据缓冲区被释放并再次重新分配,以便挪用外部方式将执行OSSerializer :: serialize()gadget,导致随便读写后将内核义务端口的地址存储在当前义务的特殊端口列表中。从用户空间读取特殊端口将向内核义务端口发送权限。

参考:iOS破绽行使链1-AGXAllocationList2 :: initWithSharedResourceList堆溢出。

extra_recipe-iOS 10.2

伊恩·比尔(Ian Beer)。

破绽:CVE-2017-2370是线性堆缓冲区溢出,可通过XNU的mach_voucher_extract_attr_recipe_trap()中的非特权上下文来实现,这是由于攻击者控制的用户空间指针用作对copyin()的挪用中的长度。

行使计谋:挪用易受攻击的Mach陷阱来确立kalloc 分配,并立刻用受控数据溢出该kalloc 分配,从而损坏了后续ipc_kmsg 工具的ikm_size 字段。这导致ipc_kmsg,它是Mach端口的预分配新闻,以为它具有比其更大的容量,并将其与后续分配的前240个字节重叠。通过将Mach端口注册为用户空间线程的异常端口,然后以受控的寄存器状态使线程溃逃,可以重复且可靠地笼罩后续分配的重叠部门,而且通过吸收异常新闻,可以读取这些字节。这样就可以在损坏 ipc_kmsg 末尾提供一个受控的240字节越界读/写原语。

后续破绽行使流程:在破绽函数之后放置另一个ipc_kmsg,并对其举行读取,以确定分配的地址。接下来,将AGXCommandQueue 用户客户端重新分配到统一内存中,并读取虚拟方式表以确定KASLR。然后,将笼罩虚函数表,以使AGXCommandQueue 上的虚函数挪用将挪用OSSerializer :: serialize()gadget,从而天生2参数的随便内核函数挪用原语。挪用函数uuid_copy()给出随便内核读/写原语。

参考:iOS上的面向异常的行使,extra_recipe行使代码。

Yalu102-iOS 10.2

由Luca Todesco(@qwertyoruiopz)和Marco Grassi(@marcograss)撰写。

破绽:CVE-2017-2370(与上面相同)。

行使计谋:易受攻击的Mach陷阱被挪用以确立kalloc 分配,并立刻用受控数据溢出它,笼罩OOL端口数组的内容,并在用户空间中插入指向伪造的Mach端口的指针。吸收包罗OOL端口的新闻会发生对伪造的Mach端口的发送权,该伪造的Mach端口的内容可以直接控制。

后续行使流程:伪造的Mach端口被转换为时钟端口,而clock_sleep_trap()用于对内核映像指针举行暴力破解。然后将端口转换为伪义务端口,以通过pid_for_task()读取内存。从泄露的内核映像指针向后扫描内核内存,直到找到内核文本库为止,这会损坏KASLR。最后,构建一个伪内核义务端口。

注重:该破绽行使不适用于启用PAN的情形。

参考:Yalu102破绽行使代码。

ziVA-iOS 10.3.1

Zimperium的Adam Donenfeld(@doadam)。

破绽:在多个破绽AppleAVE2 由于外部方式分享IOSurface 与用户空间的指针和信托IOSurface 指针从用户空间读取。

行使计谋:确立一个IOSurface 工具,并挪用AppleAVE2 外部方式以泄露其地址。iofence 在指针IOSurface 使用泄露另一个外部方式挪用,打破KASLR。所述IOSurface 工具被释放,并与使用控制的数据重新分配IOSurface 属性堆喷。将泄露的指针提供给信托从用户空间提供的IOSurface 指针的AppleAVE2 外部方式,可以挟制伪造的IOSurface 上的虚函数挪用;这被视为在已知地址用受控目的工具举行的oneshot挟制虚函数挪用。

后续的行使流程:被挟制的虚函数挪用与OSSerializer :: serialize()gadget一起使用,以挪用copyin()并笼罩2个sysctl_oid 结构。sysctls被笼罩,因此读取第一个sysctl会挪用copyin()来更新第二个sysctl的函数指针和参数,而读取第二个sysctl则使用OSSerializer :: serialize()gadget来挪用带有3个参数的内核函数。这个3参数的随便内核函数挪用原语用于通过挪用copyin()/ copyout()来读写随便内存。

注重:iOS 10.3引入了task_conversion_eval()的初始形式,这是一种较弱的缓解措施,它阻止用户空间接见现实内核义务端口的权限。iOS 10.3之后的任何破绽行使都需要构建伪造的内核义务端口。

参考:Ro(o)tten apple,ziVA破绽行使代码。

async_wake-iOS 11.1.2

伊恩·比尔(Ian Beer)。

破绽:CVE-2017-13861是IOSurfaceRootUserClient :: s_set_surface_notify()中的破绽,该破绽导致在Mach端口上删除了分外的引用。CVE-2017-13865是XNU的proc_list_uptrs()中的一个破绽,该破绽通过在将内容复制到用户空间之前无法完全初始化堆内存来泄露内核指针。

行使计谋:信息泄露用于发现随便Mach端口的地址。将分配端口页面,并凭据其地址从该页面中选择特定端口,使用IOSurfaceRootUserClient 错误将端口释放,从而发生对悬挂的Mach端口的已知(部门受控)地址的吸收。

后续行使流程:释放该页面上的其他端口,并强制举行区域垃圾接纳,以便使用ipc_kmsg 的内容重新分配该页面,从而在已知地址处提供一个伪造的Mach端口,其内容受控制。重新分配将端口转换为伪义务端口,可以使用pid_for_task()读取随便内核内存。(使用mach_port_set_context()无需重新分配伪端口即可更新要读取的地址。)使用内核读取原语定位相关的内核工具,并使用伪内核义务端口再次分配伪端口。

注重:iOS 11删除了mach_zone_force_gc()函数,该函数允许用户空间提醒内核执行区域垃圾接纳,从而接纳区域图中所有可用的虚拟页面供其他区域使用。iOS 11及更高版本的破绽需要开发一种手艺来强制区域垃圾接纳。为此,至少开发了三种自力的手艺,在async_wake,v0rtex和In-the-wild iOS行使链3中获得了证实。

参考:async_wake破绽行使代码。

iOS破绽行使链2-iOS 10.3.3

由克莱门特·莱西尼(ClémentLecigne)在野外发现。由Ian Beer和SamuelGroß剖析。

破绽:CVE-2017-13861(与上面相同)。

行使计谋:两个Mach端口,端口A和端口B,作为堆喷的一部门分配。触发该破绽后,将抛弃对端口A的引用,并释放了A周围的端口,从而导致端口指针悬空。通过挪用mach_zone_force_gc()强制举行区域垃圾接纳,并使用包罗模式的OOL端口堆喷重新分配包罗端口A的页面,该模式包罗以下模式:端口A的ip_context 字段与指向端口B的指针重叠。挪用mach_port_get_context()给出端口B的地址。破绽再次通过端口B触发,从而导致在已知地址悬挂Mach端口的吸收权。

后续的行使流程:在另一个区域垃圾接纳之后,使用分段的OOL内存堆喷重新分配了悬空的端口B,以便挪用mach_port_get_context()可以识别堆喷重新分配的端口B的哪个4 MB段。该段已释放,而且端口B被重新分配了使用管道缓冲区,在已知地址提供受控的伪造Mach端口。伪端口转换为时钟端口,而clock_sleep_trap()用于强行使用KASLR。接下来将伪端口转换为伪义务端口,并使用pid_for_task()确立4字节内核读取原语。最后,将伪端口转换为伪内核义务端口。

参考资料:iOS破绽行使链2-IOSurface。

v0rtex-iOS 10.3.3

通过Siguza(@ S1guza)。

破绽:CVE-2017-13861(与上面相同)。

行使计谋:对该端口举行了堆喷,并抛弃了一个端口上的引用。页面上的其他端口被释放,留下悬挂的Mach端口的吸收权。

后续破绽行使流程:使用mach_zone_force_gc()强制举行区域垃圾接纳,并通过IOSurface 属性Spray 用OSString 缓冲区重新分配包罗悬空端口的页面。所述OSString 缓冲区包罗初始化端口的要害领域和允许的索引图案OSString 包罗端口通过挪用来确定mach_port_get_context()假端口上。释放包罗伪端口的OSString 并将其重新分配为通俗的Mach端口。挪用mach_port_request_notification()将真实Mach端口的地址放入伪端口的ip_pdrequest中字段,然后通过IOSurface 读取OSString 的内容以获取地址。再次使用mach_port_request_notification()获取伪端口自己的地址。

释放并重新分配字符串缓冲区,以便可以将mach_port_get_attributes()用作4字节的随便读取原语,而且目的地址可以通过mach_port_set_context()举行读取更新。(这类似于pid_for_task()手艺,但约束条件略有差别。)从现实Mach端口的地址最先,读取内核内存以查找相关的内核工具。使用伪造的义务端口释放并重新分配字符串缓冲区,足以将字符串缓冲区重新映射到历程的地址空间。通过映射更新伪端口,以使用iokit_user_client_trap()发生7参数的随便内核函数挪用原语和挪用内核函数天生伪造的内核义务端口。

参考:v0rtex编写,v0rtex行使代码。

CVE-2018-4150 bpf-filter-poc的行使-iOS 11.2.6

破绽剖析和POC,由Corellium的Chris Wade(@cmwdotme)提供,由littlelailo(@littlelailo)行使。

破绽:CVE-2018-4150是XNU BPF子系统中的竞争条件,由于在不重新分配响应缓冲区的情形下增添了缓冲区长度,导致线性堆缓冲区溢出。

破绽行使计谋:条件竞争被触发以错误地增添缓冲区的长度,而不重新分配缓冲区自己。发送数据包并将其存储在缓冲区中,溢出到后续的OOL端口数组中,并在用户空间中插入指向伪造的Mach端口的指针。吸收包罗OOL端口的新闻会发生对伪造的Mach端口的发送权,该伪造的Mach端口的内容可以直接控制。

后续行使流程:伪造的Mach端口被转换为时钟端口,而clock_sleep_trap()用于对内核映像指针举行暴力破解。然后将端口转换为伪义务端口,以通过pid_for_task()读取内存。从泄露的内核映像指针向后扫描内核内存,直到找到内核文本库为止,这会损坏KASLR。破绽行使的最后部门还不完整,然则在此阶段使用现有代码可以简朴,确定性地构建伪内核义务端口。

注重:该破绽行使不适用于启用PAN的情形。

参考文献:CVE-2018-4150 POC,针对CVE-2018-4150-bpf-filter-poc的不完全行使破绽行使代码。

multi_path-iOS 11.3.1

伊恩·比尔(Ian Beer)。

破绽:CVE-2018-4241是XNU的mptcp_usr_connectx()中的工具内线性堆缓冲区溢出,原因是界限检查不准确。

行使计谋:整理内核堆,以将2048字节ipc_kmsg 结构放置在与几个多路径TCP套接字关联的mptses 结构(包罗溢出的工具)下方的16 MB对齐地址上。该破绽用于使用零笼罩mptses 结构中mpte_itfinfo 指针的低3个字节,而且套接字已关闭。这将触发损坏指针的kfree(),从而在16 MB对齐界限处释放ipc_kmsg 结构。释放的ipc_kmsg 插槽已通过堆喷的管道缓冲区重新分配。再次触发该破绽以笼罩mpte_itfinfo 的低3个字节另一个具有零的mptses 结构中的指针,而且套接字被关闭,导致另一个具有相同地址的kfree()。这将释放刚分配到该插槽中的管道缓冲区,从而留下一个悬空的管道缓冲区。

后续行使流程:使用预先分配的ipc_kmsg 重新分配插槽。用户空间线程溃逃,导致新闻存储在与管道缓冲区重叠的预分配ipc_kmsg 缓冲区中;读取用户空间中的管道会发生ipc_kmsg 结构的内容,并给出悬空管道缓冲区/ ipc_kmsg 的地址。写入管道是为了更改ipc_kmsg 结构的内容,以便吸收新闻会发生对管道缓冲区内伪造的Mach端口的发送权。吸收到异常新闻,并使用pid_for_task()将管道重写以将伪端口转换为内核读取原语。找到相关的内核工具,并将伪端口转换为伪内核义务端口。

参考:multi_path破绽行使代码。

multipath_kfree-iOS 11.3.1

由JohnÅkerblom(@jaakerblom)。

破绽:CVE-2018-4241(与上面相同)。

开发计谋:内核堆预先分配的4096字节ipc_kmsg 结构四周的mptses 结构的几个TCP套接字。触发该破绽两次,以损坏两个mptses 结构中mpte_itfinfo 指针的低2个字节,从而关闭套接字会导致两个损坏的指针的kfree()。每个指针已损坏指向0x7a0 字节到ipc_kmsg 分配,发生4096字节的2个新闻。包罗部门释放的ipc_kmsg 结构之一(带有ipc_kmsg的Mach端口)通过使用mach_port_peek()来检测损坏的msgh_id 字段,找到了完整的标头,但释放了邮件内容)。找到端口后,通过堆喷预分配的ipc_kmsg 结构来重新分配孔,并在每个结构中放置一条新闻。填充孔与替换部门的ipc_kmsg 标头重叠在原始ipc_kmsg 的Mach新闻内容(部门释放)上,以便在原始端口上吸收新闻会读取替换ipc_kmsg 标头的内容。标头包罗一个指向自身的指针,该指针公然了替换的地址ipc_kmsg分配。再次触发该破绽以释放替换新闻,从而将部门释放的预分配ipc_kmsg保留在已知地址处。

后续攻击流程:通过堆喷AGXCommandQueue 用户客户端来重新分配损坏的ipc_kmsg 中的破绽。在用户空间中的Mach端口上收到一条新闻,该新闻复制了AGXCommandQueue 工具的内容,使用该vtable可以从中确定KASLR珍爱。然后,通过堆喷更多预分配的ipc_kmsg 结构,并以稍微差别的内部结构释放并重新分配已损坏的ipc_kmsg,从而对内容举行更多控制。一条新闻放置在每个刚刚堆喷的ipc_kmsg 结构中,以修改重叠的AGXCommandQueue 并挟制虚拟方式挪用。被挟制的虚拟方式使用OSSerializer :: serialize()gadget挪用copyout(),该工具用于识别哪个堆喷的AGXCommandQueue 用户客户端与损坏的ipc_kmsg中的插槽重叠。依次更新每个刚刚分配的ipc_kmsg 结构的内容,以标识哪个端口与损坏的ipc_kmsg 相对应。通过发送到预分配端口的异常新闻来更新AGXCommandQueue 工具的内容,将预分配端口和用户客户端端口一起使用以构建3参数的随便内核函数挪用原语。

参考:multipath_kfree行使代码。

empty_list-iOS 11.3.1

伊恩·比尔(Ian Beer)。

破绽:CVE-2018-4243是由于不准确的界限检查而在XNU的getvolattrlist()中部门控制的8字节堆越界写入。

行使计谋:由于重大的触发约束,此破绽被视为在kalloc.16 分配结束时对8个字节的堆举行了越界写入。内核堆被整理为kalloc.16 和ipc.ports 区域的交替块模式,进一步的整理将逆向kalloc.16 free表。释放种种kalloc.16 分配之后,重复触发该破绽,直到块末尾的kalloc.16 分配溢出,从而损坏了后续页面上第一个ipc_port 的前8个字节。通过挪用mach_port_set_attributes()释放损坏的端口,留下持有吸收权的程序。

后续行使流程:强制举行区域垃圾接纳,并使用OOL ports数组重新分配悬空端口,该数组包罗指向与ip_context 字段重叠的另一个Mach端口的指针,以便通过挪用mach_port_get_context()检索另一个端口的地址。然后使用管道缓冲区重新分配悬空的端口,并使用pid_for_task()将其转换为内核读取原语。以另一个端口的地址为起点,找到相关的内核工具。最后,将伪端口转换为伪内核义务端口。

参考:empty_list破绽行使代码。

iOS破绽行使链3-iOS 11.4

由克莱门特·莱西尼(ClémentLecigne)在野外发现,由Ian Beer和SamuelGroß剖析。

破绽:由于未能消灭释放的指针,因此从AppleVXD393UserClient :: DestroyDecoder()可以双重释放。

行使计谋:确立并释放目的56字节的分配,使悬空指针保持完整。使用IOSurface 属性Spray 使用OSData 缓冲区重新分配插槽。再次挪用易受攻击的方式以释放缓冲区,留下悬空的OSData 缓冲区。再次使用包罗单个目的Mach端口指针的OOL端口数组重新分配该插槽,并通过IOSurface 属性在用户空间中读取内容,从而天生端口的地址。再次挪用易受攻击的方式以释放OOL端口,并使用另一个OSData 重新分配插槽包罗两个指向Mach端口的指针的缓冲区。存放OOL形貌符的存放端口被损坏,抛弃了对Mach端口的两个引用。这样就使该历程具有在已知地址悬挂Mach端口的吸收权。

后续行使流程:执行区域垃圾接纳,并使用分段的OOL内存堆喷重新分配悬空的端口,以便挪用mach_port_get_context()可以标识堆喷的哪一部门重新分配了端口。释放该段,并使用管道缓冲区重新分配悬空端口,从而在已知地址处提供受控的伪造Mach端口。伪端口转换为时钟端口,而clock_sleep_trap()用于强行使用KASLR。接下来,将伪端口转换为伪义务端口,并使用pid_for_task()确立内核读取原语。最后,将伪端口转换为伪内核义务端口。

参考:iOS破绽行使链3-XPC VXD393 / D5500 IOFree。

Spice-iOS 11.4.1

Synacktiv的Luca Moro(@JohnCool__)举行破绽剖析和POC 。由Siguza,Viktor Oreshkin(@ stek29),Ben Sparkes(@iBSparkes)和littlelailo举行行使。

,

欧博亚洲APP下载ALLbet6.com

欢迎进入欧博亚洲APP下载(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。

,

破绽:“ LightSpeed”破绽(可能是CVE-2018-4344)是XNU的lio_listio()中的一种竞争状态,原因是状态治理欠妥导致UAF。

行使计谋:在一个线程的循环中挪用易受攻击的函数,以通过从kalloc.16 分配一个缓冲区并竞速两次释放该缓冲区来频频触发该破绽。另一个线程重复发送一条新闻,其中包罗从kalloc.16 分配的OOL端口数组,立刻通过IOSurface 属性将大量kalloc.16 分配包罗指向用户空间中伪造的Mach端口的指针,并吸收OOL端口。当竞争乐成时,双释放会导致OOL端口阵列被释放,而且随后的喷射可能会使用伪造的OOL端口阵列重新分配插槽。在用户空间中吸收OOL端口会给出一个获得对伪造的Mach端口的权力,该端口的内容可以直接控制。

后续破绽行使流程:第二个Mach端口在伪端口上注册为通知端口,在伪端口的ip_pdrequest 字段中公然了第二个端口的地址。使用mach_port_get_attributes()修改了伪端口,以组织内核读取原语。从公然的端口指针最先,读取内核存储器以找到相关的内核工具。使用iokit_user_client_trap()将伪端口转换为伪用户客户端端口,从而提供7参数的随便内核函数挪用原语。最后,构建一个伪内核义务端口。

注重:该破绽行使不适用于启用PAN的情形。

剖析是对文件pwn.m中的实现举行的,由于这似乎可以与该列表中的其他破绽行使实现举行最直接的对照。

参考资料:LightSpeed,iOS / macOS沙箱逃逸,Spice行使代码。

footm1ll-iOS 11.4.1

Luca Moro的破绽剖析和POC。由Tihmstar(@tihmstar)行使。

破绽:“ LightSpeed”破绽(与上面相同)。

行使计谋:在一个线程的循环中挪用易受攻击的函数,以通过从kalloc.16 分配一个缓冲区并竞速两次释放该缓冲区来频频触发该破绽。另一个线程发送牢固数目的新闻,其中包罗从kalloc.16 分配的OOL端口数组。当竞争乐成时,两次释放会导致OOL端口数组释放,从而在某些新闻中留下悬空的OOL端口数组指针。第一个线程住手触发破绽,并确立了大量IOSurface 工具。依次吸收每个新闻,并使用IOSurface 喷射大量kalloc.16 分配,其中包罗指向用户空间中伪造的Mach端口的指针属性。每次堆喷都可以使用虚伪的OOL端口阵列从悬空的OOL端口阵列重新分配插槽。乐成吸收用户空间中的OOL端口将为伪造的Mach端口提供吸收权,该伪造的Mach端口可以直接控制其内容。

后续破绽行使流程:第二个Mach端口在伪端口上注册为通知端口,在伪端口的ip_pdrequest 字段中公然了第二个端口的地址。使用pid_for_task()修改了假端口,以组织内核读取原语。从公然的端口指针最先,读取内核存储器以找到相关的内核工具。使用iokit_user_client_trap()将伪端口转换为伪用户客户端端口,从而提供7参数的随便内核函数挪用原语。最后,构建一个伪内核义务端口。

注重:该破绽行使不适用于启用PAN的情形。

参考资料:LightSpeed,一个iOS / macOS沙箱逃逸,破绽行使代码。

Chaos - iOS 12.1.2

奇虎360 Vulcan Team的Zhao Qixun Zhao(@ S0rryMybad)。

由于XNU的task_swap_mach_voucher()无法遵守MIG生存期语义,导致在ipc_voucher 工具上添加或删除了分外的引用,因此破绽CVE-2019-6225可以UAF。

行使计谋:喷射了大量ipc_voucher 工具,而且触发了两次破绽,以削减凭证上的引用计数并将其释放。页面上的其余内存将被释放,并强制举行区域垃圾接纳,将悬空的ipc_voucher 指针留在线程的**ith_voucher** 字段中。

后续行使流程:悬挂的凭证由OSString 缓冲区使用IOSurface 属性Spray 重新分配。挪用thread_get_mach_voucher()以获获得该凭证的新分配的凭证端口的发送权,这导致指向该凭证端口的指针存储在与OSString 缓冲区重叠的伪凭证中;读取OSString 属性将显示凭证端口的地址。所述OSString 重叠假凭证被释放并具有大堆喷,这两个在硬编码的地址包罗一个假的Mach端口控制的数据的分配,并更新假的重新分配iv_port指向伪造的端口的指针。再次挪用thread_get_mach_voucher()以获得对假端口的发送权,并标识哪个OSString 缓冲区包罗假Mach端口。这样,该历程就可以向**IOSurface** 属性缓冲区中**的伪造的Mach端口发送权限,该端口位于已知地址(大致等效于悬挂的Mach端口)。通过重新分配OSString 缓冲区以将伪端口转换为伪义务端口并挪用pid_for_task()来构建内核读取原语。读取随便内存。找到相关的内核工具,并将伪端口转换为伪映射端口,以将伪端口重新映射到用户空间,从而无需重新分配它。最后,伪端口被转换为伪内核义务端口。

注重:A12引入了PAC,它限制了使用某些涉及代码指针的行使手艺的能力(例如,vtable挟制)。此外,iOS 12在ipc_port_finalize()中引入了缓解措施,以防止在端口处于流动状态时释放端口(即,端口未被损坏,例如,由于历程仍拥有该端口的权力)。这改变了已往破绽行使的通用结构,即在某个历程仍保留其使用权的同时,该端口将被释放。效果,在iOS 12 破绽行使中获得假端口的权力似乎比早期破绽行使的发生晚。

参考:IPC凭证UaF远程越狱阶段2(EN)。

voucher_swap-iOS 12.1.2

由Google Project Zero的Brandon Azad(@_bazad)提供。

破绽:CVE-2019-6225(与上面相同)。

行使计谋:对内核堆举行修饰,以将ipc_port 分配块直接放在管道缓冲区块之前。喷射了大量ipc_voucher 工具,并触发该破绽以削减凭证上的引用计数并释放它。页面上的其余凭单将被释放,并强制举行区域垃圾接纳,将悬空ipc_voucher 指针留在线程的ith_voucher字段中。

后续行使流程:悬空的凭证通过OOL ports数组举行重新分配,该数组包罗指向先前分配的ipc_port 的指针,该指针与凭证的iv_refs 字段重叠。通过挪用thread_get_mach_voucher()来检索凭证端口的发送权,并通过重复挪用易受攻击的函数来更新凭证的引用计数,从而更新重叠的ipc_port 指针以指向管道缓冲区。吸收OOL端口会发生对伪造的Mach端口的发送权,该端口的内容可以直接控制。挪用mach_port_request_notification()以插入指向包罗伪造端口中另一个Mach端口的指针的数组的指针ip_requests 字段。使用pid_for_task()构建内核读取原语,并读取另一个Mach端口的地址以盘算假端口的地址。找到相关的内核工具,并构建伪造的内核义务端口。

参考文献:voucher_swap:在iOS的12 MIG环境与开发引用计数,voucher_swap攻击代码。

MachSwap-iOS 12.1.2

本·斯帕克斯(Ben Sparkes)。

破绽:CVE-2019-6225(与上面相同)。

行使计谋:喷射了大量ipc_voucher 工具,而且触发了两次破绽,以削减凭证上的引用计数并将其释放。页面上的其余凭单将被释放,并强制举行区域垃圾接纳,将悬空的ipc_voucher 指针留在线程的ith_voucher 字段中。

后续行使流程:悬空凭证由OSString 缓冲区重新分配,该缓冲区包罗使用IOSurface 属性Spray 指向用户空间中虚伪端口的虚伪凭证。挪用thread_get_mach_voucher()以获得对伪造凭证端口的发送权,从而发生对伪造Mach端口的发送权,该伪造Mach端口的内容可以直接控制。一条新闻被发送到假端口,以泄露ipc_kmsg 工具的地址。使用pid_for_task()构建内核读取原语,而且从公然的指针最先定位相关的内核工具。最终,构建了伪造的内核义务端口。

注重:该破绽行使不适用于启用PAN的情形。

参考文献:MachSwap:在iOS 12内核破绽,machswap攻击代码。

iOS破绽行使链5-iOS 12.1.2

由克莱门特·莱西尼(ClémentLecigne)在野外发现。由Ian Beer和SamuelGroß剖析。

破绽:CVE-2019-6225(与上面相同)。

行使计谋:喷射了大量ipc_voucher 工具,并触发该破绽以削减凭证上的引用计数并释放它。页面上的其余凭单将被释放,并强制举行区域垃圾接纳,将悬空的ipc_voucher指针留在线程的ith_voucher 字段中。

后续行使流程:悬空的凭证由OOL内存堆喷重新分配。分配了大量的Mach端口,然后挪用thread_get_mach_voucher()以获得针对该凭证的新分配的凭证端口的发送权,这导致指向该凭证端口的指针存储在与OOL端口数组重叠的伪凭证中。分配了更多的端口,然后吸收OOL内存喷射,公然了伪造凭证的凭证端口地址。悬挂的凭证再次与另一个OOL内存喷射重新分配,该更新更新了凭证的iv_port指向下一页的指针。Mach端口被损坏,区域垃圾被强行接纳,伪造的凭证只剩下一个指向悬挂端口的指针。悬挂的端口通过管道缓冲区重新分配。最后,挪用thread_get_mach_voucher(),以将伪造的Mach端口发送到已知地址的发送权,该地址的内容可以直接控制。伪端口转换为伪义务端口,并使用pid_for_task()确立内核读取原语。找到相关的内核工具,并将伪端口转换为伪内核义务端口。

参考:iOS破绽行使链5-task_swap_mach_voucher。

iOS破绽行使链4-iOS 12.1.3

由克莱门特·莱西尼(ClémentLecigne)在野外发现。由Ian Beer和SamuelGroß剖析,还由一位匿名研究人员剖析。

破绽CVE-2019-7287是由于未选中memcpy()导致IOKit函数ProvInfoIOKitUserClient :: ucEncryptSUInfo()中的线性堆缓冲区溢出。

行使计谋:整理内核堆,以在OOL端口数组之前的kalloc.4096 中放置,在通过IOSurface 属性接见的OSData 缓冲区之前的kalloc.6144中放置。该破绽被触发与从分配源kalloc.4096 并从所分配的目的地kalloc.6144 ,使目的Mach端口的地址被复制到OSDATA 缓冲器。然后OSDATA的缓冲器被读出,公然的目的端口的地址。再次整理堆以在OOL内存缓冲区之前的kalloc.4096 和kalloc.6144中放置在OOL端口数组之前。再次触发该破绽,将指向目的端口的指针插入OOL端口数组。释放目的端口,并强制举行区域垃圾接纳,在OOL ports数组中留下一个悬空的端口指针。悬空的端口通过管道缓冲区重新分配,而且OOL端口被吸收,从而为已知地址的伪Mach端口提供了吸收权,该伪造的Mach端口的内容可以直接控制。

后续行使流程:虚伪端口被转换为虚伪时钟端口,而clock_sleep_trap()用于强行使用KASLR。伪端口转换为伪义务端口,并使用pid_for_task()确立内核读取原语。找到相关的内核工具,并将伪端口转换为伪内核义务端口。

参考:iOS破绽行使链4-cfprefsd ProvInfoIOKit,关于iOS 12.1.4的平安性内容。

攻击iPhone XS Max-iOS 12.1.4

王铁磊(@wangtielei)和徐昊(@windknown)。

破绽:该破绽是XNU UNIX域套接字绑定实现中的竞争条件,这是由于暂且解锁反模式导致了“UaF”。

行使计谋:喷射套接字,并触发破绽,以使指针指向vnode 结构中悬空的套接字指针。关闭套接字,强制举行区域垃圾接纳,并通过OSData 堆喷(可能是IOSurface 属性堆喷)用受控数据重新分配套接字。伪套接字被组织为具有0的引用计数。触发使用后释放来挪用伪套接字上的socket_unlock(),这将导致伪套接字/ OSData 缓冲区使用kfree()释放。这样就留下了悬挂的OSData缓冲区,可以使用未指定的方式举行接见。

后续行使流程:悬空的OSData 缓冲区通过OOL ports数组举行重新分配,而且OSData 缓冲区被释放,剩下悬空的OOL ports数组。喷射内核内存以将伪造的Mach端口放置在硬编码地址上(或使用了信息泄露),而且OOL端口阵列与另一个OSData 缓冲区重新分配,将指向伪造的Mach端口的指针插入到OOL端口阵列中。吸收OOL端口,从而在已知地址向伪Mach端口发送或吸收权限,伪端口通过未指定的方式转换为伪内核义务端口。

注重:此破绽的唯一参考是BlackHat演示,因此上面注释存在不确定性。

作者开发了此破绽行使的两个版本:一个用于非PAC装备,一个用于支持PAC的装备。此处先容的破绽行使是针对启用PAC的装备的。non-PAC破绽行使现实上更简朴(挟制socket_lock()使用的函数指针)。

参考:攻击iPhone XS Max。

SockPuppet-iOS 12.2和iOS 12.4

由Ned Williamson(@nedwilliamson)与Google Project Zero互助。

该破绽:CVE-2019-8605是一个由于XNU的in6_pcbdetach()未能消灭释放指针的UaF破绽。

行使计谋:在破绽之上组织了随便读取,随便的kfree()和随便的Mach端口地址公然原语。

随便读取原语:多次触发该破绽以确立许多与套接字关联的ip6_pktopts 悬空结构。悬空的ip6_pktopts 通过IOSurface 属性通过OSData 缓冲区spray 重新分配,使得ip6po_minmtu 设置为已知值,而ip6po_pktinfo 设置为要读取的地址。所述ip6po_minmtu 字段经由检查的getsockopt() ,以及若是准确的话,的getsockopt(IPV6_PKTINFO)被挪用来读取20个字节的数据的地址所指向的ip6po_pktinfo 。

随便kfree()原语:破绽被多次触发以确立许多与套接字关联的ip6_pktopts 悬空结构。悬空的ip6_pktopts 通过IOSurface 属性使用OSData 缓冲区Spray 重新分配,使得ip6po_minmtu 设置为已知值,而ip6po_pktinfo 设置为可用地址。所述ip6po_minmtu 字段经由检查的getsockopt() ,以及若是准确的话,setsockopt的(IPV6_PKTINFO)被挪用来挪用kfree_addr()在ip6po_pktinfo 指针。

随便Mach端口地址公然原语:破绽被多次触发以确立许多与套接字关联的ip6_pktopts 悬空结构。悬空的ip6_pktopts 使用包罗指向目的端口的指针的OOL端口数组spray重新分配。的ip6po_minmtu 和ip6po_prefer_tempaddr 字段经由读取的getsockopt(),公然目的端口指针的值。使用随便读取原语检查端口是否为预期类型。

后续行使流程:Mach端口地址公然原语用于公然当前义务的地址。确立了两个管道,并使用内核读取原语找到了内核中管道缓冲区的地址。找到了相关的内核工具,并在管道缓冲区之一中组织了伪内核义务端口。随便kfree()原语用于释放另一个管道的管道缓冲区,而且通过堆喷OOL端口数组来重新分配管道缓冲区。然后写入管道,以将指向伪内核义务端口的指针插入OOL端口数组,然后吸收OOL端口,从而天生伪内核义务端口。

注重:与该列表中的大多数其他行使线性结构的破绽行使差别,SockPuppet是按条理结构举行构建的,并始终基于相同的原语。这种怪异的结构可能是由于潜在破绽的壮大函数和稳定性所致:该错误直接提供了随便读取和随便免费的原语,而且在实践中,这两个原语都是100%平安可靠的,由于可以检查重新分配是乐成的。然则,这种结构意味着在特定于破绽的行使与通用行使之间的高级行使流程中没有明确的时间界限。相反,该界限出现在破绽行使代码中的观点层之间。

SockPuppet错误已在iOS 12.3中修复,但在iOS 12.4中已重新引入。

参考:SockPuppet:适用于iOS 12.4的内核破绽行使,SockPuppet行使代码。

oob_timestamp-iOS 13.3

布兰登·阿扎德(Brandon Azad)。

破绽:CVE-2020-3837是由于不准确的界限检查而导致在IOKit的IOAccelCommandQueue2 :: processSegmentKernelCommand()中对多达8个字节的时间戳数据举行线性堆越界写入。

行使计谋:整理内核映射以部署两个96 MB的共享内存区域,一个8页的ipc_kmsg ,一个8页的OOL端口阵列和80 MB的OSData 缓冲区(通过IOSurface 属性堆喷)。凭据当前时间盘算要溢出的字节数,并触发溢出以损坏ipc_kmsg 的ikm_size 字段,这样ipc_kmsg 的巨细现在在16页至80 MB之间。包罗ipc_kmsg 的端口被销毁,释放了损坏的ipc_kmsg ,OOL端口数组以及一些后续的OSData 缓冲区。更多OSData通过IOSurface 喷射缓冲区,以重新分配OOL端口阵列,该阵列包罗一个指向伪端口的指针,该指针位于可能与96 MB共享内存区域之一重叠的硬编码地址上。吸收OOL端口,从而对已知地址的伪Mach端口发生吸收权,该地址的内容可以直接控制。

后续行使流程:使用pid_for_task()组织内核内存读取原语,找到相关的内核工具,并构建伪造的内核义务端口。

注重:iOS 13引入了zone_require,这是一个缓解措施,可在使用某些工具之前检查是否从预期的zalloc 区域中分配了某些工具。当工具在zalloc_map 之外分配时,实现中的疏忽导致了绕过。

参考:oob_timestamp行使代码。

0x03 iOS内核行使缓解措施

接下来,我们将先容一些当前的iOS内核行使缓解措施。此列表并不详尽,但简要总结了行使开发人员可能会在iOS 13上遇到的一些缓解措施。

Kernel Stack Canaries - iOS 6

iOS 6引入了内核客栈Canaries(或客栈Cookie),以防止内核中的客栈缓冲区溢出。列表中的破绽均不受客栈金丝雀的影响,由于它们不针对客栈缓冲区溢出破绽。

Kernel ASLR-iOS 6

内核地址空间结构随机化(内核ASLR或KASLR)是一种缓解措施,可在内核地址空间中将内核缓存映像的基地址随机化。在实行内核ASLR之前,内核缓存映像中的内核函数和工具的地址始终位于牢固地址。

绕过KASLR是所有现代iOS内核行使的尺度步骤。

Kernel Heap ASLR-iOS 6

从iOS 6最先,种种内核堆区域的基址已被随机化,这旨在减轻行使硬编码地址确定工具分配位置的破绽。

解决内核堆随机化问题是现代iOS内核行使的尺度步骤。通常,这涉及堆堆喷,纵然没有确切的地址,也要诱导内核分配大量数据以影响堆的形状。同样,可以行使许多破绽来发生信息泄露,从而泄露堆上相关内核工具的地址。

W ^ X / DEP-iOS 6

iOS 6还通过确保将内核页面映射为可写或可执行文件,而不是两者(通常称为“写或执行”或“ W ^ X”)来引入大量内核地址空间。这意味着页表不再将内核代码页映射为可写,而且内核堆和客栈也不再映射为可执行文件。(确保非代码数据未映射为可执行文件通常被称为数据执行珍爱或DEP。)

现代的公共iOS破绽行使程序并没有实验绕过W ^ X(例如,通过修改页表和注入shellcode);相反,通过修改内核数据结构并执行代码重用攻击来实现行使。这主要是由于存在一种称为KTRR的更壮大的,硬件强制的W ^ X缓解。

PXN-iOS 7

苹果的A7处置器是iPhone中的第一个64位ARMv8-A处置器。以前,iOS 6将内核和用户地址空间离开,因此在正常的内核执行时代无法接见用户代码和数据页。随着转向64位,地址空间不再离开。因此,在页表项中设置了“从不执行特权(PXN)”位,以确保内核无法执行驻留在用户空间页中的shellcode。

与W ^ X相似,由于对KTRR的更强珍爱,PXN作为防止跳转到用户空间shellcode的珍爱。

PAN-iOS 10

永不特权接见(PAN)是一项ARMv8.1-A平安函数,可防止内核接见用户空间也可以接见的虚拟地址。这用于防止内核作废攻击者提供的指向用户空间中数据结构的指针。它类似于某些Intel处置器上的Supervisor模式接见阻止(SMAP)函数。

只管以前没有绕过 PAN ,但现代的公共iOS内核破绽通常会通过将数据喷入内核然后学习数据地址来解决PAN问题。只管最可靠的手艺涉及公然插入内核的数据的地址,然则存在一些通常可以解决PAN的手艺,例如堆喷足够的数据以压倒内核映射的随机性,并强制将牢固的硬编码地址分配给受控数据。 还存在其他用于在用户空间和内核之间确立共享内存映射的原语,这些原语也可用于解决PAN。

KTRR-iOS 10

KTRR(可能是内核文本只读区域,是Kernel Integrity Protection的一部门)是在Apple A10处置器(ARMv8.1-A)上引入的自界说硬件平安缓解措施。它是WMU珍爱的一种壮大形式,由MMU和内存控制器在延续的单个内存范围内实行,笼罩内核高速缓存映像的只读部门以及一些敏感数据结构(如顶级页表和信托高速缓存) 。苹果公司也将其称为内核完整性珍爱(KIP)v1。

只管之前两次公然绕过KTRR ,但现代的公共iOS内核破绽通常通过不操作受KTRR珍爱的内存来绕过KTRR。

APRR-iOS 11

APRR(可能代表接见珍爱重新路由或接见权限限制寄存器)是Apple A11和更高版本的CPU上的自界说硬件函数,可通过特殊寄存器间接接见虚拟内存接见权限(通常在页面的页面表条目中指定),从而允许接见可以按原子和按焦点更改大页面组的权限。它通过将通常直接指定接见权限的PTE中的位转换为包罗真实接见权限的特殊寄存器的索引来事情。更改寄存器值会在具有相同接见权限索引的所有页面上交流珍爱。APRR有点类似于较新的Intel处置器上可用的“内存珍爱密钥”函数。

APRR自己不提供任何平安界限,然则可以在一个地址空间内支解特权级别,PPL大量使用它在iOS内核中确立平安界限。

PPL-iOS 12

PPL(页面珍爱层)是基于APRR并依赖于KTRR的软件层,旨在在内核读/写/执行与直接页表接见之间确立平安界限。PPL的主要目的是防止攻击者修改已举行代码署名的页面(例如,使用内核读/写来笼罩历程的可执行代码)。这一定意味着PPL还必须保持对页表的完全控制,并防止攻击者映射敏感的物理地址,包罗页表,页表元数据和IOMMU寄存器。

停止2020年5月,尚未公然绕过PPL。也就是说,到目前为止,现代iOS内核破绽并未受到PPL的影响。

PAC-iOS 12

指针验证码(PAC)是一种ARMv8.3-A平安函数,它通过将指针值的加密署名存储在指针的高位来减轻指针窜改。Apple随A12一起推出了PAC,并显着增强了实现(与ARM尺度相比),以抵御使用内核读/写的攻击者,只管在大多数情形下它在函数上无法区分。苹果的内核使用PAC来实现控制流完整性(CFI),从而在内核读/写和内核代码执行之间设置了平安界限。

只管众多公共旁路了iOS内核的基础PAC-CFI的,PAC内核仍然是一种有用的缓解破绽:它已严重制约了许多开发中的破绽缓和解了行使手艺。例如,已往的攻击行使内核执行原语来构建内核读/写原语(例如,参见ziVA)。若是不先绕过PAC,就无法再在A12上使用。此外,IOKit中PAC珍爱的指针的普遍使用使将许多错误转化为有用的原语变得异常难题。考虑到IOKit中严重的平安问题的悠久历史,这是一个伟大的胜利。

zone_require-iOS 13

zone_require是iOS 13中引入的一种软件缓解措施,可在使用前添加检查,以确保从预期的zalloc 区域分配了某些指针。iOS内核缓存中最常见的zone_require检查是Mach端口。例如,每次ipc_port 锁准时,都市挪用zone_require()函数以检查包罗Mach端口的分配是否驻留在ipc.ports 区域中(例如,不包罗通过kalloc()分配的OSData 缓冲区)。

由于伪造的端口是现代手艺的组成部门,因此zone_require对其具有重大影响。像CVE-2017-13861(async_wake)破绽上参考ipc_port 不再提供确立一个假的端口的直接路径。虽然zone_require已被公然绕过,但该手艺依然有用。

 https://bugs.chromium.org/p/project-zero/issues/detail?id=1986#c5
本文翻译自:https://googleprojectzero.blogspot.com/2020/06/a-survey-of-recent-ios-kernel-exploits.html?m=1如若转载,请注明原文地址:
发表评论
sunbet声明:该文看法仅代表作者自己,与本平台无关。请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片

您可能还会对下面的文章感兴趣: