//hook.c
#include <ntddk.h>
typedef struct _SERVICE_DESCRIPTOR_TABLE
{
PULONG ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG NumberOfService;
ULONG ParamTableBase;
}SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TABLE; //由于KeServiceDescriptorTable只有一项,这里就简单点了
extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;//KeServiceDescriptorTable为导出函数
/////////////////////////////////////
VOID Hook();
VOID Unhook();
VOID OnUnload(IN PDRIVER_OBJECT DriverObject);
//////////////////////////////////////
ULONG JmpDeviceIoControlFile = 0;
ULONG JmpNtOpenProcess = 0;
ULONG JmpNtProtectVirtualMemory = 0;
ULONG JmpNtReadVirtualMemory = 0;
ULONG JmpNtWriteVirtualMemory = 0;
ULONG JmpNtOpenSection = 0;
ULONG JmpNtSuspendThread = 0;
ULONG OldDeviceIoControlAddress = 0;
ULONG OldNtOpenProcessAddress = 0;
ULONG OldNtProtectVirtualMemoryAddress = 0;
ULONG OldNtReadVirtualMemoryAddress = 0;
ULONG OldWriteVirtualMemoryAddress = 0;
ULONG OldNtOpenSectionAddress = 0;
ULONG OldNtSuspendThreadAddress = 0;
//////////////////////////////////////
__declspec(naked) NTSTATUS __stdcall MyNtDeviceIoControlFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG IoControlCode,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength
)
{
__asm
{
mov edi,edi
push ebp
mov ebp,esp
push 1
jmp [JmpDeviceIoControlFile]
}
}
__declspec(naked) NTSTATUS __stdcall MyNtOpenProcess(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK AccessMask,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId)
{
__asm
{
push 0C4h
push 0x804db4a0 //共十个字节
jmp [JmpNtOpenProcess]
}
}
__declspec(naked) NTSTATUS __stdcall MyNtProtectVirtualMemory(
IN HANDLE ProcessHandle,
IN OUT PVOID *BaseAddress,
IN OUT PULONG NumberOfBytesToProtect,
IN ULONG NewAccessProtection,
OUT PULONG OldAccessProtection
)//7
{
__asm
{
push 0x44
push 0x804db078
jmp [JmpNtProtectVirtualMemory]
}
}
__declspec(naked) NTSTATUS __stdcall MyNtReadVirtualMemory(
IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
OUT PVOID Buffer,
IN ULONG NumberOfBytesToRead,
OUT PULONG NumberOfBytesReaded OPTIONAL
)//7
{
__asm
{
push 0x1C
push 0x804daed0
jmp [JmpNtReadVirtualMemory]
}
}
__declspec(naked) NTSTATUS __stdcall MyNtWriteVirtualMemory(
IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
IN PVOID Buffer,
IN ULONG NumberOfBytesToWrite,
OUT PULONG NumberOfBytesWritten OPTIONAL)//7
{
__asm
{
push 0x1C
push 0x804daee8
jmp [JmpNtWriteVirtualMemory]
}
}
__declspec(naked) NTSTATUS __stdcall MyNtOpenSection(
OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes)//7
{
__asm
{
push 0x18
push 0x804dace0
jmp [JmpNtOpenSection]
}
}
__declspec(naked) NTSTATUS __stdcall MyNtSuspendThread(
IN HANDLE ThreadHandle,
OUT PULONG PreviousSuspendCount OPTIONAL )//7
{
__asm
{
push 0x20
push 0x804db9e0
jmp [JmpNtSuspendThread]
}
}
///////////////////////////////////////////////////
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
DriverObject->DriverUnload = OnUnload;
DbgPrint("Unhooker load");
Hook();
return STATUS_SUCCESS;
}
/////////////////////////////////////////////////////
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
DbgPrint("Unhooker unload!");
Unhook();
}
/////////////////////////////////////////////////////
VOID Hook()
{
//得到内核函数在SSDT表中索引的地址
ULONG NtDeviceIoControlIndexAddress = (ULONG)(KeServiceDescriptorTable->ServiceTableBase+0x42);
ULONG NtOpenProcessIndexAddress = (ULONG)(KeServiceDescriptorTable->ServiceTableBase+0x7a);
ULONG NtProtectVirtualMemoryIndexAddress = (ULONG)(KeServiceDescriptorTable->ServiceTableBase+0x89);
ULONG NtReadVirtualMemoryIndexAddress = (ULONG)(KeServiceDescriptorTable->ServiceTableBase+0xba);
ULONG NtWriteVirtualMemoryIndexAddress = (ULONG)(KeServiceDescriptorTable->ServiceTableBase+0x115);
ULONG NtOpenSectionIndexAddress = (ULONG)(KeServiceDescriptorTable->ServiceTableBase+0x7D);
ULONG NtSuspendThreadIndexAddress = (ULONG)(KeServiceDescriptorTable->ServiceTableBase+0xFE);
//在SSDT表中取到内核函数的地址,并保存以便卸载驱动的时候恢复
OldDeviceIoControlAddress = *(ULONG*)NtDeviceIoControlIndexAddress ;
OldNtOpenProcessAddress = *(ULONG*)NtOpenProcessIndexAddress ;
OldNtProtectVirtualMemoryAddress = *(ULONG*)NtProtectVirtualMemoryIndexAddress ;
OldNtReadVirtualMemoryAddress = *(ULONG*)NtReadVirtualMemoryIndexAddress ;
OldWriteVirtualMemoryAddress = *(ULONG*)NtWriteVirtualMemoryIndexAddress;
OldNtOpenSectionAddress = *(ULONG*)NtOpenSectionIndexAddress ;
OldNtSuspendThreadAddress = *(ULONG*)NtSuspendThreadIndexAddress ;
//得到跳转指令的位置
JmpDeviceIoControlFile = OldDeviceIoControlAddress+7;
JmpNtOpenProcess = OldNtOpenProcessAddress + 10;
JmpNtProtectVirtualMemory = OldNtProtectVirtualMemoryAddress + 7;
JmpNtReadVirtualMemory = OldNtReadVirtualMemoryAddress + 7;
JmpNtWriteVirtualMemory = OldWriteVirtualMemoryAddress + 7;
JmpNtOpenSection = OldNtSuspendThreadAddress + 7;
JmpNtSuspendThread = OldNtSuspendThreadAddress + 7;
__asm{//去掉内存保护
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
//把我们自己函数写进SSDT表中索引位置
*(ULONG*)NtDeviceIoControlIndexAddress = (ULONG)MyNtDeviceIoControlFile;
*(ULONG*)NtOpenProcessIndexAddress = (ULONG)MyNtOpenProcess;
*(ULONG*)NtProtectVirtualMemoryIndexAddress = (ULONG)MyNtProtectVirtualMemory;
*(ULONG*)NtReadVirtualMemoryIndexAddress = (ULONG)MyNtReadVirtualMemory;
*(ULONG*)NtWriteVirtualMemoryIndexAddress = (ULONG)MyNtWriteVirtualMemory;
*(ULONG*)NtOpenSectionIndexAddress = (ULONG)MyNtOpenSection;
*(ULONG*)NtSuspendThreadIndexAddress = (ULONG)MyNtSuspendThread;
__asm{//恢复内存保护
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
DbgPrint("Hook");
}
//////////////////////////////////////////////////////
VOID Unhook()
{
//得到内核函数在SSDT表中索引的地址
ULONG NtDeviceIoControlIndexAddress = (ULONG)(KeServiceDescriptorTable->ServiceTableBase+0x42);
ULONG NtOpenProcessIndexAddress = (ULONG)(KeServiceDescriptorTable->ServiceTableBase+0x7a);
ULONG NtProtectVirtualMemoryIndexAddress = (ULONG)(KeServiceDescriptorTable->ServiceTableBase+0x89);
ULONG NtReadVirtualMemoryIndexAddress = (ULONG)(KeServiceDescriptorTable->ServiceTableBase+0xba);
ULONG NtWriteVirtualMemoryIndexAddress = (ULONG)(KeServiceDescriptorTable->ServiceTableBase+0x115);
ULONG NtOpenSectionIndexAddress = (ULONG)(KeServiceDescriptorTable->ServiceTableBase+0x7D);
ULONG NtSuspendThreadIndexAddress = (ULONG)(KeServiceDescriptorTable->ServiceTableBase+0xFE);
__asm{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
}
//在SSDT表中索引的地址恢复系统内核函数
*(ULONG*)NtDeviceIoControlIndexAddress = (ULONG)OldDeviceIoControlAddress;
*(ULONG*)NtOpenProcessIndexAddress = (ULONG)OldNtOpenProcessAddress;
*(ULONG*)NtProtectVirtualMemoryIndexAddress = (ULONG)OldNtProtectVirtualMemoryAddress;
*(ULONG*)NtReadVirtualMemoryIndexAddress = (ULONG)OldNtReadVirtualMemoryAddress;
*(ULONG*)NtWriteVirtualMemoryIndexAddress = (ULONG)OldWriteVirtualMemoryAddress;
*(ULONG*)NtOpenSectionIndexAddress = (ULONG)OldNtOpenSectionAddress;
*(ULONG*)NtSuspendThreadIndexAddress = (ULONG)OldNtSuspendThreadAddress;
__asm{
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
DbgPrint("Unhook");
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课