【问题标题】:Prevention of file direct memory reads in xnu kernel防止 xnu 内核中的文件直接内存读取
【发布时间】:2018-12-11 11:56:58
【问题描述】:

我有 dylib 文件,我阻止在内核级别对其进行访问。 我使用的驱动程序通过回调来侦听 kauth vnode 范围,从而阻止对该文件的任何访问。

但是,我注意到 coreSymbolication 框架可以在 4 次重试访问文件后绕过此授权流程,并直接访问文件内存,如下面的回溯中所示:

frame #2: 0xffffff7f87ac4784 IOStorageFamily`dkreadwrite(dkr=0xffffff8062fca3e0, dkrtype=<unavailable>) at IOMediaBSDClient.cpp:2975 [opt]
frame #3: 0xffffff80072d8734 kernel`spec_strategy(ap=<unavailable>) at spec_vnops.c:2409 [opt]
frame #4: 0xffffff8007282212 kernel`buf_strategy(devvp=<unavailable>, ap=<unavailable>) at vfs_bio.c:1379 [opt]
frame #5: 0xffffff800728ad42 kernel`cluster_io [inlined] VNOP_STRATEGY(bp=0xffffff8062fca3e0) at kpi_vfs.c:5696 [opt]
frame #6: 0xffffff800728ad0b kernel`cluster_io(vp=0xffffff80145a8c18, upl=0xffffff80107f7700, upl_offset=0x0000000000004000, f_offset=40960, non_rounded_size=0, flags=141, real_bp=<unavailable>, iostate=<unavailable>, callback=<unavailable>, callback_arg=<unavailable>) at vfs_cluster.c:1801 [opt]
frame #7: 0xffffff800728b8f5 kernel`cluster_pagein_ext(vp=0xffffff80145a8c18, upl=0xffffff80107f7700, upl_offset=<unavailable>, f_offset=24576, size=<unavailable>, filesize=-549414335464, flags=<unavailable>, callback=<unavailable>, callback_arg=<unavailable>) at vfs_cluster.c:2171 [opt]
frame #8: 0xffffff800728b7e5 kernel`cluster_pagein(vp=<unavailable>, upl=<unavailable>, upl_offset=<unavailable>, f_offset=<unavailable>, size=<unavailable>, filesize=<unavailable>, flags=0) at vfs_cluster.c:2116 [opt]
frame #9: 0xffffff7f893d60be
frame #10: 0xffffff80075a811a kernel`vnode_pagein [inlined] VNOP_PAGEIN(size=24576, flags=341478424, ctx=<unavailable>) at kpi_vfs.c:5273 [opt]
frame #11: 0xffffff80075a80d3 kernel`vnode_pagein(vp=0xffffff80145a8c18, upl=<unavailable>, upl_offset=<unavailable>, f_offset=24576, size=<unavailable>, flags=341478424, errorp=<unavailable>) at vnode_pager.c:593 [opt]
frame #12: 0xffffff80070dc119 kernel`vnode_pager_cluster_read(vnode_object=0xffffff80145a48e8, base_offset=24576, offset=<unavailable>, io_streaming=<unavailable>, cnt=0x0000000000004000) at bsd_vm.c:851 [opt]
frame #13: 0xffffff80070dbe93 kernel`vnode_pager_data_request(mem_obj=0xffffff80145a48e8, offset=24576, length=<unavailable>, desired_access=<unavailable>, fault_info=<unavailable>) at bsd_vm.c:639 [opt]
frame #14: 0xffffff80070eb011 kernel`vm_fault_page [inlined] memory_object_data_request(memory_object=<unavailable>, offset=<unavailable>, length=4096, desired_access=1, fault_info=<unavailable>) at memory_object.c:2134 [opt]
frame #15: 0xffffff80070eaffb kernel`vm_fault_page(first_object=0xffffff8011d64a00, first_offset=4096, fault_type=1, must_be_resident=0, caller_lookup=0, protection=0xffffff806717be90, result_page=<unavailable>, top_page=<unavailable>, type_of_fault=<unavailable>, error_code=<unavailable>, no_zero_fill=<unavailable>, data_supply=0, fault_info=<unavailable>) at vm_fault.c:1770 [opt]
frame #16: 0xffffff80070ef82a kernel`vm_fault_internal(map=<unavailable>, vaddr=<unavailable>, caller_prot=1, change_wiring=<unavailable>, wire_tag=0, interruptible=2, caller_pmap=<unavailable>, caller_pmap_addr=<unavailable>, physpage_p=<unavailable>) at vm_fault.c:4610 [opt]
frame #17: 0xffffff8007188f92 kernel`user_trap [inlined] vm_fault(map=<unavailable>, fault_type=<unavailable>, change_wiring=0, wire_tag=0, interruptible=2, caller_pmap_addr=0) at vm_fault.c:3416 [opt]
frame #18: 0xffffff8007188f6f kernel`user_trap(saved_state=0xffffff800f07b7a0) at trap.c:1083 [opt]

我的问题是如何在不先打开文件内存的情况下出现内存故障(kauth 阻止打开系统调用)。什么系统调用实际上可以初始化上面列出的回溯的内核线程?

谢谢

【问题讨论】:

  • 发生这种情况的进程是否加载了dylib?如果是这样,我不知道你将如何阻止它。要么让进程加载文件,要么不……
  • 我阻止此文件被除我自己以外的其他进程访问。但它似乎仍然是可能的,因为当您使用vnode_pagein 读取文件时 kauth 没有保护...实际上我什至使用不支持的 mac 策略 mpo_file_check_mmap 钩子方法的 KPI 阻止了mmap...但是pagein 仍然发生,所以我想知道是什么触发了它?如何在不先打开文件的情况下读取文件内存并获取文件描述符?

标签: macos kernel authorization kernel-module xnu


【解决方案1】:

据推测,该文件是在加载主机可执行文件期间打开和映射的,它直接或通过另一个依赖项间接将其列为依赖项。我不知道细节的细节,但大概加载动态库的代码在dyld中,但内核可能会有一些合作。我知道 dyld 做了一些缓存,所以文件可能不是直接加载的,而是已经在内存中的缓存版本被映射到进程中。如果属实,这可能很难防止。我会检查 dyld 源并追踪可执行文件的动态库依赖项是如何加载的,看看在哪里,如果在任何地方,你可能能够拦截它。

【讨论】:

  • 嗯......这是一个有趣的理论,所以你的意思是除了文件缓存之外,还有一个缓存来管理 dyld 中加载的库。在我的情况下,此事件是从 spindump 触发的,它试图获取动态加载此文件的进程的当前采样堆栈跟踪所使用的符号。所以我猜它有一些隐藏的方式来获取文件描述。
  • 这是一篇很好的文章,涵盖了一些 dyld 缓存方面,尤其是最新的 dyld3 实现:allegro.tech/2018/05/Static-linking-vs-dyld3.html
  • @kamil.s,我只是想知道spindump 是否真的尝试加载库以获取报告所需的符号。我会检查这个...
  • symtab 是 Mach-O 文件中的一个普通链接命令 (LC_SYMTAB),据我所知,通常由 dyld 在加载时与其余部分一起加载到进程的地址空间中文件。所以它应该只是找到地址并从内存中读取符号的问题。
  • @pmdj LC_SYMTABdyld 在旧版 Mach-O 中使用,现在由 LC_DYLD_INFO_ONLY 驱动
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-03
相关资源
最近更新 更多