ring0 恢复SSDTHook

原理:

用ZwQuerySystemInformation 功能号为11(SystemModuleInformation)  得到所有系统模块的地址 遍历搜索得到ntos模块的基地址

读Ntos模块到System进程空间中

在ntos中找到函数真正地址

将地址转换为ssdt的索引


//X64版本
#include "ResumeSSDTHook.h" #define SEC_IMAGE 0x1000000 PVOID __NtosModuleBaseAddress = NULL; ULONG64 __NtosModuleLength = 0; PVOID __SSDTAddress = 0; ULONG32 __NtOpenProcessIndex = 0; NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegisterPath) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status; int i = 0; char FunctionName[] = "NtOpenProcess"; char ModuleName[] = "ntoskrnl.exe"; UNICODE_STRING DeviceName; UNICODE_STRING LinkName; RtlInitUnicodeString(&DeviceName,DEVICE_NAME); RtlInitUnicodeString(&LinkName,LINK_NAME); //创建设备对象; Status = IoCreateDevice(DriverObject,0, &DeviceName,FILE_DEVICE_UNKNOWN,0,FALSE,&DeviceObject); if (!NT_SUCCESS(Status)) { return Status; } Status = IoCreateSymbolicLink(&LinkName,&DeviceName); for (i = 0; i<IRP_MJ_MAXIMUM_FUNCTION; i++) { DriverObject->MajorFunction[i] = DefaultPassThrough; } DriverObject->DriverUnload = UnloadDriver; //得Ntos if (GetSystemMoudleInfoBySystemModuleName(ModuleName, &__NtosModuleBaseAddress, &__NtosModuleLength) == FALSE) { return Status; } DbgPrint("Win7 Ntos模块地址:%p\r\n", __NtosModuleBaseAddress); DbgPrint("Win7 Ntos模块大小:%x\r\n", __NtosModuleLength); //得ssdt if (GetSSDTAddress(&__SSDTAddress) == FALSE) { return Status; } DbgPrint("Win7 SSDT地址:%p\r\n", __SSDTAddress); //得需要hook的函数的索引 if (GetSSDTFunctionIndexFromNtdllExportTableByFunctionName(FunctionName, &__NtOpenProcessIndex) == FALSE) { return STATUS_UNSUCCESSFUL; } DbgPrint("Win7 __NtOpenProcessIndex地址:%d\r\n", __NtOpenProcessIndex); // if (ResumeSSDT(__SSDTAddress, __NtosModuleBaseAddress, __NtOpenProcessIndex, 4) == TRUE) { DbgPrint("恢复成功\r\n"); } #ifdef WIN64 DbgPrint("WIN64: ResumeSSDTHook IS RUNNING!!!"); #else DbgPrint("WIN32: ResumeSSDTHook SIS RUNNING!!!"); #endif return STATUS_SUCCESS; } NTSTATUS DefaultPassThrough(PDEVICE_OBJECT DeviceObject,PIRP Irp) { Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp,IO_NO_INCREMENT); return STATUS_SUCCESS; } VOID UnloadDriver(PDRIVER_OBJECT DriverObject) { UNICODE_STRING LinkName; PDEVICE_OBJECT NextDeviceObject = NULL; PDEVICE_OBJECT CurrentDeviceObject = NULL; RtlInitUnicodeString(&LinkName,LINK_NAME); IoDeleteSymbolicLink(&LinkName); CurrentDeviceObject = DriverObject->DeviceObject; while (CurrentDeviceObject != NULL) { NextDeviceObject = CurrentDeviceObject->NextDevice; IoDeleteDevice(CurrentDeviceObject); CurrentDeviceObject = NextDeviceObject; } DbgPrint("ResumeSSDTHook IS STOPPED!!!"); } BOOLEAN GetSystemMoudleInfoBySystemModuleName(char* ModuleName, PVOID* ModuleBase, ULONG64* ModuleLength) { int i = 0; NTSTATUS Status = STATUS_SUCCESS; PVOID BufferData = NULL; ULONG ReturnLength = 0; //功能号为11,先获取所需的缓冲区大小 得大小 Status = ZwQuerySystemInformation(SystemModuleInformation, NULL, 0, &ReturnLength); //SSDT if (Status != STATUS_INFO_LENGTH_MISMATCH) //没有内存 { return FALSE; } //申请内存 BufferData = ExAllocatePool(PagedPool, ReturnLength); //PagedPool(数据段 置换到磁盘) NonPagedPool(代码段 不置换到磁盘) if (BufferData == NULL) { return FALSE; } //再次调用 得数据 Status = ZwQuerySystemInformation(SystemModuleInformation, BufferData, ReturnLength, &ReturnLength); if (!NT_SUCCESS(Status)) { ExFreePool(BufferData); return FALSE; } for (i = 0; i < ((PSYSTEM_MODULES_INFO)BufferData)->NumberOfModules; i++) { if (strstr(((PSYSTEM_MODULES_INFO)BufferData)->Modules[i].ModuleFullPathData, ModuleName) != NULL) //Ntoskernel.exe { *ModuleBase = ((PSYSTEM_MODULES_INFO)BufferData)->Modules[i].ModuleBase; *ModuleLength = ((PSYSTEM_MODULES_INFO)BufferData)->Modules[i].ModuleLength; if (BufferData != NULL) { ExFreePool(BufferData); BufferData = NULL; } return TRUE; } } if (BufferData != NULL) { ExFreePool(BufferData); BufferData = NULL; } return FALSE; } BOOLEAN ResumeSSDT(ULONG64 SSDTAddress, ULONG64 ModuleBase, ULONG32 SSDTFunctionIndex, ULONG32 ParameterCount) { int i = 0; PUINT8 RVAOfSSDT = 0; WCHAR FileFullPathData[] = L"\\SystemRoot\\System32\\ntoskrnl.exe"; PIMAGE_DOS_HEADER DosHeader = NULL; PIMAGE_NT_HEADERS NtHeader = NULL; PIMAGE_OPTIONAL_HEADER OptionalHeader = NULL; PIMAGE_SECTION_HEADER SectionHeader = NULL; PVOID PresupporseImageBase = 0; //优先加载地址 PVOID BaseOfSSDTInFile = 0; //文件基地址 PVOID v1 = 0; //函数真正地址 ULONG32 v2 = 0; //SSDT[Offset] char v3; CHAR Bits[4] = { 0 }; PVOID BufferData = NULL; //获得SSDT与ntos模块基地址RVA RVAOfSSDT = ((PUINT8)(((PSERVER_SERVICE_DESCRIPTOR_TABLE)SSDTAddress)->Unknow0)) - (PUINT8)ModuleBase; //读Ntos模块到System进程空间中 (FileAlign) if (ReadingFileInRing0Space(FileFullPathData, &BufferData) == FALSE) { return FALSE; } DosHeader = (PIMAGE_DOS_HEADER)BufferData; NtHeader = (PIMAGE_NT_HEADERS)(DosHeader->e_lfanew + (PUINT8)BufferData); OptionalHeader = &(NtHeader->OptionalHeader); PresupporseImageBase = OptionalHeader->ImageBase; //优先加载的地址 SectionHeader = (PIMAGE_SECTION_HEADER)((PUINT8)NtHeader + sizeof(IMAGE_NT_HEADERS)); for (i = 0; i<NtHeader->FileHeader.NumberOfSections; i++) { if (RVAOfSSDT >= SectionHeader[i].VirtualAddress && RVAOfSSDT < (SectionHeader[i].VirtualAddress + SectionHeader[i].SizeOfRawData)) { //SSDT的文件偏移 BaseOfSSDTInFile = (PVOID)((PUINT8)BufferData + (RVAOfSSDT - (PUINT8)(SectionHeader[i].VirtualAddress)) + SectionHeader[i].PointerToRawData); break; } } //NtOpenProcess 文件中ssdt索引对应的函数地址 - 模块加载基地址 + ntos模块的基地址 v1 = (PUINT8)(((PULONG64)BaseOfSSDTInFile)[SSDTFunctionIndex]) - (PUINT8)PresupporseImageBase + (PUINT8)ModuleBase; //偏移 v1 = (PUINT8)v1 - (PUINT8)(((PSERVER_SERVICE_DESCRIPTOR_TABLE)SSDTAddress)->Unknow0); v1 = (ULONG32)v1 << 4; //处理参数个数 if (ParameterCount>4) { ParameterCount = ParameterCount - 4; } else { ParameterCount = 0; } //处理低四位,填写参数个数 如果一个函数的参数为5 那么dwTemp的低4位就是 0001 如果参数是6 就是0002 因为 6要减4 #define SETBIT(x,y) x|=(1<<y) //将X的第Y位置1 #define CLRBIT(x,y) x&=~(1<<y) //将X的第Y位清0 #define GETBIT(x,y) (x & (1 << y)) //取X的第Y位,返回0或非0 memcpy(&v3, &v1, 1); for (i = 0; i<4; i++) //一个16进制 4个二进制 0000 { Bits[i] = GETBIT(ParameterCount, i); if (Bits[i]) { SETBIT(v3, i); } else { CLRBIT(v3, i); } } memcpy(&v1, &v3, 1); //获得真实的数据了 //获得当前的数据 v2 = ((PULONG32)(((PSERVER_SERVICE_DESCRIPTOR_TABLE)SSDTAddress)->Unknow0))[SSDTFunctionIndex]; if (v1 != v2) { WPOFF(); ((PULONG32)(((PSERVER_SERVICE_DESCRIPTOR_TABLE)SSDTAddress)->Unknow0))[SSDTFunctionIndex] = (ULONG32)v1; WPON(); } if (BufferData != NULL) { ExFreePool(BufferData); BufferData = NULL; } return TRUE; } VOID WPOFF() { _disable(); __writecr0(__readcr0() & (~(0x10000))); } VOID WPON() { __writecr0(__readcr0() ^ 0x10000); _enable(); } BOOLEAN GetSSDTAddress(ULONG64* SSDTAddress) { //kd> rdmsr c0000082 PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082); PUCHAR EndSearchAddress = StartSearchAddress + PAGE_SIZE; PUCHAR i = NULL; UCHAR v1 = 0, v2 = 0, v3 = 0; INT64 Offset = 0; //002320c7 ULONG64 VariableAddress = 0; *SSDTAddress = NULL; for (i = StartSearchAddress; i < EndSearchAddress; i++) { if (MmIsAddressValid(i) && MmIsAddressValid(i + 1) && MmIsAddressValid(i + 2)) { v1 = *i; v2 = *(i + 1); v3 = *(i + 2); if (v1 == 0x4c && v2 == 0x8d && v3 == 0x15) { memcpy(&Offset, i + 3, 4); *SSDTAddress = Offset + (ULONG64)i + 7; break; } } } //如果是Win32 导出表 搜索 KeServiceDescriptorTable if (*SSDTAddress == NULL) { return FALSE; } return TRUE; } BOOLEAN GetSSDTFunctionIndexFromNtdllExportTableByFunctionName(CHAR* FunctionName, ULONG32* SSDTFunctionIndex) { ULONG i; BOOLEAN IsOk = FALSE; WCHAR FileFullPath[] = L"\\SystemRoot\\System32\\ntdll.dll"; //C:\Windows\ SIZE_T MappingViewSize = 0; PVOID MappingBaseAddress = NULL; PIMAGE_EXPORT_DIRECTORY ImageExportDirectory = NULL; PIMAGE_NT_HEADERS NtHeader = NULL; UINT32* AddressOfFunctions = NULL; UINT32* AddressOfNames = NULL; UINT16* AddressOfNameOrdinals = NULL; CHAR* v1 = NULL; ULONG32 FunctionOrdinal = 0; PVOID FunctionAddress = 0; ULONG32 Offset_SSDTFunctionIndex = 4; //将Ntdll.dll映射 当前的空间中 *SSDTFunctionIndex = -1; IsOk = MappingPEFileInRing0Space(FileFullPath, &MappingBaseAddress, &MappingViewSize); if (IsOk == FALSE) { return FALSE; } else { __try { NtHeader = RtlImageNtHeader(MappingBaseAddress); //extern if (NtHeader && NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) { ImageExportDirectory = (IMAGE_EXPORT_DIRECTORY*)((UINT8*)MappingBaseAddress + NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); AddressOfFunctions = (UINT32*)((UINT8*)MappingBaseAddress + ImageExportDirectory->AddressOfFunctions); AddressOfNames = (UINT32*)((UINT8*)MappingBaseAddress + ImageExportDirectory->AddressOfNames); AddressOfNameOrdinals = (UINT16*)((UINT8*)MappingBaseAddress + ImageExportDirectory->AddressOfNameOrdinals); for (i = 0; i < ImageExportDirectory->NumberOfNames; i++) { v1 = (char*)((ULONG64)MappingBaseAddress + AddressOfNames[i]); //获得函数名称 if (_stricmp(FunctionName, v1) == 0) { FunctionOrdinal = AddressOfNameOrdinals[i]; FunctionAddress = (PVOID)((UINT8*)MappingBaseAddress + AddressOfFunctions[FunctionOrdinal]); *SSDTFunctionIndex = *(ULONG32*)((UINT8*)FunctionAddress + Offset_SSDTFunctionIndex); break; } } } } __except (EXCEPTION_EXECUTE_HANDLER) { ; } } ZwUnmapViewOfSection(NtCurrentProcess(), MappingBaseAddress); //解除映射 if (*SSDTFunctionIndex == -1) { return FALSE; } return TRUE; } BOOLEAN MappingPEFileInRing0Space(WCHAR* FileFullPath, PVOID* MappingBaseAddress, PSIZE_T MappingViewSize) { NTSTATUS Status; UNICODE_STRING v1; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; HANDLE FileHandle = NULL; HANDLE SectionHandle = NULL; if (!FileFullPath &&MmIsAddressValid(FileFullPath)) { return FALSE; } if (!MappingBaseAddress&&MmIsAddressValid(MappingBaseAddress)) { return FALSE; } RtlInitUnicodeString(&v1, FileFullPath); InitializeObjectAttributes(&ObjectAttributes, &v1, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL ); //获得文件句柄 Status = IoCreateFile(&FileHandle, GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, //文件绝对路径 &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone, NULL, IO_NO_PARAMETER_CHECKING ); if (!NT_SUCCESS(Status)) { return FALSE; } ObjectAttributes.ObjectName = NULL; Status = ZwCreateSection(&SectionHandle, SECTION_QUERY | SECTION_MAP_READ, &ObjectAttributes, NULL, PAGE_WRITECOPY, SEC_IMAGE, //内存对齐 0x1000 FileHandle ); ZwClose(FileHandle); if (!NT_SUCCESS(Status)) { return FALSE; } Status = ZwMapViewOfSection(SectionHandle, NtCurrentProcess(), //映射到当前进程的内存空间中 MappingBaseAddress, 0, 0, 0, MappingViewSize, ViewUnmap, 0, PAGE_WRITECOPY ); ZwClose(SectionHandle); if (!NT_SUCCESS(Status)) { return FALSE; } return TRUE; } BOOLEAN ReadingFileInRing0Space(WCHAR* FileFullPathData, PVOID* BufferData) { NTSTATUS Status; LARGE_INTEGER ReturnLength = { 0,0 }; UNICODE_STRING v1; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE FileHandle; IO_STATUS_BLOCK IoStatusBlock; FILE_STANDARD_INFORMATION v2 = { 0 }; if (FileFullPathData == NULL&&*BufferData != NULL) { return FALSE; } RtlInitUnicodeString(&v1, FileFullPathData); InitializeObjectAttributes(&ObjectAttributes, &v1, OBJ_CASE_INSENSITIVE, NULL, NULL); //获取文件句柄 Status = ZwCreateFile(&FileHandle, SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (!NT_SUCCESS(Status)) { return FALSE; } //计算文件长度 Status = ZwQueryInformationFile(FileHandle, &IoStatusBlock, &v2, sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation); if (!NT_SUCCESS(Status)) { ZwClose(FileHandle); return FALSE; } //动态申请内存 *BufferData = ExAllocatePool(PagedPool, v2.EndOfFile.LowPart); if (*BufferData == NULL) { ZwClose(FileHandle); return FALSE; } //读取文件到内存 Status = ZwReadFile(FileHandle, NULL, NULL, NULL, &IoStatusBlock, *BufferData, v2.EndOfFile.LowPart, &ReturnLength, NULL); if (!NT_SUCCESS(Status)) { ExFreePool(*BufferData); ZwClose(FileHandle); return FALSE; } ZwClose(FileHandle); return TRUE; }
#include <ntifs.h>
#include <ntimage.h>
#ifndef CXX_ResumeSSDTHook_H
#define CXX_ResumeSSDTHook_H

#define DEVICE_NAME  L"\\Device\\ResumeSSDTHookDevice"
#define LINK_NAME    L"\\??\\ResumeSSDTHookLink"
#define  SystemModuleInformation 0xB

typedef struct SYSTEM_MODULE_INFO
{
    UINT32 Unknow0[4];
    UINT64 ModuleBase;
    UINT32 ModuleLength;
    UINT32 Flags;
    UINT64 Unknow1;
    char   ModuleFullPathData[256];
} SYSTEM_MODULE_INFO, *PSYSTEM_MODULE_INFO;

typedef struct _SYSTEM_MODULES_INFO
{
    UINT32 NumberOfModules;
    SYSTEM_MODULE_INFO Modules[1];
}SYSTEM_MODULES_INFO, *PSYSTEM_MODULES_INFO;

typedef struct _SERVER_SERVICE_DESCRIPTOR_TABLE_
{
    PVOID Unknow0;
    PVOID Unknow1;
    PVOID Unknow2;
    PVOID Unknow3;
}SERVER_SERVICE_DESCRIPTOR_TABLE, *PSERVER_SERVICE_DESCRIPTOR_TABLE;

extern
PIMAGE_NT_HEADERS
NTAPI
RtlImageNtHeader(PVOID BaseAddress);

extern
NTSTATUS
ZwQuerySystemInformation(
    IN ULONG SystemInformationClass,
    IN PVOID SystemInformation,
    IN ULONG SystemInformationLength,
    OUT PULONG ReturnLength);

VOID
    UnloadDriver(PDRIVER_OBJECT DriverObject);

BOOLEAN GetSystemMoudleInfoBySystemModuleName(char * ModuleName, PVOID * ModuleBase, ULONG64 * ModuleLength);

BOOLEAN ResumeSSDT(ULONG64 SSDTAddress, ULONG64 ModuleBase, ULONG32 SSDTFunctionIndex, ULONG32 ParameterCount);

VOID WPOFF();

VOID WPON();

BOOLEAN GetSSDTAddress(ULONG64 * SSDTAddress);

BOOLEAN GetSSDTFunctionIndexFromNtdllExportTableByFunctionName(CHAR * FunctionName, ULONG32 * SSDTFunctionIndex);

BOOLEAN MappingPEFileInRing0Space(WCHAR * FileFullPath, PVOID * MappingBaseAddress, PSIZE_T MappingViewSize);

BOOLEAN ReadingFileInRing0Space(WCHAR * FileFullPathData, PVOID * BufferData);

NTSTATUS
    DefaultPassThrough(PDEVICE_OBJECT  DeviceObject,PIRP Irp);

#endif

 

posted @ 2017-08-25 14:06  HsinTsao  阅读(724)  评论(0编辑  收藏  举报