【舊文章搬運】遍歷EPROCESS中的ActiveProcessLinks列舉程序
原文發表於百度空間,2008-7-25
==========================================================================
前面對PEB的相關結構和其中的重要成員進行了分析和學習,現在開始真正進入核心,學習核心中的一些結構.
這個EPROCESS結構在ntddk.h中有定義,但是並未給出具體的結構,因此要得到EPROCESS中一些重要的成員變數,只能通過偏移的方法,比如PID,ImageName等.這些偏移可以在Windbg中dt _EPROCESS得到,但是不公開感覺還是不爽,而且這東西在不同的系統版本中不一樣,如果要相容的話,就必須先判斷作業系統版本.
在此程式中用到的相關偏移如下(XP系統):
#define EPROCESS_ACTIVELIST_OFFSET 0x88 //活動程序鏈 #define EPROCESS_PID_OFFSET 0x84 //PID了 #define EPROCESS_IMAGENAME_OFFSET 0x174 //映像名稱 #define EPROCESS_FLINK_OFFSET 0x88 //雙鏈表的前向指標 #define EPROCESS_BLINK_OFFSET 0x8C //雙鏈表的後向指標
由於是第一次寫驅動,有些寫法還不太清楚,下面的程式碼參考了別人的一些.
VOID ShowEPROCESS(void) { DWORD EProcess,FirstEProcess; LIST_ENTRY* ActiveProcessLinks; DWORD pid,dwCount=0; PUCHAR pImage; PPROCESS_INFO ProcessInfo={0}; EProcess=FirstEProcess=(DWORD)PsGetCurrentProcess(); //pid=*(DWORD*)((char*)EProcess+EPROCESS_PID_OFFSET); __try { while( EProcess!= 0) { dwCount++; pid= *( (DWORD*)( EProcess + EPROCESS_PID_OFFSET ) ); pImage= (PUCHAR)( EProcess + EPROCESS_IMAGENAME_OFFSET ) ; DbgPrint ( "[Pid=%8d] EProcess=0x%08X %s\n", pid, EProcess, pImage) ; ActiveProcessLinks = (LIST_ENTRY*) ( EProcess + EPROCESS_FLINK_OFFSET ) ; EProcess = (DWORD)ActiveProcessLinks->Flink - EPROCESS_FLINK_OFFSET ; if ( EProcess == FirstEProcess ) break ; } DbgPrint ( "ProcessCount = %d\n", dwCount ) ; } __except ( 1 ) { DbgPrint ( "EnumProcessList exception !" ) ; } }
上面程式碼的實現思想很簡單,因為系統中所有程序的EPROCESS通過它的一個成員變ActiveProcessLinks這個雙向連結串列連線起來,遍歷連結串列的操作很簡單,每得到一個ActiveProcessLinks,取其地址,再減去它離EPROCESS結構入口處的偏移,就可以得到EPROCESS的地址了,然後就可以輕鬆得到想要的成員變數.
下面的結果圖:
結果比實際程序數要多,表明其中有一部分其實是殭屍程序,已經死掉卻還在程序鏈上掛著.
由此我感覺到,這個程序鏈並不是那麼嚴格,因此也就可以把正常程序從鏈上摘掉,這為下面的隱藏程序實現提供了基礎.
至於對抗這種檢測方法,很簡單,DKOM把想要隱藏的程序從活動程序鏈上摘掉即可.
實現原理如下圖:
圖中,著色部分即是LIST_ENTRY結構,綠色指標Flink指向前一個,黃色指標Blink指向後一個.
正常的連線情況如藍線所示,若要摘要某個結點,修改該結點前後兩個結點的指標即可,修改示意如紅線所示.同時,還要把被隱藏的程序的EPROCESS中的兩個指標都修改為NULL.
這樣,通過遍歷雙鏈表的方法就找不到這個程序了,這就是最簡單的DKOM法隱藏程序.