Quantcast
Channel: CodeSection,代码区,网络安全 - CodeSec
Viewing all articles
Browse latest Browse all 12749

【技术分享】OS X内核大揭秘之基础篇

$
0
0
【技术分享】OS X内核大揭秘之基础篇

2017-10-09 12:07:33

阅读:679次
点赞(0)
收藏
来源: theori.io





【技术分享】OS X内核大揭秘之基础篇

作者:天鸽





【技术分享】OS X内核大揭秘之基础篇

译者:天鸽

预估稿费:200RMB

投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿


前言

虽然近年来的许多研究都集中在 windows 操作系统上,但在安全性方面,iPhone 上的 iOS 和 MacBook 上的 macOS 操作系统也不容忽视。在本系列博客中,我们将探讨 OS X 内核中的 bug 分析和漏洞利用技术。


(1)寻找内核bug

我们可以使用模糊测试和代码审计的方法找到在内核级执行中的 bug,如 BSD、Mach 和 IOKit。

BSD:内核的 BSD 部分提供了大多数系统调用、网络和文件系统的功能。源自 FreeBSD 5。

Mach:来自 CMU 开发的 Mach 3.0 微内核。实现了内核映射和 IPC 等基本服务。用户空间应用程序可以通过 Mach Trap 访问 Mach 服务。

IOKit:IOKit 是一个用 C++ 编写的框架,它为 XNU 提供了驱动程序,而 Apple 提供了自己的运行时系统 libkern。


(2)初步利用

任意读/写可用于获取利用此漏洞必要的数据,或者在内核区域中创建任意数据。

由于每个 bug 都有自己独特的数据,所以应该读/写可以用于该漏洞利用的数据。


(3)内核权限获取和AAR/AAW

为了获得 kernel_task(pid=0) 权限所需的值,我们先遍历内核中的所有进程以获取 ipc object 和 kernel task,然后将数据转储到用户空间。

你可以使用它进行内核级的读/写。


(4)获得root权限

由于每个进程都被加载到内核内存中,所以我们可以捕获目标进程,并将下面的进程权限结构的 CR_RUID(Credential Real UID) 更改为 0。

[bsd/sys/ucred.h] /* *In-kernelcredentialstructure. * *Notethatthisstructureshouldnotbeusedoutsidethekernel,norshould *itorcopiesofitbeexportedoutside. */ structucred{ TAILQ_ENTRY(ucred)cr_link;/*nevermodifythiswithoutKAUTH_CRED_HASH_LOCK*/ u_longcr_ref;/*referencecount*/ structposix_cred{ /* *Thecredentialhashdependsoneverythingfromthispointon *(seekauth_cred_get_hashkey) */ uid_tcr_uid;/*effectiveuserid*/ uid_tcr_ruid;/*realuserid*/ uid_tcr_svuid;/*saveduserid*/ shortcr_ngroups;/*numberofgroupsinadvisorylist*/ gid_tcr_groups[NGROUPS];/*advisorygrouplist*/ gid_tcr_rgid;/*realgroupid*/ gid_tcr_svgid;/*savedgroupid*/ uid_tcr_gmuid;/*UIDforgroupmembershippurposes*/ intcr_flags;/*flagsoncredential*/ }cr_posix; structlabel*cr_label;/*MAClabel*/ /* *NOTE:Ifanythingelse(besidestheflags) *addedafterthelabel,youmustchange *kauth_cred_find(). */ structau_sessioncr_audit;/*userauditingdata*/ };

更改完成后,该进程将返回到 root 目录。

于是,如果你运行 system("/bin/bash");,将可以获得 root 权限的 shell。


背景知识

Kernel Zone

在 OS X 中,内核使用一个称为 Zone 的结构来分配堆。

Zone 使用 zalloc(zone) 和 kalloc(size) 进行分配,使用 zfree(zone,ptr) 和 kfree(ptr,size) 进行释放。

当调用 kalloc 时,zalloc 在内部被调用。kalloc zone 可以通过 sudo zprint kalloc 找到。

zone metadata:第一页中包含的 zone 信息有 size、page_count、alloc_element、free_element 等。

OOL(Out-Of-Line) Port

在 IPC 通信中加载的非内联数据包

它保存在内核中,直到它收到 OOL 的数据。

在做 OS X 内核利用时,可以通过 OOL 的 Leak 进行 fakeport 攻击。


OS X 内核漏洞缓解技术

LASLR

引导时内核内存地址随机化

Kext(Kernel Extension) 和内核共享相同的 kslide

旁路攻击:kslide地址计算(kslide=kernel_base - kernel text base)

DEP

防止内核中的 RWX 权限

旁路攻击:ROP

SMEP/SMAP

Intel CPU 提供的内核内存保护计算

SMEP(Supervisor Mode Execution Protection):无法在用户地址空间中执行内核代码

SMAP(Supervisor Mode Access Protection):不允许在用户地址空间中访问内存。仅在支持的 CPU 体系结构上可用。

旁路攻击:启用 ROP 绕过内核

vm_map_copy()更改

OS X 10.11 El Capitan 以前的内核中,可以使用溢出漏洞捕获 kdata 指针和 vm_map_copy 的 size,从而读取任意的数据,但这里 vm_map_copy 结构体发生了变化。(osfmk/vm/vm_map.h)

// 更改前

structvm_map_copy{ inttype; #defineVM_MAP_COPY_ENTRY_LIST1 #defineVM_MAP_COPY_OBJECT2 #defineVMMAP_COPY_KERNEL_BUFFER3 vm_object_offset_toffset; vm_map_size_tsize; union{ structvm_map_headerhdr; vm_object_tobject; struct{//<<=BeforeChange void*kdata; vm_size_tkalloc_size; }c_k; }c_u; };

// 更改后

structvm_map_copy{ inttype; #defineVM_MAP_COPY_ENTRY_LIST1 #defineVM_MAP_COPY_OBJECT2 #defineVM_MAP_COPY_KERNEL_BUFFER3 vm_object_offset_toffset; vm_map_size_tsize; union{ structvm_map_headerhdr; vm_object_tobject; uint8_tkdata[0];//<<=Changed } }

然而,在 OS X 10.11 El capitan 的 ipc_kmsg_copyout_ool_descriptor() 中存在一种绕过竞争条件技术的情况。(目前该结构体已被修复)


其他

iOS 和 macOS 的结构和安全性补丁是非常相似的,所以通常可以把它们放在一起。

攻击是棘手的,除非有一个完美的溢出 bug。

许多 bug 很难通过远程攻击实现。(例如,使用safari漏洞获取内核权限的过程)

在早期版本的 OS X 中,通过将数据写入一个空指针,可以相对简单地实现 LPE(参见下面的源代码)。

voidnull_page(){ sync(); vm_address_taddr=0; vm_deallocate(mach_task_self(),0x0,0x1000); vm_allocate(mach_task_self(),&addr,0x1000,0); uint64_t*np=0; for(inti=1;i<0x100;i++) { np[i]=0x4141414141414141; } }

从 iOS 9.2,macOS 10.11 开始及以后的版本中,重新分配的内存地址很难被预测。(freelist randomization)

在 iOS 10,macOS 10.12 中,vm_map_size(vm_map_copy) 堆利用的漏洞也已经被修补。


内核调试

简介

一旦内核崩溃,操作系统将停止工作,因此你必须安装一个或多个虚拟机,并使用 kdp 来进行调试。如果你使用的是 OS X 中的“Parallels Desktop”,则可以使用恢复分区来安装 OSX 虚拟机。如果你已经有所需的 OSX 版本,则可以通过搜索安装镜像文件或虚拟机。

首先你需要下载内核调试工具包(Kernel Debug Kit),以便于在主机(host)中配置各种调试环境。内核调试工具包允许你使用 LLDB 或 GDB 加载和调试默认情况下不被包含的符号。如果你希望直接分析内核二进制文件并监视 1day 漏洞,则可以使用内核调试工具包在存在漏洞的 OSX 版本上进行分析。

主机设置

https://developer.apple.com/download/more/?=Kernel%20Debug%20Kit


【技术分享】OS X内核大揭秘之基础篇

它与 OSX 的版本是对应的,因此请根据你正在分析的 1-day 漏洞版本进行下载。安装并运行下载的 dmg 文件时,调试工具包存在于 /Library/Developer/KDKs/ 路径下。


【技术分享】OS X内核大揭秘之基础篇

在 OSX 上运行的内核二进制文件存在于路径 /System/Library/Kernels/kernel 下。你可以将二进制文件 attach 到调试器上,通过配置调试工具包,即使主机和客户机的 OSX 版本不同,你也可以进行调试。

现在,使用 LLDB 完成对主机的配置。


【技术分享】OS X内核大揭秘之基础篇

如果你将二进制文件加载到 LLDB 时看到了上面的报错信息。这很容易解决,如下所示。

(lldb)commandscriptimport"/Library/Developer/KDKs/KDK_10.12.1_16B2657.kdk/System/Library/Kernels/kernel.dSYM/Contents/Resources/DWARF/../python/kernel.py" songsangjun-ui-MacBook-Pro:~s0ngsari$echo"settingssettarget.load-script-from-symbol-filetrue">~/.lldbinit

请注意主机和客户机都必须禁用 System Integrity Protection(SIP)。

你已经完成了对主机环境的配置,现在再对客户机进行配置就可以调试内核了。

客户机设置

OSX 可以使用 nvram 设置引导参数(boot-args)。

$nvramboot-args

boot-args 是作为 OS 在启动时设置的参数。但我们使用这些参数是为了记录调试所需的中断和日志信息。boot-args 有很多参数,这里我们先设置 debug。可以参考下面的图表。


【技术分享】OS X内核大揭秘之基础篇

【技术分享】OS X内核大揭秘之基础篇

调试内核时,给 debug 参数赋值 0x144。DB_NMI 标志允许调试器使用 NMI 中断 attach 到调试对象上。你可以设置如下所示的选项。

$sudonvramboot-args="debug=0x144-v" DB_LOG_PI_SCRN DB_ARP DB_NMI BootVerbosemode $sudoreboot

之后,boot-args 被设置并产生一个 NMI 中断,从而允许调试器调试内核。

有时候即使 NMI 已经在调试对象中给出,也不能进行调试,那么需要在调试器中添加 arp 表。

$arp-s<DebuggeeIP><DebuggeeMac>

这样就完成了主机和客户机的配置,可以继续下面的调试了。

attach 到调试器

作为本文的例子,我们将调试的 1day 漏洞是 CVE-2017-2370。

$vitest.c $clang-otesttest.c

在客户机中编译 PoC 并产生一个 NMI,NMI 可以通过命令 Command + Alt + Control + Shift + Esc 产生。一旦产生了 NMI,操作系统将被安全地停止运行。

在调试器中,你可以使用 kdp-remote 进行远程调试,首先打开 KDK 的内核二进制文件。

songsangjun-ui-MacBook-Pro:~s0ngsari$lldb/Library/Developer/KDKs/KDK_10.12.1_16B2657.kdk/System/Library/Kernels/kernel (lldb)targetcreate"/Library/Developer/KDKs/KDK_10.12.1_16B2657.kdk/System/Library/Kernels/kernel" Loadingkerneldebuggingfrom/Library/Developer/KDKs/KDK_10.12.1_16B2657.kdk/System/Library/Kernels/kernel.dSYM/Contents/Resources/DWARF/../Python/kernel.py LLDBversionlldb-350.0.21.9 settingssettarget.process.python-os-plugin-path"/Library/Developer/KDKs/KDK_10.12.1_16B2657.kdk/System/Library/Kernels/kernel.dSYM/Contents/Resources/DWARF/../Python/lldbmacros/core/operating_system.py" settingssettarget.trap-handler-nameshndl_allintrshndl_alltrapstrap_from_kernelhndl_double_faulthndl_machine_check_fleh_prefabt_ExceptionVectorsBase_ExceptionVectorsTable_fleh_undef_fleh_dataabt_fleh_irq_fleh_decirq_fleh_fiq_generic_fleh_dec commandscriptimport"/Library/Developer/KDKs/KDK_10.12.1_16B2657.kdk/System/Library/Kernels/kernel.dSYM/Contents/Resources/DWARF/../Python/lldbmacros/xnu.py" xnudebugmacrosloadedsuccessfully.Runshowlldbtypesummariestoenabletypesummaries. Currentexecutablesetto'/Library/Developer/KDKs/KDK_10.12.1_16B2657.kdk/System/Library/Kernels/kernel'(x86_64). (lldb)

如果没有报错,则使用 kdp-remote 命令链接到远程调试器。

(lldb)kdp-remote<debuggeeIP> Version:DarwinKernelVersion16.1.0:WedOct1920:31:56PDT2016;root:xnu-3789.21.4~4/RELEASE_X86_64;UUID=75CA1C4D-7BF4-321B-B544-D8F1B6D60EF8;stext=0xffffff8014200000 KernelUUID:75CA1C4D-7BF4-321B-B544-D8F1B6D60EF8 LoadAddress:0xffffff8014200000 Kernelslid0x14000000inmemory. Loadedkernelfile/Library/Developer/KDKs/KDK_10.12.1_16B2657.kdk/System/Library/Kernels/kernel Loading94kextmoduleswarning:Can'tfindbinary/dSYMforcom.apple.kec.corecrypto(809FEC94-017C-307A-B099-A01EFF5485FB) .warning:Can'tfindbinary/dSYMforcom.apple.kec.pthread(36567317-B854-3157-ABF3-CEAD0A3770BB) .warning:Can'tfindbinary/dSYMforcom.apple.kec.Libm(51D82C5F-0248-334D-ADC6-5861BBB83C97) .warning:Can'tfindbinary/dSYMforcom.apple.iokit.IOACPIFamily(4F7FB6AD-2498-3F71-827C-ED7AA4BF2511) .Targetarch:x86_64 Instantiatingthreadscompletelyfromsavedstateinmemory. .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleACPIPlatform(249D7BA8-3FD5-3207-A482-0605CB898037) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleFDEKeyStore(EA5D0966-E8EA-337A-98EB-195806E8F723) .warning:Can'tfindbinary/dSYMforcom.apple.iokit.IOReportFamily(B14DC3D3-7250-3DA3-BF50-C666EBEDAF4C) .Targetarch:x86_64 Instantiatingthreadscompletelyfromsavedstateinmemory. .warning:Can'tfindbinary/dSYMforcom.apple.driver.DiskImages(05A729EF-20B8-3254-8F13-42DF42E0544B) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleBusPowerController(DB526B45-1A45-3A81-A0C1-57F826CADEDF) .Targetarch:x86_64 Instantiatingthreadscompletelyfromsavedstateinmemory. .warning:Can'tfindbinary/dSYMforcom.apple.driver.KernelRelayHost(3B58E6F0-DE92-3289-9D3B-3BF12208585F) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleCredentialManager(54677B39-44B3-3AAA-BBEC-D78D0B5CC1A7) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleMobileFileIntegrity(0EFA4D2C-2271-3C43-B777-17D05716144A) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleKeyStore(75515493-6D25-39F7-8F0B-B08B505CAB74) .warning:Can'tfindbinary/dSYMforcom.apple.security.TMSafetyNet(1CB512A3-24BD-344A-BFB4-44A61F27AB03) .warning:Can'tfindbinary/dSYMforcom.apple.kext.AppleMatch(3B280DAB-903F-33DC-8110-525A1154B11E) .warning:Can'tfindbinary/dSYMforcom.apple.security.sandbox(32039FC4-CA9B-3B74-B326-A2BF5CFE45E1) .warning:Can'tfindbinary/dSYMforcom.apple.security.quarantine(EC92F0F9-694E-3E22-8B2C-4A071D20C6BA) .warning:Can'tfindbinary/dSYMforcom.apple.nke.applicationfirewall(2A0DC0EF-655C-3D4B-93FD-3AED72BEBBDC) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleAPIC(BC2E6D01-BCBB-3525-BF38-BF99C3F1EC46) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleSMBIOS(9BB02681-4B47-3592-AD62-71FB0BF56965) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleRTC(3FD1BCF4-8AFC-3CE6-A36E-26410544AD14) .warning:Can'tfindbinary/dSYMforcom.apple.iokit.IOSMBusFamily(185F0EBF-0262-3370-BD47-8FE4C8AA726E) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleACPIEC(BC227AE1-3CD5-3938-9C8C-009F1A966FBE) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleHPET(2CFB49B8-4CC2-320B-9C6E-99646DFD8571) .Targetarch:x86_64 Instantiatingthreadscompletelyfromsavedstateinmemory. .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleACPIButtons(4D5E51D6-8A6B-3B6A-A8F2-472D56C9D0C3) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleSmartBatteryManager(31670664-0EF0-39B5-A13F-15B8F9EC1283) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleEFIRuntime(6B7A5B9A-C313-3F7F-B6E2-60EE54593BC8) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleEFINVRAM(6F4404D6-8625-35CA-AEB6-6ECD7B64FA52) .Targetarch:x86_64 Instantiatingthreadscompletelyfromsavedstateinmemory. .warning:Can'tfindbinary/dSYMforcom.apple.driver.usb.AppleUSBHostPacketFilter(9888F9CD-B7EE-3A9D-8530-6FA4C167B26C) .warning:Can'tfindbinary/dSYMforcom.apple.driver.usb.AppleUSBEHCI(BF6EF9A2-F090-3094-B3FA-F34351D946CF) .warning:Can'tfindbinary/dSYMforcom.apple.driver.usb.AppleUSBUHCI(4EF43593-FC11-31E6-8B27-E7A6B5703C15) .warning:Can'tfindbinary/dSYMforcom.apple.driver.usb.AppleUSBUHCIPCI(4EC90565-DB48-3190-8608-1F6DA30B8691) .warning:Can'tfindbinary/dSYMforcom.apple.driver.usb.AppleUSBXHCI(E5F9850E-A1A1-305F-854D-48B46C08B2EC) .warning:Can'tfindbinary/dSYMforcom.apple.driver.usb.AppleUSBXHCIPCI(B4287428-23D9-3547-93B5-2FEB73A02EA6) .warning:Can'tfindbinary/dSYMforcom.apple.driver.usb.AppleUSBEHCIPCI(4FCE62CA-0477-34A2-9564-86F807CDBD4D) .warning:Can'tfindbinary/dSYMforcom.apple.iokit.IOATAFamily(BC25A382-3DA0-33C7-93C5-E8A823B50F98) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleIntelPIIXATA(BDC5E432-B04E-3ACF-A213-672128140381) .warning:Can'tfindbinary/dSYMforcom.apple.iokit.IOAHCIFamily(5C275B66-A173-3D92-853A-44FC35D45FFC) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleAHCIPort(BE72151C-73BE-35B7-8C31-74F49E4C5E98) .Targetarch:x86_64 Instantiatingthreadscompletelyfromsavedstateinmemory. .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleIntel8254XEthernet(34B30414-098D-3D22-AAB5-1A754D0647C6) .warning:Can'tfindbinary/dSYMforcom.apple.iokit.IOAHCIBlockStorage(C449634B-8121-3BFB-972D-966847C4321F) .Targetarch:x86_64 Instantiatingthreadscompletelyfromsavedstateinmemory. .warning:Can'tfindbinary/dSYMforcom.apple.iokit.IOAHCISerialATAPI(681FA1E2-E3DE-3FEB-ACA7-16FC2B9078A6) .warning:Can'tfindbinary/dSYMforcom.apple.filesystems.hfs.encodings.kext(68A8D6C1-CDCA-371C-970B-325BF2E7ECAB) .Targetarch:x86_64 Instantiatingthreadscompletelyfromsavedstateinmemory. .Targetarch:x86_64 Instantiatingthreadscompletelyfromsavedstateinmemory. .Targetarch:x86_64 Instantiatingthreadscompletelyfromsavedstateinmemory. .Targetarch:x86_64 Instantiatingthreadscompletelyfromsavedstateinmemory. .Targetarch:x86_64 Instantiatingthreadscompletelyfromsavedstateinmemory. .warning:Can'tfindbinary/dSYMforcom.apple.filesystems.hfs.kext(6C6C4A98-1534-3C52-B006-00FBC479233E) .warning:Can'tfindbinary/dSYMforcom.apple.BootCache(C38789F4-9226-303C-99BE-3B8EAF8EC5C2) .warning:Can'tfindbinary/dSYMforcom.apple.AppleFSCompression.AppleFSCompressionTypeZlib(9B32DDE9-151F-31A1-90E9-3CEB2C7BE27C) .warning:Can'tfindbinary/dSYMforcom.apple.AppleFSCompression.AppleFSCompressionTypeDataless(C6F882D7-C35C-3963-A2FA-10033FF40107) .warning:Can'tfindbinary/dSYMforcom.apple.driver.usb.AppleUSBHostCompositeDevice(30502C8D-F4B2-345F-B8F0-F8C54CAD7F46) .warning:Can'tfindbinary/dSYMforcom.apple.driver.usb.networking(74394A72-1E87-363E-8CFD-182BD8C9362E) .warning:Can'tfindbinary/dSYMforcom.apple.driver.usb.AppleUSBHub(F7BC6869-E4BA-3291-B7EA-BF28A0ABEF4A) .warning:Can'tfindbinary/dSYMforcom.apple.driver.usb.IOUSBHostHIDDevice(0548123A-013B-3C74-86A8-33DF73E9CBBB) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleHIDKeyboard(664B787F-6DE5-3211-9081-E434055A550B) .Targetarch:x86_64 Instantiatingthreadscompletelyfromsavedstateinmemory. .warning:Can'tfindbinary/dSYMforcom.parallels.kext.video(5520E5F4-AC7C-9446-6088-5D8CAF25478D) .warning:Can'tfindbinary/dSYMforcom.parallels.driver.AppleIntelAC97Controller(705C3A56-06CE-E995-5A75-618C5EF3D45D) .warning:Can'tfindbinary/dSYMforcom.apple.vecLib.kext(C0ABF85C-CA30-3F02-9E1E-06F3BA5047A8) .Targetarch:x86_64 Instantiatingthreadscompletelyfromsavedstateinmemory. .warning:Can'tfindbinary/dSYMforcom.apple.iokit.IOSlowAdaptiveClockingFamily(F026208D-CC0C-3599-B303-9196904A584E) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleIntelSlowAdaptiveClocking(6FE984DD-A1FE-309E-83CF-B346989A6F17) .warning:Can'tfindbinary/dSYMforcom.apple.driver.IOPlatformPluginFamily(087648A2-8A44-3095-AEC7-44A872A46205) .warning:Can'tfindbinary/dSYMforcom.apple.driver.IOPlatformPluginLegacy(9156271B-C61E-3B40-B5B6-102369F12A8B) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleSMC(969D80B2-E714-3145-95B0-F61627E0EE4D) .warning:Can'tfindbinary/dSYMforcom.apple.driver.ACPI_SMC_PlatformPlugin(7224B682-B40F-3A4A-BCA0-82727D251ECB) .warning:Can'tfindbinary/dSYMforcom.parallels.kext.tg(09C02F97-D104-80F1-2A96-6BEF8A2F6967) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleSMBusController(4DAA381E-3690-3E94-8025-DFB34F714094) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleMCCSControl(102DD5D9-2DD5-3BCB-B5C0-BE08E1049CD6) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleUpstreamUserClient(F39509A4-191C-35DA-B7D9-08F95E5AB8BC) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleHV(39AC9B9B-7B20-322F-82F0-044B3CC08D43) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleSSE(907BB577-46DF-3C86-9034-758B61AD054D) .warning:Can'tfindbinary/dSYMforcom.apple.Dont_Steal_Mac_OS_X(B97F871A-44FD-3EA4-BC46-8FD682118C79) .warning:Can'tfindbinary/dSYMforcom.apple.iokit.IOBluetoothFamily(794ACDDD-2B46-3BF0-94E9-4FD7C109A427) .Targetarch:x86_64 Instantiatingthreadscompletelyfromsavedstateinmemory. .warning:Can'tfindbinary/dSYMforcom.apple.iokit.IOBluetoothSerialManager(6F68B8CF-6543-328E-AF57-DD250412CF02) .warning:Can'tfindbinary/dSYMforcom.apple.iokit.IOSurface(D3B2D208-487C-3166-9F7D-D6159AABC428) .warning:Can'tfindbinary/dSYMforcom.apple.iokit.IOUserEthernet(5EE448BD-95EC-35AD-B7FC-A1237E4BB346) .warning:Can'tfindbinary/dSYMforcom.apple.driver.pmtelemetry(F46D019B-17FF-3CD5-A093-0894B81C1404) .warning:Can'tfindbinary/dSYMforcom.parallels.driver.AppleIntelAC97Audio(F8F3B21C-958B-BB10-E13C-42CA34BF6815) .warning:Can'tfindbinary/dSYMforcom.apple.driver.AppleOSXWatchdog(757A8B72-2A1A-32BA-99EC-6D802DE6E91F) .warning:Can'tfindbinary/dSYMforcom.apple.kext.triggers(4E564246-8804-3673-B440-606AD360A3BB) .warning:Can'tfindbinary/dSYMforcom.apple.filesystems.autofs(AA36D92F-D92B-3102-BAE3-F86A0A298143) .warning:Can'tfindbinary/dSYMforcom.apple.filesystems.smbfs(42EF3BC8-5041-3E94-BC74-9D5906694E3A) .warning:Can'tfindbinary/dSYMforcom.apple.driver.usb.cdc(6CB80B6B-9071-38ED-9A4B-635ABF20A429) .Targetarch:x86_64 Instantiatingthreadscompletelyfromsavedstateinmemory. done. Targetarch:x86_64 Instantiatingthreadscompletelyfromsavedstateinmemory. kernelwascompiledwithoptimization-steppingmaybehaveoddly;variablesmaynotbeavailable. Process1stopped *thread#2:tid=0x16cc,0xffffff801440bb4ekernel`Debugger[inlined]hw_atomic_sub(delt=1)atlocks.c:1513,name='0xffffff801c791028',queue='0x0',stopreason=signalSIGSTOP frame#0:0xffffff801440bb4ekernel`Debugger[inlined]hw_atomic_sub(delt=1)atlocks.c:1513[opt] (lldb)

如果正确地捕获到了内核,就可以通过恢复调试对象进程并运行 PoC 来检查是否会产生崩溃。

(lldb)c Process1resuming (lldb)Unloading1kextmodules.done. Process1stopped *thread#4:tid=0x1af6,0xffffff8014751a8ckernel`fp_lookup(p=0xffffff801ebec780,fd=1,resultfp=0xffffff806eb6bf20,locked=0)+92atkern_descrip.c:3879,name='0xffffff801c09a9a8',queue='0x0',stopreason=EXC_BAD_INSTRUCTION(code=13,subcode=0x0) frame#0:0xffffff8014751a8ckernel`fp_lookup(p=0xffffff801ebec780,fd=1,resultfp=0xffffff806eb6bf20,locked=0)+92atkern_descrip.c:3879[opt] (lldb)registerread GeneralPurposeRegisters: rax=0x4141414141414141 rbx=0x0000000000000001 rcx=0x0000000000000001 rdx=0xffffff8020d0e800 rdi=0xffffff801ebec848 rsi=0x0000000000000001 rbp=0xffffff806eb6bef0 rsp=0xffffff806eb6bec0 r8=0x0000000000000000 r9=0x00007fffda6afa50 r10=0x000000000000000a r11=0x0000000000000246 r12=0xffffff801ebec780 r13=0xffffff801ec3e4f8 r14=0x0000000000000000 r15=0xffffff806eb6bf20 rip=0xffffff8014751a8ckernel`fp_lookup+92atkern_descrip.c:3879 rflags=0x0000000000010246 cs=0x0000000000000008 fs=0x0000000000000000 gs=0x0000000000000000 (lldb)

LLDB 和 GDB 的命令有所不同,最好将它们分开学习。或者使用一个名为 kgmacros 的脚本,总的来说使用 GDB 进行调试也不错。

记录堆日志

运行 Poc 并设置断点来跟踪堆是很困难的。但是,你可以通过上面说到的 boot-args 来跟踪堆。这可以跟踪 OSX 堆的所覆盖的 zone。

$sudonvramboot-args="debug=0x144-v-zczlog1=kalloc.128zlog2=kalloc.256"

与上面的命令一样,使用 -zc zlog1=zone,然后重启。最重要的是知道 Poc 所使用的 zone。我们只跟踪所选择的 zone,而不是全部,所以如果你想跟踪起来比较轻松,就只传递一个 zone 到 boot-args 中。

使用 zlog 时

(lldb)bt *thread#2:tid=0x0cb5,0xffffff801200bb4ekernel`Debugger[inlined]hw_atomic_sub(delt=1)atlocks.c:1513,name='0xffffff8019752980',queue='0x0',stopreason=signalSIGSTOP *frame#0:0xffffff801200bb4ekernel`Debugger[inlined]hw_atomic_sub(delt=1)atlocks.c:1513[opt] frame#1:0xffffff801200bb4ekernel`Debugger(message=<unavailable>)+910atmodel_dep.c:1025[opt] frame#2:0xffffff8011ef368ckernel`panic(str="\"afreedzoneelementhasbeenmodifiedinzone%s:expected%pbutfound%p,bitschanged%p,atoffset%dof%dinelement%p,cookies%p%p\"@/Library/Caches/com.apple.xbs/Sources/xnu/xnu-3789.21.4/osfmk/kern/zalloc.c:651")+236atdebug.c:458[opt] frame#3:0xffffff8011f3f5c0kernel`backup_ptr_mismatch_panic[inlined]zone_element_was_modified_panic(offset=0)+800atzalloc.c:642[opt] frame#4:0xffffff8011f3f559kernel`backup_ptr_mismatch_panic(zone=<unavailable>,element=<unavailable>,primary=4702111234474983745,backup=<unavailable>)+697atzalloc.c:710[opt] frame#5:0xffffff8011f3e739kernel`try_alloc_from_zone(zone=<unavailable>,check_poison=<unavailable>)+521atzalloc.c:832[opt] frame#6:0xffffff8011f3d174kernel`zalloc_internal(zone=<unavailable>,canblock=1,nopagewait=0)+484atzalloc.c:2284[opt] frame#7:0xffffff8011f84580kernel`vm_map_copyin_internal+51atvm_map.c:9428[opt] frame#8:0xffffff8011f8454dkernel`vm_map_copyin_internal(src_map=<unavailable>,src_addr=140351705630208,len=3240,flags=<unavailable>,copy_result=<unavailable>)+253atvm_map.c:10279[opt] frame#9:0xffffff8011ed7629kernel`ipc_kmsg_copyin_ool_descriptor[inlined]vm_map_copyin_common(src_map=<unavailable>,src_destroy=<unavailable>,copy_result=0xffffff8071adbe40,use_maxprot=0)+201atvm_map.c:10187[opt] frame#10:0xffffff8011ed7616kernel`ipc_kmsg_copyin_ool_descriptor(dsc=0xffffff8018874c98,user_dsc=<unavailable>,is_64bit=<unavailable>,paddr=<unavailable>,copy=0xffffff8071adbe40,space_needed=<unavailable>,map=<unavailable>,mr=<unavailable>)+182atipc_kmsg.c:2701[opt] frame#11:0xffffff8011ed7c25kernel`ipc_kmsg_copyin_body(kmsg=0xffffff8018874c00,space=0xffffff8018925b40,map=0xffffff801c0e9e08)+613atipc_kmsg.c:3035[opt] frame#12:0xffffff8011ee992fkernel`mach_msg_overwrite_trap(args=<unavailable>)+287atmach_msg.c:548[opt] frame#13:0xffffff8011ff26aekernel`mach_call_munger64(state=0xffffff8018dd12c0)+430atbsd_i386.c:562[opt] frame#14:0xffffff8011ea5f66kernel`hndl_mach_scall64+22

未使用 zlog 时

(lldb)bt *thread#2:tid=0x13ab,0xffffff8015c0bb4ekernel`Debugger[inlined]hw_atomic_sub(delt=1)atlocks.c:1513,name='0xffffff80200f4288',queue='0x0',stopreason=signalSIGSTOP *frame#0:0xffffff8015c0bb4ekernel`Debugger[inlined]hw_atomic_sub(delt=1)atlocks.c:1513[opt] frame#1:0xffffff8015c0bb4ekernel`Debugger(message=<unavailable>)+910atmodel_dep.c:1025[opt] frame#2:0xffffff8015af368ckernel`panic(str="\"Invalidqueueelementlinkagefor%p:next%pnext->prev%pprev%pprev->next%p\"@/Library/Caches/com.apple.xbs/Sources/xnu/xnu-3789.21.4/osfmk/kern/queue.h:245")+236atdebug.c:458[opt] frame#3:0xffffff8015bec040kernel`pmap_enter_options[inlined]__QUEUE_ELT_VALIDATE+81atqueue.h:244[opt] frame#4:0xffffff8015bebfefkernel`pmap_enter_options[inlined]insqueatqueue.h:347[opt] frame#5:0xffffff8015bebfefkernel`pmap_enter_options[inlined]pv_hash_add+32atpmap_internal.h:544[opt] frame#6:0xffffff8015bebfcfkernel`pmap_enter_options(pmap=<unavailable>,vaddr=<unavailable>,pn=<unavailable>,prot=<unavailable>,fault_type=<unavailable>,flags=<unavailable>,wired=<unavailable>,options=<unavailable>,arg=<unavailable>)+5103atpmap_x86_common.c:926[opt] frame#7:0xffffff8015b6fb41kernel`vm_fault_enter(m=0xffffff801c1c3c00,pmap=<unavailable>,vaddr=140736734584832,prot=<unavailable>,caller_prot=<unavailable>,wired=0,change_wiring=<unavailable>,no_cache=0,cs_bypass=<unavailable>,user_tag=1962753648,pmap_options=<unavailable>,need_retry=<unavailable>,type_of_fault=<unavailable>)+4481atvm_fault.c:3292[opt] frame#8:0xffffff8015b71405kernel`vm_fault_internal(map=<unavailable>,vaddr=<unavailable>,caller_prot=<unavailable>,change_wiring=0,interruptible=2,caller_pmap=0x0000000000000000,caller_pmap_addr=0,physpage_p=<unavailable>)+4421atvm_fault.c:4086[opt] frame#9:0xffffff8015c069fckernel`user_trap[inlined]vm_fault(map=<unavailable>,vaddr=<unavailable>,fault_type=<unavailable>,change_wiring=0,interruptible=2,caller_pmap=<unavailable>,caller_pmap_addr=0)+652atvm_fault.c:3397[opt] frame#10:0xffffff8015c069d8kernel`user_trap(saved_state=0xffffff801ff11060)+616attrap.c:1120[opt] frame#11:0xffffff8015aa5655kernel`hndl_alltraps+229

当查看调用栈时,差异是很明显的。使用了 zlog 时,你可以看到调用栈被分配给了 zalloc,但未使用 zlog 时就看不到。所以如果你要分析 1day 漏洞的堆腐败时,了解 zone 的概念并使用 zlog 可以进行更好的调试。

更多内容

了解 bug 很重要,但调试也很重要。做调试时我会使用一些简单的命令。

(lldb)bt *thread#2:tid=0x1650,0xffffff801200bb4ekernel`Debugger[inlined]hw_atomic_sub(delt=1)atlocks.c:1513,name='0xffffff801a0eee18',queue='0x0',stopreason=signalSIGSTOP *frame#0:0xffffff801200bb4ekernel`Debugger[inlined]hw_atomic_sub(delt=1)atlocks.c:1513[opt] frame#1:0xffffff801200bb4ekernel`Debugger(message=<unavailable>)+910atmodel_dep.c:1025[opt] frame#2:0xffffff8011ef368ckernel`panic(str="\"afreedzoneelementhasbeenmodifiedinzone%s:expected%pbutfound%p,bitschanged%p,atoffset%dof%dinelement%p,cookies%p%p\"@/Library/Caches/com.apple.xbs/Sources/xnu/xnu-3789.21.4/osfmk/kern/zalloc.c:651")+236atdebug.c:458[opt] frame#3:0xffffff8011f3f5c0kernel`backup_ptr_mismatch_panic[inlined]zone_element_was_modified_panic(offset=0)+800atzalloc.c:642[opt] frame#4:0xffffff8011f3f559kernel`backup_ptr_mismatch_panic(zone=<unavailable>,element=<unavailable>,primary=4702111234474983745,backup=<unavailable>)+697atzalloc.c:710[opt] frame#5:0xffffff8011f3e739kernel`try_alloc_from_zone(zone=<unavailable>,check_poison=<unavailable>)+521atzalloc.c:832[opt] frame#6:0xffffff8011f3d174kernel`zalloc_internal(zone=<unavailable>,canblock=1,nopagewait=0)+484atzalloc.c:2284[opt] frame#7:0xffffff8011ed5248kernel`ipc_kmsg_alloc(msg_and_trailer_size=4352)+248atipc_kmsg.c:929[opt] frame#8:0xffffff8011ef832dkernel`ipc_kobject_server(request=<unavailable>,option=<unavailable>)+141atipc_kobject.c:299[opt] frame#9:0xffffff8011ed5f61kernel`ipc_kmsg_send(kmsg=<unavailable>,option=<unavailable>,send_timeout=<unavailable>)+225atipc_kmsg.c:1826[opt] frame#10:0xffffff8011ee9957kernel`mach_msg_overwrite_trap(args=<unavailable>)+327atmach_msg.c:556[opt] frame#11:0xffffff8011ff26aekernel`mach_call_munger64(state=0xffffff8019fed920)+430atbsd_i386.c:562[opt] frame#12:0xffffff8011ea5f66kernel`hndl_mach_scall64+22

bt 命令是 BackTrace 的缩写,它用于将线程堆栈信息打印出来。你可以选择跳转到单个 frame 并查看其局部变量。

(lldb)frameselect5 frame#5:0xffffff8011f3e739kernel`try_alloc_from_zone(zone=<unavailable>,check_poison=<unavailable>)+521atzalloc.c:832[opt]

如果你使用 frame select 命令选择了一个 frame,则会把当前 frame 的信息打印出来,并且 rip 也会变为该 frame 的地址。如下所示。

(lldb)registerread GeneralPurposeRegisters: rbx=0xffffff801f977000 rbp=0xffffff8872cabc50 rsp=0xffffff8872cabc10 r12=0x7e415085550ee3c7 r13=0x4141414141414141 r14=0xffffff8017cd70a0 r15=0x4141414141414141 rip=0xffffff8011f3e739kernel`try_alloc_from_zone+521atzalloc.c:832

你可以看到 rip 确实在我们选择的 frame 中,并且可以看到该函数局部变量的值。

(lldb)framevar (zone_t)zone=<variablenotavailable> (boolean_t*)check_poison=<variablenotavailable> (zone_page_metadata*)page_meta=0xffffff8017cd70a0 (vm_offset_t)element=18446743524483756032 (vm_offset_t*)primary=0xffffff801f977000 (vm_offset_t)next_element_primary=4702111234474983745 (vm_offset_t)next_element=9097641255853024199 (vm_offset_t)next_element_backup=4702111234474983745 (vm_offset_t*)backup=<nolocation,valuemayhavebeenoptimizedout>

OSX 中 Page 的第一部分被称为元数据(Meta data),它包含了有关该 zone 的大量信息,如堆的元数据。

对于 iOS 10,有如下元数据:

zindex:zone_array 中的索引

Page_count:分配的页面大小

free_count:页面中 free element 数量

freelist_offset:页面中第一个 free element 的地址

下面我们看一下名为 primary 的变量。

(lldb)memoryread0xffffff801f977000 0xffffff801f977000:41414141414141414141414141414141AAAAAAAAAAAAAAAA 0xffffff801f977010:41414141414141414141414141414141AAAAAAAAAAAAAAAA

如果 PoC 被正确地触发,那么正常情况下会显示一串 A。由于分配给 zone 的元素在 memset 中以 A 填充,因此结果如上所示。

以这种方式触发 PoC 后,如果存在你所需的 frame,则可以通过选择该 frame 并检查局部变量的方式进行调试。请注意 frame 相关的命令通常是很有用的。

我们可以查看在 Mac 上运行的所有任务的基址,内核任务也在其中。可以看到内核任务名为 kernel_task,你可以使用下面的命令将其输出。

(lldb)showalltasks taskvm_mapipc_space#actsflagspidprocessio_policywq_statecommand 0xffffff80185b3aa00xffffff8014d1e6e80xffffff80180ab80013400xffffff80126ba360-1-1-1kernel_task 0xffffff80185b30000xffffff8018db08380xffffff80180ab840610xffffff8018d81128-1-1-1launchd 0xffffff801961c0000xffffff80196032680xffffff80195c27404D340xffffff8018d80cb0-1-1-1UserEventAgent 0xffffff801961caa00xffffff80196038380xffffff80195c29802D360xffffff8018d80838TQ-1-1-1uninstalld 0xffffff8019634aa00xffffff80196034580xffffff80195c29c02D370xffffff8018d81e90-1-1-1kextd&n


【技术分享】OS X内核大揭秘之基础篇
【技术分享】OS X内核大揭秘之基础篇
本文由 安全客 翻译,转载请注明“转自安全客”,并附上链接。
原文链接:http://theori.io/research/korean/osx-kernel-exploit-1

Viewing all articles
Browse latest Browse all 12749

Trending Articles