353 lines
8.5 KiB
C
353 lines
8.5 KiB
C
|
#ifndef _nthook_H_
|
|||
|
#define _nthook_H_
|
|||
|
#include "drvdef.h"
|
|||
|
|
|||
|
#include "controlcode.h"
|
|||
|
|
|||
|
//Function Declaration
|
|||
|
ULONG GetNtInitialAddress(UNICODE_STRING FuncName);
|
|||
|
|
|||
|
ULONG GetNtCurrentAddress(ULONG NtIndex);
|
|||
|
|
|||
|
BOOL IsProcessProtected(DWORD PID);
|
|||
|
|
|||
|
NTSTATUS Nt_SSDT_Hook(ULONG NtIndex,ULONG HookedAddress);
|
|||
|
|
|||
|
NTSTATUS Nt_SSDT_UnHook(ULONG NtIndex,ULONG InitialAddress);
|
|||
|
|
|||
|
void ClosePageProtection();
|
|||
|
|
|||
|
void OpenPageProtection();
|
|||
|
|
|||
|
void Write_SSDT_Hook_Table(HookEntry* Hook_Entry,ULONG NtIndex,ULONG InitialAddress,ULONG HookedAddress);
|
|||
|
|
|||
|
//PAGE
|
|||
|
#pragma PAGECODE
|
|||
|
|
|||
|
//Used for getting the address of Nt functions
|
|||
|
ULONG GetNtInitialAddress(UNICODE_STRING FuncName)
|
|||
|
{
|
|||
|
return (ULONG)MmGetSystemRoutineAddress(&FuncName);
|
|||
|
}
|
|||
|
|
|||
|
#pragma PAGECODE
|
|||
|
|
|||
|
ULONG GetNtCurrentAddress(ULONG NtIndex)
|
|||
|
{
|
|||
|
ULONG RTN;
|
|||
|
ULONG _index = NtIndex * 4;
|
|||
|
|
|||
|
__asm
|
|||
|
{
|
|||
|
push ecx
|
|||
|
|
|||
|
mov ecx,KeServiceDescriptorTable
|
|||
|
//get the first term
|
|||
|
mov ecx,[ecx]
|
|||
|
//nth term = base+4n
|
|||
|
add ecx,_index
|
|||
|
|
|||
|
mov ecx,[ecx]
|
|||
|
|
|||
|
mov RTN,ecx
|
|||
|
pop ecx
|
|||
|
}
|
|||
|
return RTN;
|
|||
|
}
|
|||
|
|
|||
|
#pragma PAGECODE
|
|||
|
//the function to hook ssdt table
|
|||
|
NTSTATUS Nt_SSDT_Hook(ULONG NtIndex,ULONG HookedAddress)
|
|||
|
{
|
|||
|
ULONG _InitialAddress,_HookedAddress;
|
|||
|
ULONG _index = NtIndex * 4;
|
|||
|
_InitialAddress = GetNtCurrentAddress(NtIndex);
|
|||
|
_HookedAddress = HookedAddress;
|
|||
|
//close page protection to write the SSDT
|
|||
|
ClosePageProtection();
|
|||
|
__asm{
|
|||
|
push ecx
|
|||
|
push edx
|
|||
|
mov ecx,KeServiceDescriptorTable
|
|||
|
mov ecx,[ecx]
|
|||
|
add ecx,_index
|
|||
|
mov edx,_HookedAddress
|
|||
|
mov [ecx],edx
|
|||
|
pop edx
|
|||
|
pop ecx
|
|||
|
}
|
|||
|
//don't be a dick to your OS. now reopen the page protection.
|
|||
|
OpenPageProtection();
|
|||
|
|
|||
|
Write_SSDT_Hook_Table(&Global_Hook_Entry[0],NtIndex,_InitialAddress,_HookedAddress);
|
|||
|
//Print "hi bro, hook finished!"
|
|||
|
DbgPrint("Hooked:Initial Address:%X. Hooked Address:%X. NtIndex:%X.",_InitialAddress,_HookedAddress,NtIndex);
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
#pragma PAGECODE
|
|||
|
//When the driver unloads, unhook the ssdt
|
|||
|
NTSTATUS Nt_SSDT_UnHook(ULONG index,ULONG InitialAddress)
|
|||
|
{
|
|||
|
ULONG _index = index * 4;
|
|||
|
ClosePageProtection();
|
|||
|
__asm {
|
|||
|
push ecx
|
|||
|
push edx
|
|||
|
mov ecx,KeServiceDescriptorTable
|
|||
|
mov ecx,[ecx]
|
|||
|
add ecx,_index
|
|||
|
mov edx,InitialAddress
|
|||
|
mov [ecx],edx
|
|||
|
pop edx
|
|||
|
pop ecx
|
|||
|
}
|
|||
|
OpenPageProtection();
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
#pragma PAGECODE
|
|||
|
//used for closing page protection
|
|||
|
void ClosePageProtection()
|
|||
|
{
|
|||
|
__asm
|
|||
|
{
|
|||
|
cli
|
|||
|
mov eax,cr0
|
|||
|
and eax,not 10000h
|
|||
|
mov cr0,eax
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#pragma PAGECODE
|
|||
|
void OpenPageProtection()
|
|||
|
{
|
|||
|
__asm
|
|||
|
{
|
|||
|
mov eax, cr0
|
|||
|
or eax, 10000h
|
|||
|
mov cr0, eax
|
|||
|
sti
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#pragma PAGECODE
|
|||
|
//Write Hook Table
|
|||
|
void Write_SSDT_Hook_Table(HookEntry* Hook_Entry,ULONG NtIndex,ULONG InitialAddress,ULONG HookedAddress)
|
|||
|
{
|
|||
|
//index in the SSDT
|
|||
|
Hook_Entry[SSDT_HOOK_NUMBER].NtIndex = NtIndex;
|
|||
|
//Initial Address
|
|||
|
Hook_Entry[SSDT_HOOK_NUMBER].InitialAddress = InitialAddress;
|
|||
|
//store hooked address
|
|||
|
Hook_Entry[SSDT_HOOK_NUMBER].HookedAddress = HookedAddress;
|
|||
|
SSDT_HOOK_NUMBER++;
|
|||
|
}
|
|||
|
|
|||
|
#pragma PAGECODE
|
|||
|
|
|||
|
//used for determining whether PID is in the table
|
|||
|
BOOL IsProcessProtected(DWORD PID)
|
|||
|
{
|
|||
|
int i = 0;
|
|||
|
for(i=0;i<Protect_PID_Number;i++)
|
|||
|
{
|
|||
|
if(Global_Protect_PID_Table[i]==PID)
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
#pragma PAGECODE
|
|||
|
NTSTATUS DispatchRoutine_Write(IN PDEVICE_OBJECT pDevobj,IN PIRP pIrp)
|
|||
|
{
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS DispatchRoutine_Close(IN PDEVICE_OBJECT pDevobj,IN PIRP pIrp)
|
|||
|
{
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
#pragma PAGECODE
|
|||
|
NTSTATUS DispatchRoutine_Create(IN PDEVICE_OBJECT pDevobj,IN PIRP pIrp)
|
|||
|
{
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
#pragma PAGECODE
|
|||
|
NTSTATUS DispatchRoutine_Read(IN PDEVICE_OBJECT pDevobj,IN PIRP pIrp)
|
|||
|
{
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
#pragma PAGECODE
|
|||
|
NTSTATUS DispatchRoutine_Device_Control(IN PDEVICE_OBJECT pDevobj,IN PIRP pIrp)
|
|||
|
{
|
|||
|
NTSTATUS status=STATUS_UNSUCCESSFUL;
|
|||
|
ULONG ControlCode,info;
|
|||
|
//get ctrlcode
|
|||
|
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
|
|||
|
ControlCode = stack->Parameters.DeviceIoControl.IoControlCode;
|
|||
|
//What is the ctrlcode?
|
|||
|
switch(ControlCode)
|
|||
|
{
|
|||
|
//if NtGetPhysicalAddressCode, return physical address(failed)
|
|||
|
case NtGetPhysicalAddressCode:
|
|||
|
{
|
|||
|
PVOID In_Physical_Address_Buffer = (PVOID)pIrp->AssociatedIrp.SystemBuffer;
|
|||
|
PPHYSICAL_ADDRESS Out_Physical_Address_Buffer = (PPHYSICAL_ADDRESS)pIrp->AssociatedIrp.SystemBuffer;
|
|||
|
DbgPrint("NtGetPhysicalAddressCode Received.\n");
|
|||
|
DbgPrint("The Virtual Address Received is %X\n",In_Physical_Address_Buffer);
|
|||
|
*(Out_Physical_Address_Buffer) = MmGetPhysicalAddress(In_Physical_Address_Buffer);
|
|||
|
DbgPrint("The Physical Address is %X.\n",(*(Out_Physical_Address_Buffer)));
|
|||
|
info = sizeof(PHYSICAL_ADDRESS);
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
break;
|
|||
|
}
|
|||
|
//Very Important<6E><74>
|
|||
|
case NtProcessProtectCode:
|
|||
|
{
|
|||
|
PDWORD uPID = (PDWORD)pIrp->AssociatedIrp.SystemBuffer;
|
|||
|
DbgPrint("NtProcessProtectCode Received.\n");
|
|||
|
//write the HookTable
|
|||
|
Global_Protect_PID_Table[Protect_PID_Number] = *uPID;
|
|||
|
DbgPrint("Protected Process PID Number:%d\n",*uPID);
|
|||
|
//protected process number + 1
|
|||
|
Protect_PID_Number++;
|
|||
|
info = 4;
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
break;
|
|||
|
}
|
|||
|
//ignore other types
|
|||
|
default:
|
|||
|
{
|
|||
|
DbgPrint("Unknown Type NtControlCode Received.\n");
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
info = 0;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
//bytes returned to the user
|
|||
|
pIrp->IoStatus.Information=info;
|
|||
|
//set status
|
|||
|
pIrp->IoStatus.Status=STATUS_SUCCESS;
|
|||
|
//complete request
|
|||
|
IoCompleteRequest(pIrp,IO_NO_INCREMENT);
|
|||
|
DbgPrint("DeviceIoControl Completed.\n");
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
//create device
|
|||
|
#pragma INITCODE
|
|||
|
NTSTATUS CreateDevice(IN PDRIVER_OBJECT pDriverObject)
|
|||
|
{
|
|||
|
PDEVICE_OBJECT pDevObj;
|
|||
|
UNICODE_STRING pDevName;
|
|||
|
UNICODE_STRING pDevSymLinkName;
|
|||
|
NTSTATUS status;
|
|||
|
RtlInitUnicodeString(&pDevName,L"\\Device\\Hyper_Assembler");
|
|||
|
status = IoCreateDevice( pDriverObject,0,&pDevName,FILE_DEVICE_UNKNOWN,0, TRUE,&pDevObj);
|
|||
|
if(!NT_SUCCESS(status))
|
|||
|
{
|
|||
|
DbgPrint("Error creating device\n");
|
|||
|
return status;
|
|||
|
}
|
|||
|
DbgPrint("Device Create Succeeded\n");
|
|||
|
pDevObj->Flags |= DO_BUFFERED_IO;
|
|||
|
RtlInitUnicodeString(&pDevSymLinkName,L"\\??\\Hyper_ASM");
|
|||
|
status = IoCreateSymbolicLink( &pDevSymLinkName,&pDevName);
|
|||
|
if (!NT_SUCCESS(status))
|
|||
|
{
|
|||
|
DbgPrint("Error Linking Name\n");
|
|||
|
IoDeleteDevice(pDevObj);
|
|||
|
return status;
|
|||
|
}
|
|||
|
DbgPrint("Linking Name Succeeded\n");
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
#pragma PAGECODE
|
|||
|
//Hooked NtTerminateProcess
|
|||
|
NTSTATUS HookedNtTerminateProcess(
|
|||
|
IN HANDLE ProcessHandle OPTIONAL,
|
|||
|
IN NTSTATUS ExitStatus)
|
|||
|
{
|
|||
|
DWORD PID;
|
|||
|
NTSTATUS status;
|
|||
|
PEPROCESS eProcess;
|
|||
|
//Get process object
|
|||
|
status = ObReferenceObjectByHandle(ProcessHandle,FILE_READ_DATA,NULL,KernelMode,&eProcess,NULL);
|
|||
|
if(!NT_SUCCESS(status))
|
|||
|
{
|
|||
|
return status;
|
|||
|
}
|
|||
|
//Get PID
|
|||
|
PID = (DWORD)PsGetProcessId(eProcess);
|
|||
|
if(IsProcessProtected(PID))
|
|||
|
{
|
|||
|
//if pid = protected
|
|||
|
DbgPrint("Protected Process Termination Detected. Access has been denied. PID:%d\n",PID);
|
|||
|
//return Access Denied!
|
|||
|
return STATUS_ACCESS_DENIED;
|
|||
|
}
|
|||
|
DbgPrint("Normal Process Termination Detected. Call NtTerminateProcess to terminate. PID:%d\n",PID);
|
|||
|
//or invoke the original NtOpenProcess to handle the request
|
|||
|
status = InitialNtTerminateProcessAddress(ProcessHandle,ExitStatus);
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
//The hooked NtOpenProcess
|
|||
|
NTSTATUS HookedNtOpenProcess(
|
|||
|
__out PHANDLE ProcessHandle,
|
|||
|
__in ACCESS_MASK DesiredAccess,
|
|||
|
__in POBJECT_ATTRIBUTES ObjectAttributes,
|
|||
|
__in_opt PCLIENT_ID ClientId
|
|||
|
)
|
|||
|
{
|
|||
|
DWORD PID;
|
|||
|
NTSTATUS status;
|
|||
|
PEPROCESS eProcess;
|
|||
|
status = ObReferenceObjectByHandle(ProcessHandle,FILE_READ_DATA,NULL,KernelMode,&eProcess,NULL);
|
|||
|
if(!NT_SUCCESS(status))
|
|||
|
{
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
PID = (DWORD)PsGetProcessId(eProcess);
|
|||
|
if(IsProcessProtected(PID))
|
|||
|
{
|
|||
|
DbgPrint("Protected Process Open Detected. Access has been denied. PID:%d\n",PID);
|
|||
|
ProcessHandle = NULL;
|
|||
|
return STATUS_ACCESS_DENIED;
|
|||
|
}
|
|||
|
DbgPrint("Normal Process Open Detected. Call NtOpenProcess to proceed.\n");
|
|||
|
status = InitialNtOpenProcessAddress(ProcessHandle,DesiredAccess,ObjectAttributes,ClientId);
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
void Driver_Unload(PDRIVER_OBJECT pDrv)
|
|||
|
{
|
|||
|
PDEVICE_OBJECT pDevObj;
|
|||
|
UNICODE_STRING SymLink;
|
|||
|
//Create Symbol Link Name
|
|||
|
RtlInitUnicodeString(&SymLink,L"\\??\\Hyper_ASM");
|
|||
|
pDevObj = pDrv->DeviceObject;
|
|||
|
//DeleteDevice
|
|||
|
IoDeleteDevice(pDevObj);
|
|||
|
IoDeleteSymbolicLink(&SymLink);
|
|||
|
SSDT_UNHOOK_ALL();
|
|||
|
DbgPrint("Driver Successfully Unloaded\n");
|
|||
|
}
|
|||
|
|
|||
|
//used for restoring system ssdt
|
|||
|
void SSDT_UNHOOK_ALL()
|
|||
|
{
|
|||
|
int i;
|
|||
|
for (i=SSDT_HOOK_NUMBER-1;i>=0;i--)
|
|||
|
{
|
|||
|
Nt_SSDT_UnHook(Global_Hook_Entry[i].NtIndex,Global_Hook_Entry[i].InitialAddress);
|
|||
|
DbgPrint("UnHooked:Initial Address:%X. Hooked Address:%X. NtIndex:%X.",Global_Hook_Entry[i].InitialAddress,Global_Hook_Entry[i].HookedAddress,Global_Hook_Entry[i].NtIndex);
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|