转载自http://blog.csdn.net/yushiqiang1688/article/details/5209597windows
最近要作一个进程监控的程序,功能很简单,就是建立和退出进程的时候,能触发咱们的事件。函数
首先的第一想法,是Hook ZwCreateProcess,结果调试的时候发现,不少建立进程的动做,并无经过这个API执行,因此天然就是没办法监控进程的建立,因而回到本质,从建立进程的动做过程来分析,建立新的进程,其大体要经历如下步骤:.net
(1)打开可执行文件,以FILE_EXECUTE权限打开;线程
(2)将可执行文件加载到内存空间;调试
(3)进程的活动结构将被建立,如(EPROCESS,KPROCESS和PEB结构);blog
(4)为新建立的进程分配地址空间;进程
(5)为进程的主线程建立线程活动结构,如(ETHREAD,KTHREAD和TEB结构);事件
(6)主线程的栈将会被分配;内存
(7)进程的主线程的上下文将被建立;原型
(8)通知windows子系统;
以上总结下来,无非有下面几种办法获取进程建立的消息:
(1)HOOK ZeCreateSection,建立虚拟内存块的时候,根据传入的文件句柄,获取句柄对应的文件名是否为exe可执行文件;
(2)Hook NtReadVirtualMemory,为新建立的进程分配地址空间等操做时,须要读取进程空间,这样捕获,就可以获取进程的建立动做;
(3)经过windows提供的回调函数,注册回调事件;
方法对比:
(1)该方法可以准确的获取进程建立的操做,可是因为此时进程并无建立完毕,一些进程的基本结构尚未建立,因此进程ID等信息没法获取;
(2)该方法可以获取进程的建立操做,但不许确。由于除了进程的建立会调用此操做外,人为的一些操做,例如某外部应用程序想读取另外一个进程的内存空间,也会调用这个函数,这时候也会有事件响应,所以结果不许确;
(3)第三种方法更直观和简单。由于采用的回调事件,并不直接HOOK API,所以更稳定。
重点分析第三种回调方法。
注册回调事件,是经过PsSetCreateProcessNotifyRoutine来实现的,其函数原型以下:
NTSTATUS PsSetCreateProcessNotifyRoutine(
IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
IN BOOLEAN Remove
);
NotifyRoutine就是注册的回调函数,当有进程建立的时候,就会调用这个NotifyRoutine对应的函数,其函数定义原型以下:
VOID (*PCREATE_PROCESS_NOTIFY_ROUTINE) (
IN HANDLE ParentId,
IN HANDLE ProcessId,
IN BOOLEAN Create
);
其中,ParentId是父进程ID,ProcessId为子进程ID,而Create表示是建立进程仍是结束进程,其中True表示建立进程,False表示结束进程。
经过这个函数,咱们就可以完成进程建立和退出的监控,首先调用PsSetCreateProcessNotifyRoutine注册进程监控回调函数,而后在回调函数里面,判断Create参数,分别处理进程建立和退出操做。
其它相似的函数还有PsSetLoadImageNotifyRoutine,PsSetCreateThreadNotifyRoutine等。