聊一聊Linux下程序隱藏的常見手法及偵測手段
0x00.前言
程序隱藏是惡意軟體隱藏自身痕跡逃避系統管理人員發現的常用伎倆之一,當然,安全防護人員有時候也會使用到,比如隱藏蜜罐中的監控程序而不被入侵者覺察等。筆者也曾在多次安全應急響應經歷中遇到過多各式各樣的程序隱藏伎倆,瞭解程序隱藏的常見手法及發現手段是每一位安全運維工程師所應掌握的知識點。本文拋磚引玉,淺談我所瞭解的Linux下程序隱藏手段及發現技巧,也希望讀者能夠積極分享自己相關經驗與技巧。
0x01.我所瞭解的 Linux下程序隱藏手段及偵測方法
Linux 下程序隱藏手法大體上分為兩種,一種是基於使用者態隱藏;一種是直接操控核心進行隱藏。
一、基於使用者空間程序隱藏手法
1、偷樑換柱型
1)隱藏原理
道理很簡單,通過替換系統中常見的程序檢視工具(比如ps、top、lsof)的二進位制程式,導致原先檢視程序相關資訊的工具(ps、top、lsof等)都被調包了,當然看不到
2)防護手段
I、從乾淨的系統上拷貝這些工具的備份至當前系統,對比前後的輸出是否一致,不一致,則說明被替換了
II、檢測這些工具的hash值是否與系統初始化的時候值不一致,是,則說明被替換了
III、專業一點話,使用一些系統完整性檢查工具,比如tripwrie、aide等
IV、部署主機入侵檢查工具(比如ossec),監控系統檔案是否被替換,如有替換,則會報警記錄
2、HooK系統呼叫型
1)隱藏原理
先說下ps、top等工具的工作原理
以ps 工作原理為例說明這些程序資訊檢視工具的原理
我們知道/proc是一個虛擬檔案系統,是VFS的一個實現形式,/proc中包含了核心資訊,硬體資訊,程序資訊等,ps等工具就是通過分析/proc檔案系統中程序相關目錄的資訊獲取程序資訊彙總。HooK系統呼叫型的程序隱藏方式都是通過攔截或者迷惑ps等工具從/proc獲取分析結果的過程,而不是針對/proc/檔案系統生成本身。
ps 首先會呼叫openat 系統函式獲取/proc目錄的檔案控制代碼,然後呼叫系統函式 getdents 遞迴獲取/proc目錄下所有檔案資訊(包括子目錄),然後開始open函式開啟/proc/程序pid/stat,/proc/程序pid/status, /proc/程序pid/cmdline 檔案開始獲取程序資訊,然後列印給你看
攻擊者通過劫持getdents 等系統呼叫函式或libc中的readdir 函式,實現對特定程序名程序的隱藏,以達到程序隱藏目的
劫持getdents 等系統呼叫函式或libc中的readdir 函式等系統呼叫函式一般來說有3個途徑
I、修改核心呼叫,比如getdents 的原始碼
II、修改libc庫中readdir 函式的原始碼
III、利用環境變數LD_PRELOAD 或者配置ld.so.preload檔案 以使的惡意的動態庫先於系統標準庫載入,以達到架空系統標準庫中相關函式的目的,最終實現對特定程序的隱藏
這3個原理類似,III相對於I、II比較簡單,在此以III為例進行演示(劫持libc 中的readdir函式)
演示(利用LD_PRELOAD這個環境變數進行程序資訊隱藏),比如隱藏ping這個程序:
先在一個視窗執行ping
在另外一個視窗載入惡意動態庫,動態庫原始碼中對指定程序資訊程序了過濾
上文也提到這種HooK系統呼叫函式的程序隱藏方式只是hook了ps等工具從/proc 獲取資訊的過程,而沒有修改/proc/檔案系統本身,其實相關程序資訊的核心對映還在/proc中
自己寫個python小工具,直接讀取/proc中的內容,也能發現異常
其實ls 也是呼叫libc中的readdir函式,如果對上述惡意動態庫進行修該也可以實現對ls命令的劫持。
不過對於直接使用cat讀取檔案(linux下什麼東東都是檔案)內容獲取程序資訊的方式,劫持libc的readdir函式是沒用的,因為cat呼叫的是一系列lookup函式(需要對這一系列函式進行劫持,原理類似)
2)防護手段
I、檢查LD_PRELOAD環境變數是否有異常
II、檢查ld.so.preload 等配置檔案是否有異常
III、自己寫個python小工具,直接讀取/proc中的內容,對於ps等工具的結果,對不上,則存在被劫持可能
IV、使用sysdig(有開源版,可以監控ps等的呼叫過程,觀察是否有惡意動態庫被載入。strace有類似功能)或者prochunter(google 上search)
sysdig proc.name=ps
3、偽造程序名型
1) 隱藏原理
在惡意程式碼中通過設定具有迷惑性的程序名字,以達到躲避管理員檢查的目的
比如 ofollow,noindex" target="_blank">Tiny Shell文章 中介紹的Tiny shell 這款工具通過在原始碼中設定PROCESS_NAME為bash,以使得其執行後的程序名顯示為bash
另:也可利用bash的特性來更換程序的名字
exec -a 更換後的程序名 原來的執行命令
比如exec -a sysdig proc.name=ps &執行之後,程序名顯示為bash proc.name=ps
如果原來的執行命令沒有引數,則非常具有迷惑性
2)防護手段
找到可疑程序所在的/proc目錄,檢視exe的指向
可疑發現真正的程序是sysdig 觸發的
4、掛載覆蓋型
1)隱藏原理
利用mount —bind 將另外一個目錄掛載覆蓋至/proc/目錄下指定程序ID的目錄,我們知道ps、top等工具會讀取/proc目錄下獲取程序資訊,如果將程序ID的目錄資訊覆蓋,則原來的程序資訊將從ps的輸出結果中隱匿。
比如程序id為42的程序資訊:mount -o bind /empty/dir /proc/42
案例: http://www.freebuf.com/articles/network/140535.html
2)防護手段
cat /proc/$$/mountinfo 或者cat /proc/mounts 檢視是否有利用mount —bind 將其他目錄或檔案掛載至/proc下的程序目錄的
二、基於對核心空間修改進行程序資訊隱藏的手法
這一類的手法就比較高深了,基本上都算作rootkit了
1、劫持VFS檔案系統系列函式實現對/proc動態生成結果的干擾,從而實現對某些程序的隱藏。
我們知道/proc這個記憶體檔案系統是VFS的一個實現,如果在VFS介面層就進行程序過濾的話,我們在/proc目錄下根本找不到相關程序的目錄資訊,更別談ps 之類工具可以獲取了。VFS層中涉及到proc動態生成結果的有inode_operation 和 file_operations等系列函式集,通過劫持這些函式集,可以使得程序資訊無法通過檔案系統介面輸出給proc
2、劫持程序建立模組程式碼,根據條件設定選擇是否隱藏程序
案例: http://www.cnblogs.com/wacc/p/3674074.html
大致的意思就是在Linux程序管理之task_struct結構體增加程序隱藏與否標記
程序建立程式碼模組中根據設定的程序隱藏比較選擇是否隱藏程序,如果為隱藏標記,則刪除/proc檔案系統中該程序的相關目錄項,直接在核心中就把指定程序給過濾了,使用者態根本查不到
對於1)和2)這兩種場景比較棘手,防護手段如下
I、查下核心是否被重新編譯替換
II、lsmod是否有新核心模組加入
III、檢視機入侵檢查系統的相關告警
0x02. 總結
Linux下程序隱藏的手法不會僅限於本文提到的這些,本文提到也只是冰山一角,淺談而已。筆者希望此文能引起更多人的關注與討論,希望各位大牛多多分享自己的經驗與奇淫技巧。筆者水平有限,文中定有不足之處,還望各位斧正。
0x03. 參考
https://github.com/hschen0712/process-hiding
http://tcspecial.iteye.com/blog/2361998
http://www.techweb.com.cn/network/system/2016-12-21/2457492.shtml
https://www.jb51.net/LINUXjishu/347787.html
http://blog.chinaunix.net/uid-26585427-id-5077452.html
http://www.voidcn.com/article/p-yfrjbuvq-pz.html
https://unix.stackexchange.com/questions/280860/how-to-hide-a-specific-process