這篇博客的內(nèi)容學(xué)習(xí)《OS X 與 IOS內(nèi)核編程》。書上有些已經(jīng)過時(shí)的指導(dǎo)??梢詤⒖嘉疫@個(gè)。
1.創(chuàng)建
- 開發(fā)環(huán)境:Xcode Version 8.2 (8C38)
- 新建項(xiàng)目:Generic Kernel Extention
- 測(cè)試代碼:
#include <mach/mach_types.h>
#include <libkern/libkern.h>
kern_return_t HelloWorld_start(kmod_info_t * ki, void *d);
kern_return_t HelloWorld_stop(kmod_info_t *ki, void *d);
kern_return_t HelloWorld_start(kmod_info_t * ki, void *d)
{
printf("--------------------");
printf("Hello World\n");
printf("--------------------");
return KERN_SUCCESS;
}
kern_return_t HelloWorld_stop(kmod_info_t *ki, void *d)
{
printf("*********************");
printf("Goodbey World\n");
printf("*********************");
return KERN_SUCCESS;
}
編寫內(nèi)核與平時(shí)用于應(yīng)用程序的API不同,printf()等函數(shù)也是這樣.內(nèi)核并不把用戶控件的頭文件<Stdio.h>包括在內(nèi).而是由自己的printf實(shí)現(xiàn).在<libkern/libkern.h>頭文件中聲明.如果你試圖在內(nèi)核工程中包含<Stdio.h>,編譯器將報(bào)告無法找到包括的頭文件.
-
修改Info.plist,在OSBundleLibraries下面添加如下項(xiàng):
com.apple.kpi.libkern String 16.3.0
庫(kù)標(biāo)識(shí)符.png
在本例中,有了前綴com.apple我們可以將該庫(kù)看做蘋果提供的標(biāo)準(zhǔn)庫(kù)
#######PS: 16.3.0是Mac OS X的內(nèi)核版本,而不是Mac OS X的版本.你也可以通在Terminal中輸入uname -r命令.查看你機(jī)器上的內(nèi)核版本

成功編譯工程之后,Xcode將創(chuàng)建一個(gè)名為HelloWorld.kext的內(nèi)核擴(kuò)展.

先把這個(gè)內(nèi)核擴(kuò)展拷貝到桌面.
查看這個(gè)內(nèi)核的基本信息 ls -l

對(duì)于安全性,因?yàn)閮?nèi)核擴(kuò)展授予了與核心操作系統(tǒng)代碼相同的高級(jí)權(quán)限,
所以內(nèi)核擴(kuò)展程序只可以由以管理員權(quán)限訪問系統(tǒng)的用戶進(jìn)行安裝或者加載.
更進(jìn)一步的安全措施是,系統(tǒng)對(duì)內(nèi)核擴(kuò)展程序包的權(quán)限要求非常嚴(yán)格,
它將拒絕加載還沒有滿足這些要求的內(nèi)核擴(kuò)展,特別是一下情況:
* KEXT程序包以及包含的所有文件和文件夾都必須由root用戶(即用戶id是0)所有
* KEXT程序包以及包含的所有文件和文件夾都必須由wheel(即組id是0)所有;
* KEXT程序包以及包含的任何目錄的權(quán)限掩碼都必須是0755(rwxr-xr-x)
* KEXT程序包中的所有文件的權(quán)限掩碼都必須是0644(rw-r--r--)
所以加載內(nèi)核前還要對(duì)內(nèi)核做處理
修改Kext的組:

接下來
將HelloWorld.kext拷貝到/System/Library/Extensions中

終端執(zhí)行代碼 : (先cd到/System/Library/Extensions的位置)
加載內(nèi)核:sudo kextload HelloWorld.kext
移除內(nèi)核:sudo kextunload HelloWorld.kext
先加載內(nèi)核:
直接加載會(huì)遇到的問題是: 10.11以后,無法使用未簽名的第三方驅(qū)動(dòng).報(bào)錯(cuò)信息如下:
/System/Library/Extensions/HelloWorld.kext failed to load - (libkern/kext) not loadable (reason unspecified); check the system/kernel logs for errors or try kextutil(8).
以前的解決: Try enabling unsigned kext loading: sudo nvram kext-dev-mode=1 and reboot(重啟電腦). 這個(gè)方法已經(jīng)失效了

也就是在OS X EL Capitan之后,kext-dev-mode這種方式已經(jīng)無效了.所以這里面可以了解到,問題是,kext需要簽名.
如何簽名

你可以創(chuàng)建一個(gè)未簽名的kext用于內(nèi)部測(cè)試加載,但是你需要禁用系統(tǒng)的完整性保護(hù)(SIP : System Integrity Protection).查看Configuring System Integrity Protection獲取更多信息
你也可以使用已經(jīng)簽名的kext,但是這個(gè)簽名的生成需要一些開發(fā)者證書,更多信息查看https://developer.apple.com/contact/kext
用第一種方法:(因?yàn)槲抑粶y(cè)試練習(xí)用,證書方面就不詳細(xì)列出)
先查看SIP的狀態(tài): enble ? disable?

因?yàn)槲疫@里是已經(jīng)修改過了,所以為disable.如果是沒有修改過的是enable的.
修改操作:
- 1.重啟電腦,重啟過程中一直按著command + R 直到進(jìn)入startup界面
-
打開Terminal輸入csrutil disable
修改SIP.png - 完成后重啟就可以了
接下來
開機(jī)后重新打開Terminal,重新加載和移除內(nèi)核:
- 加載內(nèi)核:sudo kextload HelloWorld.kext
- 移除內(nèi)核:sudo kextunload HelloWorld.kext
這個(gè)時(shí)候就不會(huì)報(bào)錯(cuò)了.加載成功后輸入kextstat查看.內(nèi)容會(huì)有好多,直接拉到最下面看最新加入的一條就可以了.

最后,查看結(jié)果
查看輸出,在Sierra中看內(nèi)核日志與以前版本不同,以前的都知道從控制臺(tái)看kernel.log,但是不能使用Console.app了,因?yàn)楦菊也坏絢ernel.log,要輸入以下命令:
log show --predicate "processID == 0" --start 2017-2-14 --debug |grep HelloWorld

PS : 注意修改寫時(shí)間就好了.
PS : 前面的3條HelloWorld,Goodbey World,HelloWorld是上一次(十幾分鐘前)測(cè)試遺留.可以忽略.
PS : 就看 --- 和 *** 的輸出內(nèi)容就可以了
寫在最后 :
這篇文章只研究了這本書的第一章,在研究后續(xù)內(nèi)容的時(shí)候,可能因?yàn)椴僮鞑划?dāng),生成一些其他內(nèi)核文件,擾亂了蘋果自身系統(tǒng)的內(nèi)核文件內(nèi)容的讀取.
所以最后導(dǎo)致,電腦開不了機(jī)!!!!!開不了機(jī)!!!!!.
所以,后面的內(nèi)容放棄研究了.......同時(shí),要是你看到,也最好注意下自己的操作是否是正確.最好也備份一下.

