Kate Li (Taiwan)的部落格

首頁

linux行程隱藏的一種實現思路

作者 alkan 時間 2020-03-25
all

目標讀者:系統安全愛好者

閱讀時長:約7分鐘

本文概要:一種Linux中行程隱藏的思路、操作與步驟截圖

前置知識:最好對Linux下編譯程式略知一二(文末有知識注解與擴展閱讀,最後奉上網易小風景)

感謝NSRC老司機團長的分享~

之前團隊內技術交流時小夥伴分享的自建蜜罐深深的引起了我的興趣,於是本人决定山寨一個類似的蜜罐把玩一番~但是擺在眼前的一個問題就是:

所以當務之急是需要將這些監控行程隱藏起來,對Linux略知一二的樓主自然也就接受挑戰啦。

眾所周知,Linux作業系統天生自帶一個虛擬分區/proc,該分區下保存硬體資訊、內核運行參數、系統狀態資訊等等,行程運行時的一些資訊自然也就存在這個分區下。

如上圖所示,系統裏運行的每一個行程都會在/proc分區下新建一個以自己pid命名的目錄,並將本行程的參數存到該目錄下。在該目錄下我們可以通過修改 cgroup檔案暴力的將行程綁定在某個CPU上,也可以通過修改cpuset檔案來優化行程在NUMA架構系統上的運行效率,還可以通過修改oom_adj檔案讓系統OOM機制永遠高抬貴手。而ps、top這類查看行程的命令恰恰也就是在/proc分區下收集資訊。換句話說,如果讓ps、top命令選擇性失明,也就能達到我們隱藏行程的目的了。

網上關於Linux隱藏行程的管道有很多,比如:

1)强行將行程pid變為0,這種方法存在破綻囙此不予考慮。

2)還有一種簡單的方法:系統啟動時會依據/etc/fstab檔案內容來掛載分區,在proc分區掛載參數中加入hidepid=2參數後,登入系統的用戶只能查看到當前用戶啟動的行程的資訊。也就是說,tomcat用戶只能看到屬於tomcat用戶行程的資訊。

這種方法也存在弊端,罐中的駭客只能看到有限的行程資訊,可能就會產生會懷疑。而且如果再存在個最近流行的tomcat提權漏洞,那罐子的身份就會瞬間破功。所以這種管道也不合適,究竟如何才能將我們的問題解决在系統最底層呢?

對於Linux系統來說有著得天獨厚的優勢,我們可以從內核解决一切問題。可是樓主的C語言實在是捉急,不由得又開始在互聯網上尋找巨人的肩膀。一篇相關的乾貨貼引起了我的注意http://blog.csdn.net/billpig/article/details/6038330(文末有引用說明),這位作者的思路很明確,在內核中新增兩個信號量,當行程向內核發出hide訊號時,內核將不會為該行程在/proc目錄下生成對應的目錄,從而也就從底層剷除了行程的資訊,即使駭客獲得了root許可權也無法通過常規手段察覺到蛛絲馬跡。除此之外,新增的unhide訊號作用恰好與hide訊號相反。

通過查閱crux官方檔案發現,Demo中使用的內核版本為2.6.15。在include/asm-i386/unistd.h檔案中定義新信號量294和295。

系統在接收到我們新定義的294和295兩個信號量之後需要調用對應的函數來做出相應的動作。在kernel/sys.c中我們實現294和295訊號調用的函數。如下圖所示,sys_hide和sys_unhide兩個函數主要功能是修改行程hide變數的值。

proc相關內核程式碼位於fs/proc/base.c中,在行程相關結構體中新聲明變數hide,通過發送信號量來修改hide的值,最後在base.c檔案proc_pid_readdir函數中將hide變數的值作為行程是否在proc檔案系統中體現的依據。

除此之外還有些零碎的步驟,查看上文中的原帖地址即可,不再贅述。

新內核編譯完成後本以為可以愉快的開始玩耍了,結果新內核根本無法啟動。通過各種修改啟動參數發現,內核報錯“kernel too old”,這就很尷尬了。再次站在巨人的肩膀上發現,確實是因為kernel too old。之前缺乏編譯老舊內核的經驗,現在才知道原來gcc調用的libc不是完全向下相容的,我們可以通過

file /lib/libc-*.*.so

來查看當前libc能够編譯的最低版本的內核,如下圖所示libc-2.5.so可以編譯最低到2.6.9版本的內核,如果編譯內核版本低於2.6.9的話就會產生kernel too old的報錯導致內核無法啟動。

綜上,我們的libc版本不可太高,又因為Demo中修改的是i386架構的內核源碼,所以我選擇的實驗環境為CentOS 5.11(32bit)。

至此,我們就可以成功安裝並啟動2.6.15版本內核了,然而事情並沒有結束。系統供外部行程使用的信號量僅有如下64個。

所以一般情况下我們的行程只能發出上圖這64種訊號,我們想要發出294和295號信號量就必須借助於與系統關係更密切的C語言程式完成。

然後通過執行命令

gcc hide.c -fPIC -shared -o hide.so 

將hide.c編譯為hide.so的動態連結程式庫。

以後我們如果有行程需要隱藏的話,只需要在程式碼裏調用hide.so中的hide函數即可,同樣unhide函數是他的逆過程。如下圖所示,在Python中import ctypes,使用它調用hide.so庫即可實現當前Python2.7行程的隱藏與恢復。

至此,已經實現了內核級別的行程隱藏,可以愉快地做一些想做而又怕被別人發現的事情了…

就跟Windows編譯程式是一樣的思路,Windows下程式編譯之後是一個可執行的檔案,Linux下呢,編譯內核的時候,一般也是從Git上把程式碼拖下來,是一個程式碼工程,編譯後,生成一個對應格式的檔案,這個時候該檔案在Linux下就跟其他檔案一樣,就是一個普通的檔案。如果你想要把編譯的這個內核在當前的系統中啟動起來的話,由於當前系統中已經有一個正在運行的內核了,一個思路是你可以設定Linux一個變數(類似於Windows的環境變數),將該變數指向這個新編譯好的內核檔案,然後這個時候再重啓當前Linux系統,系統啟動時會讀取那個變數的值,然後啟動新的內核。(實驗的時候建議在虛擬機器裏操作哦)

拓展閱讀

more

《linux隱藏進程- crux實現》

發佈日期:2010.11.26

連結:http://blog.csdn.net/billpig/article/details/6038330

《linux內核編譯過程的最終總結版》

發佈日期:2012.12.18

連結:http://blog.csdn.net/fjt19900921/article/details/8316481

網易小風景NO.1

不妨關注下,詩酒趁年華

小提示:長按二維碼識別關注