S.l.e!ep.¢%

像打了激速一样,以四倍的速度运转,开心的工作
简单、开放、平等的公司文化;尊重个性、自由与个人价值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

CsrssWalker学习笔记(附源代码)

Posted on 2009-11-18 15:48 S.l.e!ep.¢% 阅读(299) 评论(0)  编辑 收藏 引用 所属分类: RootKit
CsrssWalker学习笔记(附源代码)
2009年06月24日 星期三 20:02
原创】CsrssWalker学习笔记(附源代码)

标 题: 【原创】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进程都进行处理。就说这么多了,具体地看代码吧~~

上传的附件
文件类型: rar CsrssWalker_Achillis_Src.rar (34.0 KB, 98 次下载) [谁下载?]

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理