標 題:
【原創】CsrssWalker學習筆記(附源代碼)
作 者:
achillis
時 間: 2009-05-24,09:35
鏈 接: http://bbs.pediy.com/showthread.php?t=89708
學習了一下古老的CsrssWalker,寫點筆記~~
在Csrss.exe中,保存著所有Win32子系統進程的進程信息,這些信息以鏈表的形式保存。
正常情況下,每一個新創建的進程都會通知Csrss.exe,Csrss.exe接收這些信息然后保存起來,所以遍歷這個鏈表就可以得到所有Win32子系統進程的信息。
首先就是找鏈表頭了,鏈表頭為CsrssRootProcess,在CSRSRV.DLL導出的函數中有對CsrssRootProcess的操作,因此可以通過CSRSRV.DLL的導出函數找到CsrssRootProcess。
比較方便一點的,是從CsrLockProcessByClientId中找到CsrssRootProcess.
代碼:
mov????? edx, [ebp+arg_4]
and????? dword ptr [edx], 0
mov????? esi, dword_75AA891C ; Base=75AA0000
add????? esi, 8
mov????? [ebp+arg_4], 0C0000001h
75AA891C處就是CsrssRootProcess的指針了,這個指針的值可以通過特征匹配找到,具體請參考代碼。讀取其內容,得到CsrssRootProcess=0x001629C0(這個只是我的系統上的)
從這里讀就可以得到CsrssRootProcess的內容了,然后遍歷Link即可
涉及到的一些數據結構在CsrssStruct.h中。
進程信息的結構如下:
代碼:
typedef struct _CSR_PROCESS
{
???? CLIENT_ID ClientId; //這里可以得到進程PID和主線程TID
???? LIST_ENTRY ListLink; //就是這個鏈表
?? LIST_ENTRY ThreadList;
???? struct _CSR_PROCESS *Parent;
???? PCSR_NT_SESSION NtSession;
???? ULONG ExpectedVersion;
???? HANDLE ClientPort;
???? ULONG_PTR ClientViewBase;
???? ULONG_PTR ClientViewBounds;
???? HANDLE ProcessHandle;
???? ULONG SequenceNumber;
???? ULONG Flags;
???? ULONG DebugFlags;
???? CLIENT_ID DebugCid;
???? ULONG ReferenceCount;
???? ULONG ProcessGroupId;
???? ULONG ProcessGroupSequence;
???? ULONG fVDM;
???? ULONG ThreadCount;
???? ULONG PriorityClass;
???? ULONG Reserved;
???? ULONG ShutdownLevel;
???? ULONG ShutdownFlags;
???? PVOID ServerData[];
} CSR_PROCESS, *PCSR_PROCESS;
但是因為這不是在當前進程中,所以每次都要先讀取出來,遍歷時與普通的遍歷雙鏈表操作稍有差別,但是也很容易實現。
具體的步驟為:
1
.找到Csrss.exe進程(這個很簡單,Vista要注意有不止一個Csrss進程)
2.遍歷Csrss.exe中的模塊列表,找到CSRSRV.DLL的基址。
3.在CSRSRV.DLL中根據導出函數CsrLockProcessByClientId找CsrssRootProcess指針
4.構建當前進程名稱列表,為輸出作準備
5.根據CsrssRootProcess指針的地址,從Csrss.exe進程中讀取和遍歷每個進程的信息并輸出
在Csrss.exe中同樣還保存著所有Win32線程的信息,由于線程數目較多,Csrss中采用Hash表的形式來保存線程信息。同樣從CSRSRV.DLL的導出函數CsrLockThreadByClientId可以得到CsrThreadHashTable的地址,這是一個Hash表,定義為:
代碼:
LIST_ENTRY CsrThreadHashTable[256];
Hash算法為:
#define CsrHashThread(t) \
???? (HandleToUlong(t)&(256 - 1))
????
很簡單的算法,
查找CsrThreadHashTable的方法及遍歷方法與前面遍CsrssRootProcessLink基本相同,不多說。這部分我并未在代碼中實現,有興趣的自己寫一寫吧,很簡單。
對于Vista等較新的系統,由于Session隔離,系統中會有不止一個Csrss進程,這樣就需要對這幾個Csrss進程都進行處理。就說這么多了,具體地看代碼吧~~