#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;
}