前言 之前團(tuán)隊(duì)內(nèi)技術(shù)交流時(shí)小伙伴分享的自建蜜罐深深的引起了我的興趣,,于是本人決定山寨一個(gè)類似的蜜罐把玩一番~但是擺在眼前的一個(gè)問(wèn)題就是: 一些監(jiān)控進(jìn)程需要運(yùn)行在蜜罐中,,一但“請(qǐng)君入罐”后被黑客察覺(jué)到這些奇奇怪怪的進(jìn)程,就十分尷尬了 所以當(dāng)務(wù)之急是需要將這些監(jiān)控進(jìn)程隱藏起來(lái),,對(duì)Linux略知一二的樓主自然也就接受挑戰(zhàn)啦,。 準(zhǔn)備工作 眾所周知,Linux 操作系統(tǒng)天生自帶一個(gè)虛擬分區(qū) /proc,,該分區(qū)下保存硬件信息,、內(nèi)核運(yùn)行參數(shù)、系統(tǒng)狀態(tài)信息等等,,進(jìn)程運(yùn)行時(shí)的一些信息自然也就存在這個(gè)分區(qū)下,。 如上圖所示,系統(tǒng)里運(yùn)行的每一個(gè)進(jìn)程都會(huì)在 /proc 分區(qū)下新建一個(gè)以自己 pid 命名的目錄,,并將本進(jìn)程的參數(shù)存到該目錄下,。在該目錄下我們可以通過(guò)修改 cgroup 文件暴力的將進(jìn)程綁定在某個(gè) CPU 上,也可以通過(guò)修改 cpuset 文件來(lái)優(yōu)化進(jìn)程在 NUMA 架構(gòu)系統(tǒng)上的運(yùn)行效率,,還可以通過(guò)修改 oom_adj 文件讓系統(tǒng) OOM 機(jī)制永遠(yuǎn)高抬貴手,。而 ps、top 這類查看進(jìn)程的命令恰恰也就是在 /proc 分區(qū)下收集信息,。換句話說(shuō),,如果讓 ps、top 命令選擇性失明,,也就能達(dá)到我們隱藏進(jìn)程的目的了,。 初次嘗試 網(wǎng)上關(guān)于 Linux 隱藏進(jìn)程的方式有很多,比如: 1)強(qiáng)行將進(jìn)程 pid 變?yōu)?0,,這種方法存在破綻因此不予考慮,。 2)還有一種簡(jiǎn)單的方法:系統(tǒng)啟動(dòng)時(shí)會(huì)依據(jù) /etc/fstab 文件內(nèi)容來(lái)掛載分區(qū),在 proc 分區(qū)掛載參數(shù)中加入 hidepid=2 參數(shù)后,,登陸系統(tǒng)的用戶只能查看到當(dāng)前用戶啟動(dòng)的進(jìn)程的信息,。也就是說(shuō), tomcat 用戶只能看到屬于 tomcat 用戶進(jìn)程的信息,。 這種方法也存在弊端,,罐中的黑客只能看到有限的進(jìn)程信息,可能就會(huì)產(chǎn)生會(huì)懷疑,。而且如果再存在個(gè)最近流行的 tomcat 提權(quán)漏洞,,那罐子的身份就會(huì)瞬間露餡。所以這種方式也不合適,,究竟如何才能將我們的問(wèn)題解決在系統(tǒng)最底層呢? “肝”起來(lái) 對(duì)于 Linux 系統(tǒng)來(lái)說(shuō)有著得天獨(dú)厚的優(yōu)勢(shì),,我們可以從內(nèi)核解決一切問(wèn)題。可是樓主的 C語(yǔ)言 實(shí)在是捉急,,不由得又開(kāi)始在互聯(lián)網(wǎng)上尋找巨人的肩膀,。一篇相關(guān)的干貨貼引起了我的注意 http://blog.csdn.net/billpig/Article/details/6038330(文末有引用說(shuō)明),這位作者的思路很明確,,在內(nèi)核中新增兩個(gè)信號(hào)量,,當(dāng)進(jìn)程向內(nèi)核發(fā)出 hide 信號(hào)時(shí),內(nèi)核將不會(huì)為該進(jìn)程在 /proc 目錄下生成對(duì)應(yīng)的目錄,,從而也就從底層鏟除了進(jìn)程的信息,,即使黑客獲得了 root 權(quán)限也無(wú)法通過(guò)常規(guī)手段察覺(jué)到蛛絲馬跡。除此之外,,新增的unhide信號(hào)作用恰好與 hide 信號(hào)相反,。 通過(guò)查閱 crux 官方文檔發(fā)現(xiàn),Demo 中使用的內(nèi)核版本為 2.6.15,。在include/asm-i386/unistd.h 文件中定義新信號(hào)量 294 和 295,。 系統(tǒng)在接收到我們新定義的 294 和 295 兩個(gè)信號(hào)量之后需要調(diào)用對(duì)應(yīng)的函數(shù)來(lái)做出相應(yīng)的動(dòng)作。在 kernel/sys.c 中我們實(shí)現(xiàn) 294 和 295 信號(hào)調(diào)用的函數(shù),。如下圖所示,,sys_hide 和 sys_unhide 兩個(gè)函數(shù)主要功能是修改進(jìn)程 hide 變量的值。 proc 相關(guān)內(nèi)核代碼位于 fs/proc/base.c 中,,在進(jìn)程相關(guān)結(jié)構(gòu)體中新聲明變量hide,,通過(guò)發(fā)送信號(hào)量來(lái)修改 hide 的值,最后在 base.c 文件 proc_pid_readdir 函數(shù)中將 hide 變量的值作為進(jìn)程是否在 proc 文件系統(tǒng)中體現(xiàn)的依據(jù),。 除此之外還有些零碎的步驟,,查看上文中的原帖地址即可,不再贅述,。 踩坑 新內(nèi)核編譯完成后本以為可以愉快的開(kāi)始玩耍了,,結(jié)果新內(nèi)核根本無(wú)法啟動(dòng)。通過(guò)各種修改啟動(dòng)參數(shù)發(fā)現(xiàn),,內(nèi)核報(bào)錯(cuò) “kernel too old” ,這就很尷尬了,。再次站在巨人的肩膀上發(fā)現(xiàn),,確實(shí)是因?yàn)?kernel too old 。之前缺乏編譯老舊內(nèi)核的經(jīng)驗(yàn),,現(xiàn)在才知道原來(lái) gcc 調(diào)用的 libc 不是完全向下兼容的,,我們可以通過(guò) file /lib/libc-*.*.so 來(lái)查看當(dāng)前 libc 能夠編譯的最低版本的內(nèi)核,如下圖所示 libc-2.5.so 可以編譯最低到 2.6.9 版本的內(nèi)核,,如果編譯內(nèi)核版本低于 2.6.9 的話就會(huì)產(chǎn)生 kernel too old 的報(bào)錯(cuò)導(dǎo)致內(nèi)核無(wú)法啟動(dòng),。 綜上,我們的 libc 版本不可太高,又因?yàn)?Demo 中修改的是 i386 架構(gòu)的內(nèi)核源碼,,所以我選擇的實(shí)驗(yàn)環(huán)境為 CentOS 5.11 (32bit) ,。 后續(xù) 至此,我們就可以成功安裝并啟動(dòng) 2.6.15 版本內(nèi)核了,,然而事情并沒(méi)有結(jié)束,。系統(tǒng)供外部進(jìn)程使用的信號(hào)量?jī)H有如下 64 個(gè)。 所以一般情況下我們的進(jìn)程只能發(fā)出上圖這 64 種信號(hào),,我們想要發(fā)出 294 和 295 號(hào)信號(hào)量就必須借助于與系統(tǒng)關(guān)系更密切的 C語(yǔ)言 程序完成,。 然后通過(guò)執(zhí)行命令 gcc hide.c -fPIC -shared -o hide.so 將 hide.c 編譯為 hide.so 的動(dòng)態(tài)鏈接庫(kù)。 以后我們?nèi)绻羞M(jìn)程需要隱藏的話,,只需要在代碼里調(diào)用 hide.so 中的 hide 函數(shù)即可,,同樣 unhide 函數(shù)是他的逆過(guò)程。如下圖所示,,在 Python 中 import ctypes ,,使用它調(diào)用 hide.so 庫(kù)即可實(shí)現(xiàn)當(dāng)前 Python2.7 進(jìn)程的隱藏與恢復(fù)。 至此,,已經(jīng)實(shí)現(xiàn)了內(nèi)核級(jí)別的進(jìn)程隱藏,,可以愉快地做一些想做而又怕被別人發(fā)現(xiàn)的事情了… Linux下編譯內(nèi)核 就跟Windows編譯程序是一樣的思路,Windows 下程序編譯之后是一個(gè)可執(zhí)行的文件,,Linux下呢,,編譯內(nèi)核的時(shí)候,一般也是從Git上把代碼拖下來(lái),,是一個(gè)代碼工程,,編譯后,生成一個(gè)對(duì)應(yīng)格式的文件,,這個(gè)時(shí)候該文件在Linux下 就跟其他文件一樣,,就是一個(gè)普通的文件。如果你想要把編譯的這個(gè)內(nèi)核在當(dāng)前的系統(tǒng)中啟動(dòng)起來(lái)的話,,由于當(dāng)前系統(tǒng)中已經(jīng)有一個(gè)正在運(yùn)行的內(nèi)核了,,一個(gè)思路是你可以設(shè)置Linux一個(gè)變量(類似于Windows的環(huán)境變量),將該變量指向這個(gè)新編譯好的內(nèi)核文件,,然后這個(gè)時(shí)候再重啟當(dāng)前Linux系統(tǒng),,系統(tǒng)啟動(dòng)時(shí)會(huì)讀取那個(gè)變量的值,然后啟動(dòng)新的內(nèi)核,。(實(shí)驗(yàn)的時(shí)候建議在虛擬機(jī)里操作哦) |
|
來(lái)自: 孤獨(dú)一兵 > 《java學(xué)習(xí)》