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

内核扩展模块

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

扩展内核的功能

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

模块化结构的安全设计
  • 代码签名:代码签名是首选的方法,如今已被大多数系统采纳为标准。Windows是一个典型实例,只允许加载具有合法数字签名的驱动程序。在控制权转交给模块入口点之前,内核会验证代码签名,代码签名保存在附加的证书中。证书必须通过私钥签名,内核已知公钥,内核也可以通过一个信任链获得这样一个密钥。苹果在iOS 中到处都使用了代码签名,不过只对自己的代码进行了签名。
  • 预链接:预链接(pre-link)是苹果在OS X 和 iOS 中使用的方法。引导加载器不按照先加载内核,再以一定顺序加载kext的方式进行加载,而是加载一个kernelcache文件。这个文件包含了内核,并且预链接了经过选择的扩展。结果和通过内核动态加载的这些扩展是一样的。预链接的两点优势:
  • 加载的熟读快得多,因为动态加载的过程需要在运行时解析内核和模块中的符号,而预链接只需要进行一次这种解析操作,要加载的内核已经完成了模块的加载工作,所有的链接地址都已经完成了解析
  • kernelcache可以添加签名,设置还可以加密(iOS就加密了)。一旦加载了kernelcache,就可以禁止所有kext加载。这样可以阻断代码进入iOS内核的合法通道

内核扩展(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 的所有者uid必须为root,gid必须为wheel。
  • kext 中目录的权限最多755,即rwxrwxr-x
  • kext 中任何文件的权限最多644(rw-r--r--)
内核扩展的相关操作

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++编写的。

  • Mach 的 kmod 支持
    XNU 的 Mach 层被扩赞为支持内核模块(kernel module)。尽管Mach 层并不知道kext的存在,但是支持kmod对象,即内核模块对象。

  • libKern
    尽管kmod_info_t 仍然是kext的基本机构,但是大部分kext处理逻辑都转移到libkern目录中,并且用C++重写了。kext 的维护逻辑现在在likern/c++/OSKext.cpp 文件中,并且通过I/O Kit 框架暴露给用户态。

  • kext加载的幕后原理
    加载kext的最初请求来自于用户态,但是实际的kext加载需要涉及内核的内存操作,因此必须在内核态中完成。为了连接用户态和内核态,kext的加载机制使用了Mach 消息。所有的kext操作都封装为序列化的XML格式,并放在Mach kext_request 消息的 oll_descriptors 数据中。这些消息属于host_ptiv 子系统的一部分,自然需要访问主机的特权端口。Mach 消息最终会涉及mach_msg_trap,从用户态转移到内核态。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容