皇冠体育寻求亚洲战略合作伙伴,皇冠代理招募中,皇冠平台开放会员注册、充值、提现、电脑版下载、APP下载。

首页科技正文

usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解

admin2020-12-2235安全技术二进制安全

本文原文来自From zero to tfp0 - Part 2: A Walkthrough of the voucher_swap exploit
在本文中将深入研究voucher_swap破绽以及获取内核义务端口的所有步骤。
该破绽的发现和POC都归功于@_bazad。
(@S0rryMybad也发现了这个破绽并用在天府杯上:https://blogs.360.cn/post/IPC%20Voucher%20UaF%20Remote%20Jailbreak%20Stage%202.html)

引用计数

本文中的破绽是由于MIG天生的代码的引用计数问题造成的。什么是引用计数?引用计数是一种简朴而有用的内存管理方式。建立或复制工具会将其引用计数加1,而销毁或笼罩工具会将其引用计数减1。若是工具的引用计数到达零,则将释放该工具。在内存有限的系统中,引用计数比垃圾接纳(它是循环发生的,可能会花费时间)更有用,由于可以在工具的引用计数为零时立刻释放工具,从而提高了系统的整体响应能力。
工具结构体中的成员可以示意该工具的引用计数。例如,Mach端口(ipc_port_t)中io_references成员示意其引用计数,ip_references和ip_release用于增添和削减端口上的引用计数。简朴搜索ip_reference将找到此函数用于操作端口的引用计数的许多示例。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第1张
voucher也是一样的,其中iv_refs成员示意引用计数。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第2张
iv_refs的类型为os_refcnt_t,它是32位整数,因此其局限为0-0xffffffff(8个f)吗?实在并不是。在libkern/os/refcnt.c中,最大值界说为0x0fffffff(7个f)。这是一种新的防止整数溢出的缓解措施。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第3张
如下所示,接见超出此局限的任何值都市触发内核panic。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第4张
voucher的ipc_voucher_reference和ipc_voucher_release函数仅检查voucher是否不为NULL,然后挪用iv_reference和iv_release,他们划分挪用os_ref_retain和os_ref_release。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第5张
BUILD/obj/EXPORT_HDRS/libkern/os/refcnt.h中可以找到更多细节。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第6张
因此,可能会泛起两种破绽:一种是以某种方式增添引用计数,从而导致溢出。如前所述,由于存在上限,这现实上是无法行使的。然则仍然可以将引用计数增添到0x0fffffff(7个f),稍后我们将使用此手艺。另一种是将工具的引用计数设置为0,然则仍然有一个指向它的指针。由于引用计数变为0,工具将被释放,因此指向该工具的指针变成了悬空指针。

破绽

让我们看一下该破绽。查看xnu-4903.221.2/osfmk/kern/task.c中的task_swap_mach_voucher函数。这是一个简朴的函数,它应该将新的voucher和旧的voucher交流。然则它只是用new_voucher替换了old_voucher。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第7张
凭据注释,task_swap_mach_voucher函数是一个占位符。可在xnu-4903.221.2/osfmk/mach/task.defs中找到它。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第8张
这证实它现实上是Mach API,由于MIG def文件正在为Mach接口天生代码。/BUILD/obj/RELEASE_X86_64/osfmk/mach/task.h中可以找到此函数的Mach新闻花样。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第9张
/BUILD/obj/RELEASE_X86_64/osfmk/RELEASE/mach/task_server.c中可以看到对请求执行的检查。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第10张
下面是现实的实现。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第11张
简化一下。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第12张
convert_port_to_voucher函数通过挪用ipc_voucher_reference函数将引用计数增添1。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第13张
convert_voucher_to_port函数通过挪用ipc_voucher_release函数将引用计数削减1。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第14张
在task_swap_mach_voucher例程中,通过挪用ipc_voucher_release函数(第4844行)将新voucher的引用计数减1。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第15张
此例程中引用计数的转变如下。
第4839行: new_voucher的引用计数+1
第4841行: old_voucher的引用计数+1
第4843行: task_swap_mach_voucher挪用,old_voucher = new_voucher
第4844行: new_voucher的引用计数-1
第4857行: new_voucher的引用计数-1(由于old_voucher现在是new_voucher)
你可能已经看出问题了。可以将new_voucher的引用计数削减为0,从而释放该工具。而且old_voucher的引用计数可以增添许多。若是存储指向new_voucher的指针,然后使用破绽将new_voucher的引用计数削减为0,这样就有可能获得指向new_voucher的悬空指针。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第16张

关于voucher

在继续之前,最好先查看ipc_voucher结构体并领会其中的成员。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第17张
第一件事是确定要在哪个工具中存储被释放的voucher的指针。最好的方式是在内核源代码中搜索ipc_voucher_t,并寻找易于获取和设置该指针的API。显著的地方之一是osfmk/kern/thread.h中的thread工具,该工具存储名为ith_voucher的voucher的引用。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第18张
可以使用thread_get_mach_voucher和thread_set_mach_voucher函数从用户态读取和写入voucher引用。查看MIG为该函数天生的代码。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第19张
一旦获得了指向已释放voucher工具的悬空指针,便可以使用其他工具占用已释放的voucher工具。然则这并不简朴。voucher通常位于自己的ipc voucher zone中,如osfmk/ipc/ipc_voucher.c所示,其中zinit为voucher分配了一个新zone。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第20张
因此,被释放的voucher的内存将被放置在zone的freelist中,并在建立新voucher时分配给新voucher。为了用其他工具占用,唯一可行的方式是触发zone垃圾网络,它会将被释放的voucher的内存(最小巨细为1页)移到zone map中,然后这些内存就可以重新分配给其他工具。可以通过分配大量voucher并释放它们来做到这一点。
让我们再次仔细查看MIG为thread_get_mach_voucher天生的代码。假设我们确适用其他工具占用了已释放的voucher工具,则挪用thread_get_mach_voucher应该乐成而内核不会panic。在第2688行的thread_get_mach_voucher函数挪用ipc_voucher_reference(voucher),这意味着该voucher应该具有有用的iv_refs成员。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第21张
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第22张
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第23张
在第2695行的convert_voucher_to_port函数如下所示。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第24张
在第503行首先检查voucher是否具有准确的引用计数。然后在第507行检查voucher端口的有用性。若是无效,则会分配一个新的voucher端口。这很棒,由于在分配伪造的voucher占用已释放的voucher时,若是以某种方式将iv_port指针设置为NULL,那么现实上还可以将新分配的voucher端口(IKOT_VOUCHER)返回到用户态(ith_voucher->iv_port)。这将使我们能够进一步操作voucher。

通过OOL端口描述符举行堆风水

正如在第1部门中简要讨论的那样,庞大的Mach新闻具有一个描述符成员,该成员有四种类型。

  • MACH_MSG_PORT_DESCRIPTOR:在新闻中发送一个端口
  • MACH_MSG_OOL_DESCRIPTOR:在新闻中发送OOL数据
  • MACH_MSG_OOL_PORTS_DESCRIPTOR:在新闻中发送OOL端口数组
  • MACH_MSG_OOL_VOLATILE_DESCRIPTOR:在新闻中发送易失性数据

当通过mach_msg发送Mach新闻时依次挪用mach_msg_send->ipc_kmsg_copyin->ipc_kmsg_copyin_body,在ipc_kmsg_copyin_body函数中对于MACH_MSG_OOL_PORTS_DESCRIPTOR的情形会挪用ipc_kmsg_copyin_ool_ports_descriptor函数。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第25张
第2879行挪用kalloc在kalloc zone中分配内存。第2902行将获得的内存转换为objects工具,该工具是端口指针的数组。因此使用OOL端口描述符发送大量Mach新闻,可以使用有用指针或0xFFFFFFFFFFFFFFFFFF(MACH_PORT_DEAD)或0x0000000000000000(MACH_PORT_NULL)填充kalloc zone。

管道缓冲区

管道是xnu中另一个用于IPC的系统挪用。它建立一个分配一对文件描述符并允许单向数据流的管道。数据流经的缓冲区称为管道缓冲区。可以从缓冲区的读取端读取写入缓冲区的写入端的数据,然则并不能反过来。基本上你可以在统一地址空间中举行读写。另一个主要的事情是它占用内核虚拟地址空间,因此是在堆中分配内存的有用原语。默认情形管道缓冲区的巨细设置为最大16384字节,所有管道缓冲区的巨细设置为最大16MB。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第26张
若是数据已被写入管道缓冲区而且管道缓冲区已满,则以为该管道缓冲区已壅闭。要释放该管道缓冲区必须从中读取数据。可以通过分配许多管道缓冲区并将数据写入其中来行使管道缓冲区举行喷射。可以建立的管道总数是16MB除以16384字节,即1024。
管道缓冲区的优势在于,若是能够获得指向其中一个管道缓冲区的指针并读取其值,则基本上可以识别出是这1024个管道缓冲区中的哪个,然后就可以在这个特定的管道缓冲区中重新分配数据。
有了足够的靠山知识,让我们详细先容一下EXP吧。

EXP

若是还没有下载voucher_swap EXP代码的话可以在这里下载以便阅读接下来的内容。

Step 1:为voucher建立一个单独的线程

建立一个单独的线程,我们将在其中存储指向voucher的指针。该线程有一个ith_voucher成员,可以在其中保留对voucher的引用。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第27张

Step 2:建立喷射管道缓冲区用的管道

建立喷射管道缓冲区用的管道。前面提过,可建立的管道总数为1024。之后我们会看到其中一个管道对应的管道缓冲区将与fake port重叠。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第28张

Step 3:喷射端口

我们需要喷射许多端口。它们将占用现有的朴陋,并迫使内核从zone map中分配新块。在此之后喷射管道缓冲区时,我们将假定它们位于端口的后面。凭据频频试验,将filler_port_count设为8000。base port是使用create_ports建立的最后一个端口。记着这一点,由于将在第8步中用到。对于前2000个端口还增添了行列限制,该限制是可以立刻发送到端口的最大新闻数。这样做的原因是我们将使用OOL端口描述符向这些端口发送新闻占用已释放的voucher,因此能够向这些端口发送更多的新闻将有助于喷射。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第29张

Step 4:喷射管道缓冲区

接下来喷射管道缓冲区,希望它们刚好在端口后面。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第30张
将ipc_port写入管道缓冲区,将其12位的IKOT_TYPE设置为管道索引。具体步骤如下。
回调函数update挪用iterate_ipc_ports。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第31张
iterate_ipc_ports给回调函数callback通报端口的偏移量。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第32张
在回调函数callback中使用端口的偏移量找到端口设置响应的成员(可以在Step 4第一张图中看到)。

Step 5:使用voucher喷射堆

接下来用voucher喷射堆并选择一个最终将被释放的voucher(uaf_voucher_port)。如前一篇文章所述,内存是从zone map中以块为单元获取的。对于特定的版本,一个块的巨细是牢固的(iPhone11,8 16C50的ipc_voucher是0x4000)。由于voucher的巨细也是牢固的(0x50),因此块中的voucher的数目也是牢固的(0x4000/0x50=80)。我们将分配分外的块,在这些块中存储uaf_voucher_port。前300个voucher基本上可以填补内存中的朴陋。然后将voucher喷射入约16个块,把uaf_voucher_port放到第7块-第10块,前后各有6个过渡的块。之后我们会看到这些块被OOL端口指针笼罩。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第33张

Step 6:继续喷射

接下来使用之前建立的端口喷射更多的内存。以后可以释放它以触发垃圾接纳。我们已经建立了填充端口,并在前2000个端口上增添了行列限制。这时将前500个端口再次用于喷射。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第34张

Step 7:存储指向voucher的指针但释放引用

usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第35张
由voucher_release函数释放引用。现实上EXP建立了两个类似的函数,用于释放引用(voucher_release)和增添引用(voucher_reference),它们都是对voucher_tweak_references的包装,后者是对task_swap_mach_voucher的包装。破绽在于task_swap_mach_voucher,该函数的参数是当前义务,新voucher(引用将被释放)和旧voucher(引用将被增添)。因此若是要释放一个voucher的引用,只需将其作为参数通报给新voucher,而且可以将旧voucher设置为MACH_PORT_NULL。反之若是要增添一个voucher的引用,只需将其作为参数通报给旧voucher,而且可以将新voucher设置为MACH_PORT_NULL。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第36张

步骤8:建立将笼罩释放的voucher的OOL端口指针

现在需要建立将笼罩释放的voucher的OOL端口指针。EXP选择kalloc.32768 zone,由于BLOCK_SIZE(ipc_voucher)=0x4000,因此将更容易展望voucher的偏移量。端口指针的数目是凭据zone巨细除以uint64_t的巨细(即端口指针的巨细)获得的。然后,挪用calloc分配具有端口指针的数组,每个端口指针的巨细为mach_port_t,初始为0。iterate_ipc_vouchers_via_mach_ports函数用于遍历端口指针(该函数把它们当成voucher),并使用回调函数给出voucher的偏移,然后将voucher的iv_refs指向base port。之以是使用ool_ports[voucher_start+1],是由于iv_refs位于voucher的起始位置+0x8。还通过calloc将iv_port设置为MACH_PORT_NULL,以便以后挪用thread_get_mach_voucher时获得一个新的voucher端口。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第37张

步骤9:释放第一次GC喷射

usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第38张

步骤10:释放先前建立的voucher,从而留下一个悬空的指针

usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第39张

步骤11:用OOL端口占用释放的voucher

第6步在前2000个端口上增添了行列限制而且将前500个端口再次用于喷射。现在对其它端口举行喷射,直到总喷射量到达内存容量的17%。ool_holding_ports指针从索引500(gc_port_count)最先,由于已经使用了500个。同时也使分配的内存巨细为32768以便分配在kalloc.32768 zone中,这是通过保留每个新闻的端口指针的数目来完成的(ool_port_count=ool_port_spray_kalloc_zone/sizeof(uint64_t),其中ool_port_spray_kalloc_zone=32768),顺遂的话就能够占用释放的voucher。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第40张
ool_ports_spray_size_with_gc在每2MB(gc_step)喷射之间添加usleep(),以留出时间举行zone垃圾网络。
这些端口中的每一个都使用带有OOL端口描述符的Mach新闻举行喷射。这将分配内核内存,并用端口指针填充它们。ool_ports_spray_port中的以下代码用于分配参数和发送新闻。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第41张

步骤12:挪用thread_get_mach_voucher以获取已释放voucher的voucher端口

若是base port的地址足够小,内核会以为引用计数仍然有用,挪用thread_get_mach_voucher不会导致内核panic。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第42张
现在内存结构如下图所示。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第43张

,

环球UG_ALLbet6.com

欢迎进入环球UG官网(UG环球):www.ugbet.us,环球UG官方网站:www.ugbet.net开放环球UG网址访问、环球UG会员注册、环球UG代理申请、环球UG电脑客户端、环球UG手机版下载等业务。

,

步骤13:更改iv_refs以指向管道缓冲区

可以使用相同的破绽(这次是增添引用)修改iv_refs值。iv_refs现在是指向base port的。由于喷射了约莫16MB的管道缓冲区,将其增添4MB(base_port_to_fake_port_offset)之后应该指向管道缓冲区中的某个地方。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第44张

步骤14:找到uaf_voucher_port

吸收先前使用OOL端口描述符发送的新闻。我们遍历新闻中的所有描述符,然后将它们通报到将起始端口地址和端口总数作为参数的处置程序。然后使用iterate_ipc_vouchers_via_mach_ports遍历所有这些端口指针,通过将所有端口指针的巨细除以voucher巨细来给出所有可能的voucher地址。遍历端口指针时检查ool_ports[voucher_start+7] (即iv_port,iv_port在voucher结构体中的偏移为56)是否是一个有用的端口。由于只在uaf_voucher_port上挪用了thread_get_mach_voucher,以是它的iv_port指向新分配的voucher端口。这样就可以找到uaf_voucher_port。将ool_ports[voucher_start+1] (即iv_refs,iv_refs在voucher结构体中的偏移为8)指向fake port。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第45张

步骤15:查找与fake port重叠的管道缓冲区

接下来需要查找与fake port重叠的管道缓冲区。使用mach_port_kobject获得fake port的IKOT_TYPE,这个值应该是管道的索引。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第46张

步骤16:清算未使用的内存

usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第47张

步骤17:设置原语以查找base port的地址

现在的义务是建立这个fake port,以便可以使用pid_for_task()手艺读取4个字节的内核内存。本文的第1部门中讨论了这种手艺。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第48张
将mach api挪用mach_port_request_notification()发送到fake port,以添加一个请求:若是该fake port变为MACH_PORT_DEAD则将通知base port。这将导致fake port的ip_requests指向包罗指向base port地址的指针的数组。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第49张

步骤18:查找base port的地址

遍历整个缓冲区,查看每个可能的端口的ip_requests,若是不为0,就说明找到了fake port。保留fake port在管道缓冲区中的偏移。然后将数据写入管道以便稍后可以读取。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第50张

步骤19:查找base port的地址

可以找到base port指针的地址,由于它位于ip_requests牢固偏移处。接下来需要从base port指针中读取base port的地址。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第51张
stage0_read是一个异常利便的函数,能够一次读取32位的内核内存。基本上步骤如下。
1.在管道中建立一个fake port,设置所有必须的属性,将IKOT设置为IKOT_NONE
2.凭据要读取的地址设置伪造的proc的地址(即bsd_info),在stage0_send_fake_task_message建立fake task并通过Mach新闻将其发送到fake port
3.读取管道,从fake port的ip_messages.imq_message获得fake task的地址
4.重写fake port,将IKOT设置为IKOT_TASK,kobject设置为fake task的地址
5.挪用pid_for_task读取内核内存
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第52张
(这里参考TyphoonCon上的PPT:)
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第53张

步骤20:盘算fake port的地址

知道了base port地址和从base port到fake port的偏移量(在步骤3中已界说为base_port_to_fake_port_offset),因此可以盘算出fake port地址。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第54张

步骤21:盘算自己的义务端口的地址

现在建立一个更好的读取原语并将其称为阶段1。下一步是盘算自己的义务端口的地址。stage1_find_port_address函数将输入作为义务,并使用阶段1的读取原语获取义务端口的地址。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第55张
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第56张

步骤22:获取主机端口的地址

为了实现完整的内核读写,需要找到vm_map和ipc_space_kernel。首先获取主机端口地址。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第57张

步骤23:从主机端口的ip_receiver获取ipc_space_kernel

第1部门中讲过ipc_port结构体具有一个指向ipc_space的receiver成员。可以通过读取主机端口ip_receiver(ip_receiver即receiver)成员来读取ipc_space_kernel。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第58张

步骤24:获取内核义务端口的地址

在堆中内核义务端口靠近主机端口,因此可以迭代该块找到内核义务端口。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第59张
以下函数检查端口是否为内核义务端口。首先查看是否为IKOT_TASK类型。然后读取kobject指向的义务,在该义务中查找bsd_info以查找其指向的proc结构体,然后读取pid值。若是为0,则示意它是内核义务端口。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第60张

步骤25:获取vm_map的地址

现在已经找到了内核义务端口,可以读取vm_map,由于它处于牢固偏移处。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第61张

步骤26:建立伪造的内核义务端口

现在可以建立一个位于管道缓冲区内的伪造的内核义务端口。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第62张
伪造的内核义务端口的原则是伪造的义务的map应指向vm_map,而receiver应指向ipc_space_kernel。可以通过以下两行代码实现。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第63张

步骤27:建立伪造的内核义务端口

现在有了一个功效齐全的内核义务端口,而且可以挪用Mach API来读写内存,是时刻构建一个更稳固的内核义务端口了。这次通过mach_vm_allocate分配内存,甚至在管道缓冲区之外也可以建立内核义务端口。
usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第64张

步骤28:清算不需要的资源

usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第65张

步骤29:清算更多不必要的资源,获得稳固的tfp0

usdt第三方支付(caibao.it):从0到tfp0第二部门:voucher_swap EXP详解 安全技术 二进制安全 第66张
完成!现在能够举行完整的内核读写。

总结

在这篇文章中,我们讨论了@_bazad发现的voucher_swap破绽,并注释了iOS12上获得tfp0的步骤。在接下来的文章中,我们将着眼于Undecimus越狱和所有需要乐成越狱iOS装备的步骤。

参考文献

1.Project Zero Issue tracker - https://bugs.chromium.org/p/project-zero/issues/detail?id=1731
2.iOS 10 - Kernel Heap Revisited - https://gsec.hitb.org/materials/sg2016/D2%20-%20Stefan%20Esser%20-%20iOS%2010%20Kernel%20Heap%20Revisited.pdf
3.Mac OS X Internals: A Systems Approach - https://www.amazon.com/Mac-OS-Internals-Approach-paperback/dp/0134426541
4.MacOS and iOS Internals, Volume III: Security & Insecurity: https://www.amazon.com/MacOS-iOS-Internals-III-Insecurity/dp/0991055535
5.CanSecWest 2017 - Port(al) to the iOS Core - https://www.slideshare.net/i0n1c/cansecwest-2017-portal-to-the-ios-core


网友评论

1条评论
  • 2021-01-24 00:01:08

    着实很难注释在2003年选中詹姆斯后,骑士队为什么还要在2004年用第十顺位选中同样为小先锋的杰克逊,或许正是由于詹姆斯的存在,杰克逊新秀赛季只进场了10场竞赛,场均只能够获得2.9分0.6个篮板。很不容易啊