SSDT HOOK

运行效果

先简单说一下SSDT HOOK。应用程序的API在使用的时候要调用系统的低层的API

那么系统如何找到对应的API呢?在系统里有一张表。

System Services Descriptor Table,系统服务描述符表。

在这个表里就有各种系统API的地址,我们只要把这些地址改成我们自己函数的地址。

那么结果大家可想而知了,系统就会调用我们的API了。道理就是这么简单。当然实现

起来也很简单。

说一下步骤

首先我们要定义一个SSDT的结构代码如下

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;

然后我们要定义一个自己的API函数,这个函数根据你要HOOK的API来

NTKERNELAPI NTSTATUS ZwTerminateProcess(IN HANDLE ProcessHandle OPTIONAL, IN NTSTATUS 

ExitStatus);

当然还要一个结构来保存要HOOK的API。为什么要保存,当然是为了恢复。:)他的结构如下

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

ExitStatus);
_ZwTerminateProcess Old_ZwTerminateProcess;

好了,下面我们要开始把SSDT里的API替换成我们的了。替换之前先把原先的API保存下。代码如下

	//找出旧函数地址并保存
	Old_ZwTerminateProcess =(_ZwTerminateProcess)(GetSystemFunc(ZwTerminateProcess));

#define GetSystemFunc(FuncName) KeServiceDescriptorTable.ServiceTableBase[*(PULONG)

((PUCHAR)FuncName+1)]

然后我们要改写了。当然系统不会那么随便就让我们来改写这个地址。它是受保护的只能读不能写。

那么我们怎么办呢?创建一个MDL来解决。代码如下

	//设置内存为可写
	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);

已经可以修改了那么我们要修改了。代码如下

HookOn( ZwTerminateProcess, NewZwTerminateProcess);

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

这样就把地址修改成我们的了,下面怎么处理自己看着办好了。我这里是仿止结束。

//通过ProcessHandle来获得当前要结束的进程的EPROCESS
	if (ObReferenceObjectByHandle

(ProcessHandle,GENERIC_READ,NULL,KernelMode,&SJMPROCESS,0) == STATUS_SUCCESS)
	{
		//如果要结束的是我们需要保护的进程,这里分两种情况
		if (ZHUPROCESS== SJMPROCESS)
		{
			if (ZHUPROCESS != PsGetCurrentProcess())
			{//情况一:当前进程不是我们所保护的进程
				//换句话说也就是其他进程试图结束我们所保护的进程,当然不能

让他结束
				nStatus = STATUS_ACCESS_DENIED;
			}

		}
	}

用完了当然要把它恢复,恢复代码如下

//卸载Hook
	UnHook( ZwTerminateProcess, Old_ZwTerminateProcess);

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

差点忘了 MDL也要恢复 呵呵 恢复代码如下

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

至此大致过程已经完了。

您可能喜欢下面几篇博文

发表评论

1 Comments.

  1. 挺复杂 咋只有用的命了

Leave a Reply



[ Ctrl + Enter ]

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word

CNXCT小组的博客 is Stephen Fry proof thanks to caching by WP Super Cache