SSDT Hook的两种方式

#ifndef _SSDT_H_
#define _SSDT_H_

#include <ntifs.h>

typedef struct _SERVICE_DESCRIPTOR_TABLE
{
	PULONG ServiceTable;
	PULONG CounterTable;
	ULONG TableSize;
	PUCHAR ArgumentTable;
}SERVICE_DESCRIPTOR_TABLE, *PSERVICE_DESCRIPTOR_TABLE;

//SSDT表
extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;

VOID WPOFF();
VOID WPON();
VOID Cr0SSDTHook(int *Index, ULONG_PTR *ul_save_real_address, ULONG_PTR ul_hook_address);
VOID Cr0RemoveHook(int *Index, ULONG_PTR ul_save_real_address);
NTSTATUS MdlSSDTHook(ULONG_PTR ul_real_function, ULONG_PTR hook_function_addr, ULONG_PTR *ul_save_real_function_addr);
NTSTATUS MdlRemoveSSDTHook(ULONG_PTR ul_real_function, ULONG_PTR hook_function_addr, ULONG_PTR *ul_save_real_function_addr);

PMDL pmdl_system_call;
PVOID *pdword_mapped_table;

/*
kd> u nt!ZwOpenProcess
nt!ZwOpenProcess:
83e5262c b8be000000      mov     eax,0BEh
83e52631 8d542404        lea     edx,[esp+4]
83e52635 9c              pushfd
83e52636 6a08            push    8
83e52638 e8b1190000      call    nt!KiSystemService (83e53fee)
83e5263d c21000          ret     10h
*/
//SYSCALL_INDEX用来获取服务号,在这里获取的是0xBE
#define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function + 1)

//交换,并保存原始数据
#define HOOK_SYSCALL(_Function, _Hook, _Orig) \
	_Orig = (ULONG_PTR)InterlockedExchange((PLONG) &pdword_mapped_table[SYSCALL_INDEX(_Function)], (LONG)_Hook)

//交换,不必保留原始数据
#define UNHOOK_SYSCALL(_Function, _UNHook) \
	InterlockedExchange((PLONG) &pdword_mapped_table[SYSCALL_INDEX(_Function)], (LONG)_UNHook)

#endif
#include "SSDT.h"

//禁用WP写保护
VOID WPOFF()
{
	__asm
	{
		cli
		mov eax, cr0
		and eax, not 10000h
		mov cr0, eax
	}
}

//开启WP写保护
VOID WPON()
{
	__asm
	{
		mov eax, cr0
		or eax, 10000h
		mov cr0, eax
		sti
	}
}

//CR0方式  Hook
//Index  ssdt中服务号
//ul_save_real_address 用来保存原始地址
//ul_hook_address 要写入ssdt表中的地址,也就是过虑函数的地址
VOID Cr0SSDTHook(int *Index, ULONG_PTR *ul_save_real_address, ULONG_PTR ul_hook_address)
{
	ULONG_PTR ul_address_temp;
	ul_address_temp = (ULONG)KeServiceDescriptorTable->ServiceTable + *Index * 4;

	if(ul_address_temp)
	{
		*ul_save_real_address = *((ULONG *)ul_address_temp);

		WPOFF();

		*((ULONG *)ul_address_temp) = ul_hook_address;

		WPON();
	}
}

//CR0方式 RemoveHook
//参数同上
VOID Cr0RemoveHook(int *Index, ULONG_PTR ul_save_real_address)
{
	ULONG_PTR ul_address_temp;
	ul_address_temp = (ULONG)KeServiceDescriptorTable->ServiceTable + *Index * 4;

	if(ul_address_temp)
	{
		WPOFF();

		*((ULONG *)ul_address_temp) = ul_save_real_address;

		WPON();
	}
}

NTSTATUS MdlSSDTHook(ULONG_PTR ul_real_function, ULONG_PTR hook_function_addr, ULONG_PTR *ul_save_real_function_addr)
{
	//创建一个内存描述表
	pmdl_system_call = MmCreateMdl(NULL, KeServiceDescriptorTable->ServiceTable, KeServiceDescriptorTable->TableSize * sizeof(ULONG_PTR));
	if(!pmdl_system_call)
		return STATUS_UNSUCCESSFUL;
	//将MDL描述的物理页面集合映射到系统地址空间
	MmBuildMdlForNonPagedPool(pmdl_system_call);
	//修改属性
	pmdl_system_call->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA;
	//锁定内存
	pdword_mapped_table = (PVOID *)MmMapLockedPages(pmdl_system_call, KernelMode);

	if(pdword_mapped_table)
	{
		HOOK_SYSCALL(ul_real_function, hook_function_addr, *ul_save_real_function_addr);
	}
	return STATUS_SUCCESS;
}

NTSTATUS MdlRemoveSSDTHook(ULONG_PTR ul_real_function, ULONG_PTR hook_function_addr, ULONG_PTR *ul_save_real_function_addr)
{
	UNHOOK_SYSCALL(ul_real_function, *ul_save_real_function_addr);

	if(pmdl_system_call)
	{
		//解除锁定
		MmUnmapLockedPages(pdword_mapped_table, pmdl_system_call);
		//释放内存描述表
		IoFreeMdl(pmdl_system_call);
		return STATUS_SUCCESS;
	}
	return STATUS_UNSUCCESSFUL;
}
/***************************************************************************************
* AUTHOR : L0g1n
* DATE   : 2013-11-28
* MODULE : SSDTHook.H
*
* IOCTRL Sample Driver
*
* Description:
*		Demonstrates communications between USER and KERNEL.
*
****************************************************************************************
* Copyright (C) 2010 L0g1n.
****************************************************************************************/

#ifndef _SSDT_HOOK_H_
#define _SSDT_HOOK_H_

#include "SSDT.h"

//过虑函数,也就是要写入ssdt表中的函数
NTSTATUS NewZwOpenProcess(OUT PHANDLE ProcessHandle,
						  IN ACCESS_MASK DesiredAccess,
						  IN POBJECT_ATTRIBUTES ObjectAttributes,
						  IN PCLIENT_ID ClientId);

typedef NTSTATUS (__stdcall *ZWOPENPROCESS) (OUT PHANDLE ProcessHandle,
											 IN ACCESS_MASK DesiredAccess,
											 IN POBJECT_ATTRIBUTES ObjectAttributes,
											 IN PCLIENT_ID ClientId);

ZWOPENPROCESS RealZwOpenProcess;

BOOLEAN bool_hook_type = FALSE;

int int_hook_index = 190;

ULONG_PTR ul_ZwOpenProcess;
UNICODE_STRING unicode_string;

#endif
/***************************************************************************************
* AUTHOR : L0g1n
* DATE   : 2013-11-28
* MODULE : SSDTHook.C
* 
* Command: 
*	Source of IOCTRL Sample Driver
*
* Description:
*		Demonstrates communications between USER and KERNEL.
*
****************************************************************************************
* Copyright (C) 2010 L0g1n.
****************************************************************************************/

#include "SSDTHook.h"


VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
	if(bool_hook_type)
	{
		Cr0RemoveHook(&int_hook_index, (ULONG_PTR)RealZwOpenProcess);
	}
	else
	{
		if(MdlRemoveSSDTHook((ULONG_PTR)ul_ZwOpenProcess, (ULONG_PTR)NewZwOpenProcess, (ULONG_PTR *)&RealZwOpenProcess) == STATUS_SUCCESS)
		{
			DbgPrint("ZwOpenProcess Remove success.\r\n");
		}
	}
}
//过虑函数
NTSTATUS NewZwOpenProcess(IN PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId)
{
	return RealZwOpenProcess(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
}


NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING theRegistryPath)
{
	DriverObject->DriverUnload = DriverUnload;

	//两种方法实现对SSDT表的修改
	if(bool_hook_type)
	{
		//方法1:传统修改CR0方式
		Cr0SSDTHook(&int_hook_index, (ULONG_PTR *)&RealZwOpenProcess, (ULONG_PTR)NewZwOpenProcess);
	}
	else
	{
		//方法2:比较安全,使用MDL分配一块虚拟内存,映射到SSDT的物理地址
		RtlInitUnicodeString(&unicode_string, L"ZwOpenProcess");
		//MmGetSystemRoutineAddress用来获取系统导出函数的地址
		ul_ZwOpenProcess = (ULONG_PTR)MmGetSystemRoutineAddress(&unicode_string);
		if(ul_ZwOpenProcess)
		{
			//ul_ZwOpenProcess函数导出地址
			//NewZwOpenProcess是Hook函数的地址,在此函数内可加入过虑代码。此函数会被写入ssdt表
			//RealZwOpenProcess用来保存ssdt表中原始函数的地址
			if(MdlSSDTHook(ul_ZwOpenProcess, (ULONG_PTR)NewZwOpenProcess, (ULONG_PTR *)&RealZwOpenProcess) == STATUS_SUCCESS)
			{
				DbgPrint("ZwOpenProcess hook success.\r\n");
			}
		}
	}
	return STATUS_SUCCESS;
}




你可能感兴趣的:(hook,ssdt)