涨姿势系列之——内核环境下花式获得CSRSS进程id

发布者:Ox9A82
发布于:2016-06-02 15:34

这个是翻别人的代码时看到的,所以叫涨姿势系列。作者写了一个获取CSRSS进程PID的函数,结果我看了好久才看懂是这么一个作用。先放上代码

 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;

就是说每个句柄项都被解释成

  • 句柄所属进程的PID
  • 句柄对应对象的类型
  • 句柄值(数字)
  • 句柄对应的对象指针

这个函数查到句柄后,匹配所有的port对象的句柄。然后把这些句柄dump到本进程(因为只有这样才可以操作句柄),用ZwQueryObject查询port对象的名称,匹配\\Windows\\ApiPort,而这个port对象正是csrss进程创建的,也就说只有csrss进程的句柄表中才会有这个句柄,这样就实现了查找的csrss进程的目的。

其实我觉得不需要把句柄复制到自己的进程中了,因为已经有对象的指针了,可以直接获取对象名了。这个做法对我来说比较新鲜,即用句柄来查找进程。


声明:该文观点仅代表作者本人,转载请注明来自看雪