MacOS开发 技术集锦

深入解析Mac OS X & iOS 操作系统 学习笔记

2016-11-16  本文已影响831人  CoderKo1o

内核扩展模块

类似用户态的共享库或动态链接库,内核扩展模块是内核使用的模块,可以根据需要动态插入或移除,而且这个需求通常来自用户态。OS X 和 iOS 中的XNU都利用了模块技术来加载各种设备的驱动程序,因此在一个完全自包含的子系统中增强内核的功能。

扩展内核的功能

在用户态有动态链接库(Windows)和共享目标(UNIX)机制,因此在内核态也有内核模块的机制:在XNU中,内核模块称为内核扩展,简称为kext。和XUN核心一样,kext也是XNU的基础构建块。事实上,通过模块插入的内核代码往往比内核核心本身的代码还要多。内核扩展运行在内核态,因此能够完全访问内核空间。开发者可以使用内核导出的所有函数,设置可以使用内核定义为私有的函数。内核对全局变量和数据结构都可以访问甚至修改,因此内核扩展成为各种内核级开发的首选方案。在内核态还可以执行性能剖析、系统调用挂钩以及其他功能。在iOS中,用户态和内核态都是固化的,企图阻止任何形式的修改。因此尽管各种i-设备上也广泛使用了内核扩展模块提供的功能,但是苹果在为每一类设备构建iOS时,都将这些内核扩展固化到kernelcache中了(不过这些内核扩展确实是在运行时从kernelcache中动态加载的)。

模块化结构的安全设计

内核扩展(kext)

内核扩展没有链到kernelcache时是单独存在的,可以在/System/Library/Extensions 目录中找到这些kext。这里大部分kext都是设备驱动程序。内核扩展可以互相依赖。每一个kext都有一个加载索引字段(Index)和一个“引用”字段(Refs)。后者表示这个kext依赖的kext个数,而前者表示这个kext所在列表中的索引,依赖其他kext的kext会使用到这个列表。每一条kext记录后面尖括号中的值表示当前kext依赖的kext索引。

kext结构

kext实际上是bundle,因此遵循通用的bundle布局:一个kext目录只包含一个子目录Contents/,Contents/子目录中的文件如下表:

文件/子目录 内容
CodeDiretory kext的代码目录文件
CodeRequirements kext的代码需求设置
CodeResources 代码资源XML文件,包含kext中文件的散列和规则
CoderSignature kext的代码签名:通常包含苹果的数字证书
Info.plist bundle清单属性列表
MacOS 这个目录下包含了实际的kext为禁止代码,二进制代码文件的类型为BUNDLE(Mach-O类型8)或KEXTABUNDLE(因故64位,Mach-O类型11)
_CodeSignature 包含Code文件的目录,这些文件实际上是Code文件的符号连接
version.plist 表示kext版本信息是属性列表
kext安全需求

由于kext包含了要加载到内核内存中的代码,所以必须有额外的安全措施保障不能随意加载任何代码,因此也不会不小心加载潜在的恶意代码。因此对kext有以下要求:

内核扩展的相关操作

kext相关的命令如下:

命令 用户
kextd 在用户空间动态加载kext
kextfind 通过各种各样的属性和标准查询kext。模拟kextd的操作,因为这条命令查找动态加载的kext
kextlibs 解析kext的依赖性
kextload 一个简单的kext加载器
kextunload 一个简单的kext卸载器
textutil 改进版本的kextload,通过了更多的选项
kernelcache

在OS X 中,kernelcache提供完整的内核,针对操作系统运行的特定平台进行优化,预加载所有必要的驱动,从而加快引导进程。在iOS 中,kernelcache 只包含内核要加载的kext,不含其它任何kext。这种机制是的iOS内核更加安全且不容易篡改。在OS X 和 iOS 两个平台上的kernelcache都采用了相同的结果,实现稍有区别:

操作系统|内容
OS X | Mach-O 二进制格式,可能是胖二进制格式,在偏移量384位置处带有complzss
iOS | IMG3 加密个数的kernelcache,和 OS X 一样采用了complzss 压缩

multi-kext

kernelcache 只是OS X 和 iOS中使用的两种预链接形式之一。还有一种形式称为multi-kext存档,检查mkext。这种文件只不过是两个或多个kext的存档,类似于kernelcache,但是不包含内核本身。file命令和其他命令都不失败mkext文件,但是我们可以通过这个二进制文件第一行中的“MKXTMOSX”签名简单地识别出这类文件。

从程序员的视角看kext

从程序员的角度看,kext只不过是一个内核态的目标文件,在内核态链接,而不是用户态链接的用户态库。创建内核扩展本身的步骤如下:
(1)启动Xcode,然后在System Pkug-ins 面板中选中Generic Kernel Extension
(2)Xcode 自动定义了kext入口点和退出点
(3)在Xcode的plist编辑器中直接编辑Info.plist文件
(4)编译代码,可以在GUI中编译,如果更喜欢用CLI的话,可以通过xcodebuild(1)命令编译

kext的内核支持

kext是XNU中独特的组件,因为kext表示的组件既不属于Mach也不属于BSD。此外,尽管内核中的大部分代码都是用C语言编写的,而XNU中管理kext部分的代码是用C++编写的。I/O Kit是在kext支持的基础上创建的,也是用C++编写的。

上一篇 下一篇

猜你喜欢

热点阅读