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