首页
论坛
课程
招聘
[原创]扫盲贴,HOOK SSDT 短文一篇。
2008-12-6 23:01 24026

[原创]扫盲贴,HOOK SSDT 短文一篇。

2008-12-6 23:01
24026
//author:梧桐
//转载请注明出处

------------------------很不华丽的分割线------------------------------------------------------

本文章仅供那些在驱动开发门外徘徊的程序爱好者参考和学习,大牛就绕过吧,
如有错误的地方,还请多多指出,不胜感激。

------------------------很不华丽的分割线------------------------------------------------------

      对于Driver 一词儿,我想大家都不陌生,它是工作在ring0下的,正是因为如此,它不不能够快速上手的,更多的时候你要熟悉它的技术资料和接口,还要熟悉底层工作的原理,一不小心搞个BSOD,那是会非常郁闷的。

    好了,现在让我们步入正题,首先确认你已经安装好了DDK(学习驱动开发,推荐WINXP DDK 2600、 Windows XP,  VS2003),配置好了你的开发环境(DDK Wizard),在VS20003里添加WINDDK路径。

    打开VS2003,Tools选项,选取 Options(如下图):



    然后,我们找到 Projects(工程),选取VC++ Directories,添加WINDDK路径:


    配置好这些环境以后,我们开始与驱动的亲密接触吧。

    先来建立一个驱动的工程:



    那些默认的选项,全部取消掉:



    接着点 Finish ,删除 Header Files、Resource Files,此时,DDK Wizard 已经为我们建立了一套Driver模板了,但细看,是不是感觉非常非常的乱?

    OK,我们把它K掉,现在我们自己来打造一个简单的入口点。

   
#include "ntddk.h"

//Unload
VOID UnLoad(IN PDRIVER_OBJECT DriverObject)
{
   DbgPrint("UnLoad Driver.\n");
}

//EntryPoint.
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, 
					 IN PUNICODE_STRING RegistryPath)
{
	DriverObject->DriverUnload = UnLoad;
	//TODO
	return STATUS_SUCCESS;
}


    在 DriverName.WXP上点Build,看看objchk\i386目录下产生的Sys文件,OK,Cool吧,当然,我们这个驱动连任何功能都没有的,Cool是很Cool,就是Cool得没内涵了,那么我们来实现点什么功能呢,好吧,让我们来对SSDT挂钩一下吧。

    要挂钩SSDT,就必须先要由内核到处一个KeServiceDescriptorTable,那么我们还要先定义一个KeServiceDescriptorTable类型的的结构体:

typedef struct ServiceDescriptorEntry
{
        unsigned int *ServiceTableBase;
        unsigned int *ServiceCounterTableBase; //Used only in checked build
        unsigned int NumberOfServices;
        unsigned char *ParamTableBase;
} SSDTEntry;


    定义了KSDT的结构,那么我们想想要HOOK那个函数呢,好吧,就以ZwTerminateProcess为例,我们开动,首先定义一个ZwTerminateProcess函数结构,函数原型:

ZwTerminateProcess(
				IN HANDLE ProcessHandle OPTIONAL, 
				IN NTSTATUS ExitStatus
				); 

结构定义:

typedef NTSTATUS(*_ZwTerminateProcess)(
								IN HANDLE ProcessHandle OPTIONAL,
								IN NTSTATUS ExitStatus
								);


    我们要HOOK ZwTerminateProcess,那么我们是不是要先找出它在KSDT中的位置呢,没错,那么我们来定义一个通过SSDT服务号得到函数地址的宏以达到我们的目的:

#define	GetSystemFunc(FuncName) KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PUCHAR)FuncName+1)]; 


    想要达到改写SSDT的目的,那么首先要解决的是内存保护机制的问题,众所周知,Windows的某些版本对内存区域启用了写保护的功能,在XP和2003中更为常见,SSDT是只读的,那怎么办呢?

    有的网友此刻估计已经明白了。

    没错,就是 Memory Descriptor List,简称 MDL。有的同学可能会问了,MDL究竟是个什么东西呢?从字面意思看,不难理解,内存描述符列表。MDL包含了内存区域的起始、拥有者proc、字节数、标记等。OK,我们需要先定义一个MDL的指针。

PMDL MDLSystemCall;


    定义了MDL的指针以后,我们要通过MAPPED系列的参数来使内存拥有可写性,然后锁定内存中的MDL,那么我们就要定义一个PVOID的指针,来供MmMap操作。

   
PVOID *MappedSCT;


    代码片段:
MDLSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4);
if(!MDLSystemCall)
  return STATUS_UNSUCCESSFUL;


    那么,建立了MDL,是不是该填充一下页数组啊?

    对的,没错。

   
MmBuildMdlForNonPagedPool(MDLSystemCall);
MDLSystemCall->MdlFlags = MDLSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA; //可写
MappedSCT = MmMapLockedPages(MDLSystemCall, KernelMode);


    我们转入HOOK话题,继续。

    刚才我们已经定义了 ZwTerminateProcess 的结构。

   
Old_ZwTerminateProcess = (_ZwTerminateProcess)(GetSystemFunc(ZwTerminateProcess));


    获取没被HOOK之前的ZwTerminateProcess在KSDT中的索引,保存。

    那么下一步呢,就是干掉他了,替换为我们的函数,那么我们是不是要构造一个自己的函数过程呢,恩,没错。

   
NTSTATUS NewZwTerminateProcess(
						    IN HANDLE ProcessHandle OPTIONAL, 
								IN NTSTATUS ExitStatus
								)
{
  //TODO
	return STATUS_SUCCESS;
}


    在过程里要怎么玩,全看你自己了。

    下面就是替换函数了,修改SSDT中函数地址指向的位置,下面是宏定义:

#define GetIndex(_foo) *(PULONG)((PUCHAR)_foo+1)
#define HookOn(_Old,_New) InterlockedExchange((PLONG)&MappedSCT[GetIndex(_Old)] ,(LONG)_New)


    代码片段:

   
MDLSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4);
if(!MDLSystemCall)
  return STATUS_UNSUCCESSFUL;
MmBuildMdlForNonPagedPool(MDLSystemCall);
MDLSystemCall->MdlFlags = MDLSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA; //可写
MappedSCT = MmMapLockedPages(MDLSystemCall, KernelMode);
HookOn(ZwTerminateProcess, NewZwTerminateProcess);
return STATUS_SUCCESS;


完整代码:

///////////////////////////////////////////////////////////////////////////////
///
/// Copyright (c) 2008 - <company name here>
///
/// Original filename: NtHook.c
/// Project          : NtHook
/// Date of creation : 2008-11-20
/// Author(s)        : 梧桐
///
/// Purpose          : <description>
///
/// Revisions:
///  0000 [2008-11-20] Initial revision.
///
///////////////////////////////////////////////////////////////////////////////
#include "ntddk.h"

#pragma pack(1)
typedef struct ServiceDescriptorEntry
{
        unsigned int *ServiceTableBase;
        unsigned int *ServiceCounterTableBase; //Used only in checked build
        unsigned int NumberOfServices;
        unsigned char *ParamTableBase;
} SSDTEntry;
__declspec(dllimport)  SSDTEntry KeServiceDescriptorTable;

#pragma pack()

NTKERNELAPI NTSTATUS ZwTerminateProcess(
						    IN HANDLE ProcessHandle OPTIONAL, 
								IN NTSTATUS ExitStatus
								); 


typedef NTSTATUS(*_ZwTerminateProcess)(
								IN HANDLE ProcessHandle OPTIONAL,
								IN NTSTATUS ExitStatus
								);
_ZwTerminateProcess Old_ZwTerminateProcess;


#define GetSystemFunc(FuncName) KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PUCHAR)FuncName+1)]
PMDL  MDSystemCall;
PVOID *MappedSCT;

#define GetIndex(_Function) *(PULONG)((PUCHAR)_Function+1)

#define HookOn(_Old, _New)  \
       (PVOID) InterlockedExchange( (PLONG) &MappedSCT[GetIndex(_Old)], (LONG) _New)

#define UnHook(_Old, _New)  \
       InterlockedExchange( (PLONG) &MappedSCT[GetIndex(_Old)], (LONG) _New)


NTSTATUS NewZwTerminateProcess(
						    IN HANDLE ProcessHandle OPTIONAL, 
								IN NTSTATUS ExitStatus
								)
{
	return STATUS_SUCCESS;
}


//Unload
VOID UnLoad(IN PDRIVER_OBJECT DriverObject)
{
   DbgPrint("UnLoad Driver.\n");
	 //卸载Hook
   UnHook( ZwTerminateProcess, Old_ZwTerminateProcess);

   //解锁、释放MDL
   if(MDSystemCall)
   {
      MmUnmapLockedPages(MappedSCT, MDSystemCall);
      IoFreeMdl(MDSystemCall);
   }
}

//EntryPoint.
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, 
					 IN PUNICODE_STRING RegistryPath)
{
	DriverObject->DriverUnload = UnLoad;
	
	//找出旧函数地址并保存
	Old_ZwTerminateProcess =(_ZwTerminateProcess)(GetSystemFunc(ZwTerminateProcess));

	MDSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4);
	if(!MDSystemCall)
		return STATUS_UNSUCCESSFUL;
	MmBuildMdlForNonPagedPool(MDSystemCall);
	MDSystemCall->MdlFlags = MDSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
	MappedSCT = MmMapLockedPages(MDSystemCall, KernelMode);

	//安装HOOK
	HookOn( ZwTerminateProcess, NewZwTerminateProcess);
	return STATUS_SUCCESS;
}


工程附件:http://xlick.3video.cn/1.zip

[注意] 欢迎加入看雪团队!base上海,招聘安全工程师、逆向工程师多个坑位等你投递!

上传的附件:
  • 1.png (8.77kb,703次下载)
  • 2.png (57.43kb,700次下载)
  • 3.png (16.67kb,697次下载)
  • 4.png (63.83kb,701次下载)
收藏
点赞0
打赏
分享
最新回复 (42)
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
eopenfang 活跃值 2008-12-6 23:09
2
0
学到了。。很实用。很好的表述。
雪    币: 564
活跃值: 活跃值 (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lixupeng 活跃值 2008-12-6 23:52
3
0
不太懂收藏了
雪    币: 273
活跃值: 活跃值 (18)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
popeylj 活跃值 6 2008-12-7 00:01
4
0
赞一个 的确对新人很有帮助
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ltKOF 活跃值 2008-12-7 00:11
5
0
学习了下,不过不太懂,先收藏
雪    币: 321
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
haras 活跃值 2008-12-7 00:47
6
0
支持,可惜当初我学驱动时没有这帖
要是早点出来,我可能节省了很多时间了。
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
gniy 活跃值 2008-12-7 01:59
7
0
楼主辛苦 文章收藏了
雪    币: 230
活跃值: 活跃值 (33)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
sxniao 活跃值 2008-12-7 02:08
8
0
就冲着你是我大哥的份上,我也要**
雪    币: 221
活跃值: 活跃值 (11)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
梧桐 活跃值 1 2008-12-7 18:44
9
0
呵呵,自己摸索可以积累很多经验的啊
雪    币: 6
活跃值: 活跃值 (11)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
benyanwk 活跃值 3 2008-12-7 19:00
10
0
LZ在线的吧...我需要和你联系...极需要的那种...可否请你查看一下...邮件...
雪    币: 266
活跃值: 活跃值 (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
thdzhqg 活跃值 2 2008-12-7 22:40
11
0
学习了,顶一下
雪    币: 221
活跃值: 活跃值 (11)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
梧桐 活跃值 1 2008-12-10 10:24
12
0
邮件给您回了,在帖子里这样是被禁止的,下不为例哦~~
雪    币: 200
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
细心 活跃值 2008-12-10 10:33
13
0
lz很强学习了
雪    币: 193
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
vcvip 活跃值 2008-12-10 14:06
14
0
支持楼主的原创!
雪    币: 432
活跃值: 活跃值 (509)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
xss 活跃值 4 2008-12-11 20:32
15
0
图文并茂,很有帮助
雪    币: 221
活跃值: 活跃值 (11)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
梧桐 活跃值 1 2008-12-14 13:46
16
0
   感觉这篇好像发错地方了。。
雪    币: 25
活跃值: 活跃值 (11)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
塞外牧羊 活跃值 2008-12-15 12:14
17
0
楼主可否给一个最新的DDK下载地址,我用的是VS2005和VS2008
雪    币: 1259
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
stu 活跃值 2008-12-15 14:43
18
0
做个记号先,以后再看。
雪    币: 231
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yese 活跃值 2008-12-15 18:23
19
0
  收藏了,好东西,谢谢LZ!
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
阳光味道 活跃值 2008-12-16 22:14
20
0
很感谢搂主的扫盲帖,但要看懂还是需要一定的基础的
呵呵
2个月钱,让我看我就看不懂
现在重新学习,另有所获,呵呵
雪    币: 1
活跃值: 活跃值 (88)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
美丽破船 活跃值 5 2008-12-16 22:19
21
0
这么好的文章,为什么才发现哦~~`
太失败了~~~
雪    币: 411
活跃值: 活跃值 (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
kmlch 活跃值 2008-12-17 08:48
22
0
好贴啊,收藏。
雪    币: 221
活跃值: 活跃值 (11)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
梧桐 活跃值 1 2008-12-17 15:28
23
0
google搜索一下,还是比较多的。
雪    币: 376
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Music小冷 活跃值 2008-12-30 03:25
24
0
正要学这个,谢谢楼主~
目前正在寻找VS2003下载中。。。

不过楼主的几张图都看不到,可否补一下啊?
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ttbaby 活跃值 2008-12-30 14:26
25
0
先收藏 学习ing
游客
登录 | 注册 方可回帖
返回