内核方法实现进程保护
编程板块很多文章都是讨论关于Ring0级的文章,其中印象最深的是2007年11期的一篇名为《Windows Rootkit开发初步》文章。这篇文章大致讲地是Rootkit实现进程隐藏,当时我受益匪浅。后来看到这期另外一篇文章名为《木马编程DIY之线程守护》这篇文章,提到了一个双进程实现进程守护的方法。不过他的引言里提到了Icesword的一种HOOK系统底层函数的方法,但是没有细讲。然后我查询很多资料加上自己的研究,试验成功了这个方法。代码原理和Rootkit文章的原理类似,不过我稍加改进更简洁明了,希望对大家学习驱动开发能有一定的帮助。原理分析
大家知道,如果想要结束一个进程,需要获得当前进程的访问权限,方法是先调用系统API函数OpenProcess打开进程。
HANDLE OpenProcess(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwProcessId
);
其中设置第一个参数为值PROCESS_ALL_ACCESS。而实际上OpenProcess这个API对应了内核的NtOpenProcess函数。这个我们可以用IceSword查看到,如图1所示,它个系统的SSDT表。我们更改NtOpenProcess的默认地址,就可以实现对NtOpenProcess函数的过滤了(这个原理和HOOK API原理类似)。当调用NtOpenProcess时,我们先判断是否为我们指定要保护的进程,如果不是,则不管它,如果是,则直接返回。这时调用OpenProcess的程序(因为程序调用的是OpenProcess在Kernel32.dll上的导出函数到ntdll.dll的NtOpenProcess函数,最后到内核的NtOpenProcess,具体信息可以查阅一些内核方面的资料)没有获得到正确的访问权限,当调用TerminateProcess结束进程的时候就会出错。
图1
步骤整理
第一步:修改SSDT表来实现对NtOpenProcess的挂钩。
第二步:通过自定义的NtOpenProcess函数过滤传递进来的PID(进程ID,用于标识进程,PID不会有重复值,一个进程一个,可能不连续)。
开发准备
首先我们需要DDK。我用的是Windows 2003的DDK,也有Windows XP/2000的DDK,不过Windows 2003的在Windows XP下一样可以使用。安装好后,在开始菜单里就找到相应的内容,如图2所示。选择后会出现一个控制台,进入到代码的目录后,使用Build命令就可以编译相应的文件了(选择Windows XP Free Build Environment 则可以生成发布版,也就是说给别人用的,Checked版本是调试版本,对方没有DDK则无法运行,这里随便选都可以,似乎没有影响),如图3所示。
图2
图3
驱动编译和一般的编译方法不太一样,需要一个source和一个makefile两个文件(都没有扩展名),两个文件指示了哪些文件是需要编译的文件以及编译后的一些信息。
makefile内容如下:
!INCLUDE $(NTMAKEENV)makefile.def
source内容如下
TARGETNAME=Protect
TARGETPATH=.sys
TARGETTYPE=DRIVER
SOURCES=Protect.c
其中Protect.c是源文件。
代码分析
下面我们就开始编写代码。先建立一个设备,这样就可以通过程序动态的控制要保护的PID,否则每次PID都会变,我们的程序就没有实际价值了。
以上就是一个标准的设备驱动的代码。这个代码定义了一个通讯命令 IOCTL_PROTECT_CONTROL,我们定义这个命令的作用就是传递进PID。下面我们修改部分代码,来实现SSDT的挂钩和进程保护。