1 HANDLE GetCsrPid()
2 {
3 HANDLE Process, hObject;
4 HANDLE CsrId = (HANDLE)0;
5 OBJECT_ATTRIBUTES obj;
6 CLIENT_ID cid;
7 UCHAR Buff[0x100];
8 POBJECT_NAME_INFORMATION ObjName = (PVOID)&Buff;
9 PSYSTEM_HANDLE_INFORMATION_EX Handles;
10 ULONG r;
11
12 Handles = GetInfoTable(SystemHandleInformation);
13
14 if (!Handles) return CsrId;
15
16 for (r = 0; r < Handles->NumberOfHandles; r++)
17 {
18 if (Handles->Information[r].ObjectTypeNumber == 21) //Port object
19 {
20 InitializeObjectAttributes(&obj, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
21
22 cid.UniqueProcess = (HANDLE)Handles->Information[r].ProcessId;
23 cid.UniqueThread = 0;
24
25 if (NT_SUCCESS(NtOpenProcess(&Process, PROCESS_DUP_HANDLE, &obj, &cid)))
26 {
27 if (NT_SUCCESS(ZwDuplicateObject(Process, (HANDLE)Handles->Information[r].Handle,NtCurrentProcess(), &hObject, 0, 0, DUPLICATE_SAME_ACCESS)))
28 {
29 if (NT_SUCCESS(ZwQueryObject(hObject, ObjectNameInformation, ObjName, 0x100, NULL)))
30 {
31 if (ObjName->Name.Buffer && !wcsncmp(L"\\Windows\\ApiPort", ObjName->Name.Buffer, 20))
32 {
33 CsrId = (HANDLE)Handles->Information[r].ProcessId;
34 }
35 }
36
37 ZwClose(hObject);
38 }
39
40 ZwClose(Process);
41 }
42 }
43 }
44
45 ExFreePool(Handles);
46 return CsrId;
47 }
作者幹了以下這幾件事:執行ZwQuerySystemInfo函式的第16號功能,這個第16號功能就是SystemHandleInformation,作用是獲取控制程式碼表。之前沒用過這個功能號,MSDN上的頁面也找不到了,找不到頁面大概是因為這個函式現在已經不被支援了吧(Win8)。搜了半天找到了這個功能的結構
typedef struct _SYSTEM_HANDLE_INFORMATION_EX
{
ULONG NumberOfHandles;
SYSTEM_HANDLE_INFORMATION Information[1];
}SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG ProcessId;
UCHAR ObjectTypeNumber;
UCHAR Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
}SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
這個函式查到控制程式碼後,匹配所有的port物件的控制程式碼。然後把這些控制程式碼dump到本程式(因為只有這樣才可以操作控制程式碼),用ZwQueryObject查詢port物件的名稱,匹配\\Windows\\ApiPort,而這個port物件正是csrss程式建立的,也就說只有csrss程式的控制程式碼表中才會有這個控制程式碼,這樣就實現了查詢的csrss程式的目的。