#include "ntddk.h"
#include "sysenterhook.h"
#if DBG
#define dprintf DbgPrint
#else
#define dprintf(x)
#endif
#define BYTE unsigned char
#define MEM_TAG 'CQ'
#define NT_DEVICE_NAME L"//Device//sysenterhook"
#define DOS_DEVICE_NAME L"//DosDevices//sysenterhook"
NTSTATUS DrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
VOID DrvUnload(IN PDRIVER_OBJECT DriverObject);
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
NTSTATUS DeviceIoControl(
IN ULONG IoControlCode,
IN PVOID InBuffer,
IN ULONG InBufferSize,
OUT PVOID OutBuffer,
IN ULONG OutBufferSize,
OUT IO_STATUS_BLOCK *IoStatus
);
ULONG d_origKiFastCallEntry; // save nt!KiFastCallEntry address
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, DrvUnload)
#endif
typedef NTSTATUS (*NTOPENPROCESS) (OUT PHANDLE ProcessHandle, IN ACCESS_MASK AccessMask, IN POBJECT_ATTRIBUTES ObjectAttribute, IN PCLIENT_ID ClientId);
typedef NTSTATUS (*NTCREATEFILE)(
__out PHANDLE FileHandle,
__in ACCESS_MASK DesiredAccess,
__in POBJECT_ATTRIBUTES ObjectAttributes,
__out PIO_STATUS_BLOCK IoStatusBlock,
__in_opt PLARGE_INTEGER AllocationSize,
__in ULONG FileAttributes,
__in ULONG ShareAccess,
__in ULONG CreateDisposition,
__in ULONG CreateOptions,
__in_opt PVOID EaBuffer,
__in ULONG EaLength
);
NTOPENPROCESS OldNtOpenProcess;
NTCREATEFILE OldNtCreateFile;
BYTE JmpCode[5] = {0xE9, 0, 0, 0, 0};
//原始指令
//mov edi,dword ptr[edi]
//mov ebx,dword ptr[edi+eax*4]
BYTE OrgCode[5] = {0x8B, 0x3F, 0x8B, 0x1C, 0x87};
//push 0
//retn
BYTE PushRetCode[6] = {0x68, 0, 0, 0, 0, 0xC3};
ULONG uKiFastCallEntryAddr = 0;
ULONG HookAddr = 0;
ULONG JMPRet = 0;
ULONG PushRetMem = 0;
NTSTATUS CqNtOpenProcess( OUT PHANDLE ProcessHandle, IN ACCESS_MASK AccessMase, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId )
{
DbgPrint("MyOpenProcess........................................../n");
return OldNtOpenProcess(ProcessHandle, AccessMase, ObjectAttributes, ClientId);
}
NTSTATUS CqNtCreateFile(
__out PHANDLE FileHandle,
__in ACCESS_MASK DesiredAccess,
__in POBJECT_ATTRIBUTES ObjectAttributes,
__out PIO_STATUS_BLOCK IoStatusBlock,
__in_opt PLARGE_INTEGER AllocationSize,
__in ULONG FileAttributes,
__in ULONG ShareAccess,
__in ULONG CreateDisposition,
__in ULONG CreateOptions,
__in_opt PVOID EaBuffer,
__in ULONG EaLength
)
{
DbgPrint("MyCreateFile............................................/n");
return OldNtCreateFile(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, AllocationSize, FileAttributes, ShareAccess, CreateDisposition, CreateOptions, EaBuffer, EaLength);
}
//HOOK KiFastCallEntry过滤函数
__declspec(naked)void CqKiFastCallEntry()
{
_asm
{
pushfd
pushad
mov edi,dword ptr [edi] //ssdt基地址
mov ebx,dword ptr [edi+eax*4] //根据索引找到服务函数地址
cmp OldNtCreateFile,ebx;//比较是否是NtCreateFile
je Label_NtCreateFile
cmp OldNtOpenProcess,ebx; //比较是否为NtOpenProcess
je Label_NtOpenProcess
popad
popfd
mov edi,dword ptr [edi]
mov ebx,dword ptr [edi+eax*4]
jmp [JMPRet];
Label_NtOpenProcess:
popad
popfd
mov ebx,CqNtOpenProcess //修改NtOpenProcess为代理函数
jmp [JMPRet];
Label_NtCreateFile:
popad
popfd
mov ebx,CqNtCreateFile //修改NtCreateFile为代理函数
jmp [JMPRet];
}
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
PDEVICE_OBJECT deviceObject = NULL;
NTSTATUS ntStatus;
UNICODE_STRING deviceNameUnicodeString;
PDEVICE_EXTENSION deviceExtension;
UNICODE_STRING deviceLinkUnicodeString;
UNICODE_STRING ustrNtOpenProcess = {0};
UNICODE_STRING ustrNtCreateFile = {0};
KIRQL oldIrql;
dprintf("entering DriverEntry/n");
RtlInitUnicodeString(&deviceNameUnicodeString, NT_DEVICE_NAME);
ntStatus = IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION),
&deviceNameUnicodeString,
FILE_DEVICE_SYSENTERHOOK,
0,
TRUE,
&deviceObject
);
if ( NT_SUCCESS(ntStatus) )
{
deviceExtension = (PDEVICE_EXTENSION)deviceObject->DeviceExtension;
RtlInitUnicodeString(&deviceLinkUnicodeString, DOS_DEVICE_NAME);
ntStatus = IoCreateSymbolicLink(
&deviceLinkUnicodeString,
&deviceNameUnicodeString
);
if ( !NT_SUCCESS(ntStatus) )
{
dprintf("IoCreateSymbolicLink failed/n");
}
DriverObject->MajorFunction[IRP_MJ_CREATE] =
DriverObject->MajorFunction[IRP_MJ_CLOSE] =
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DrvDispatch;
DriverObject->DriverUnload = DrvUnload;
}
if ( !NT_SUCCESS(ntStatus) )
{
if (deviceObject)
IoDeleteDevice(deviceObject);
}
dprintf("entering DriverEntry/n");
DriverObject->DriverUnload = DrvUnload;
__asm int 3
//获取Hook服务函数地址 NtOpenProcess和NtCreateFile为例
RtlInitUnicodeString(&ustrNtOpenProcess, L"NtOpenProcess" );
RtlInitUnicodeString(&ustrNtCreateFile, L"NtCreateFile");
OldNtOpenProcess=(NTOPENPROCESS)MmGetSystemRoutineAddress( &ustrNtOpenProcess);
OldNtCreateFile = (NTCREATEFILE)MmGetSystemRoutineAddress(&ustrNtCreateFile);
DbgPrint("NtOpenProcess = 0x%08X/n",OldNtOpenProcess);
DbgPrint("NtCreateFile = 0x%8X/n", OldNtCreateFile);
__asm
{
pushfd
pushad
mov ecx,0x176//SYSENTER_EIP_MAR(系统初始化时会使其指向KiFastCallEntry)
rdmsr
mov uKiFastCallEntryAddr,eax //获取KiFastCallEntry地址
xor ecx,ecx
Label1:
cmp ecx,0x100
je Label3
mov edx,DWORD ptr [eax]
cmp edx,0x1C8B3F8B //搜索特征码,获取要Hook的位置
je Label2
inc eax
inc ecx
jmp Label1
Label2:
mov HookAddr,eax
Label3:
popad
popfd
}
if( HookAddr==0 )
{
return ntStatus;
}
//申请内存 存放跳转指令
PushRetMem = (ULONG)ExAllocatePoolWithTag(NonPagedPool, 6, MEM_TAG);
if( (PVOID)PushRetMem == NULL )
{
return ntStatus;
}
DbgPrint("PushRetMem = 0x%08X/n",PushRetMem);
//存放跳转指令jmp 相对地址 跳到 pushRetMem
*(ULONG*)&JmpCode[1]=(ULONG)(PushRetMem) - (HookAddr + 5);
//存放push CqKiFastCallEntry retn(跳到过滤函数)
*(ULONG*)&PushRetCode[1] = (ULONG)CqKiFastCallEntry;
//HOOK返回地址
JMPRet = HookAddr + 5;
//提升中断请求级
oldIrql = KeRaiseIrqlToDpcLevel();
//关闭中断
_asm
{
CLI
MOV EAX, CR0
AND EAX, NOT 10000H
MOV CR0, EAX
}
//把PushRetMem地址存放push CqKiFastCallEntry retn(跳到过滤函数)指令
RtlCopyMemory((PVOID)PushRetMem,PushRetCode,6);
//覆盖KiFastCallEntry中的特征代码为JmpCode
RtlCopyMemory((PVOID)HookAddr,JmpCode,5);
//开启中断
_asm
{
MOV EAX, CR0
OR EAX, 10000H
MOV CR0, EAX
STI
}
//恢复先前中断请求级
KeLowerIrql(oldIrql);
DbgPrint("KiFastCallEntry = 0x%08X/n",uKiFastCallEntryAddr);
DbgPrint("HookAddr = 0x%08X/n",HookAddr);
/
return ntStatus;
}
NTSTATUS DrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION deviceExtension;
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
ULONG ioControlCode;
NTSTATUS ntStatus;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
irpStack = IoGetCurrentIrpStackLocation(Irp);
deviceExtension = DeviceObject->DeviceExtension;
ioBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
switch (irpStack->MajorFunction)
{
case IRP_MJ_CREATE:
dprintf("IRP_MJ_CREATE/n");
break;
case IRP_MJ_CLOSE:
dprintf("IRP_MJ_CLOSE/n");
break;
case IRP_MJ_DEVICE_CONTROL:
dprintf("IRP_MJ_DEVICE_CONTROL/n");
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
ntStatus = DeviceIoControl(
ioControlCode,
ioBuffer,
inputBufferLength,
ioBuffer,
outputBufferLength,
&Irp->IoStatus
);
break;
}
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return ntStatus;
}
VOID DrvUnload(IN PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING deviceLinkUnicodeString;
RtlInitUnicodeString(&deviceLinkUnicodeString, DOS_DEVICE_NAME);
IoDeleteSymbolicLink(&deviceLinkUnicodeString);
IoDeleteDevice(DriverObject->DeviceObject);
if (HookAddr!=0)
{
KIRQL oldIrql;
//提升中断请求级
oldIrql = KeRaiseIrqlToDpcLevel();
//关闭中断
_asm
{
CLI
MOV EAX, CR0
AND EAX, NOT 10000H
MOV CR0, EAX
}
//进行还原HOOK操作
RtlCopyMemory((PVOID)HookAddr,OrgCode,5);
_asm
{
MOV EAX, CR0
OR EAX, 10000H
MOV CR0, EAX
STI
}
//恢复先前中断请求级
KeLowerIrql(oldIrql);
// 释放内存
ExFreePool((PVOID)PushRetMem);
}
dprintf("unloading/n");
}
NTSTATUS DeviceIoControl(
IN ULONG IoControlCode,
IN PVOID InBuffer,
IN ULONG InBufferSize,
OUT PVOID OutBuffer,
IN ULONG OutBufferSize,
OUT IO_STATUS_BLOCK *IoStatus
)
{
NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
switch (IoControlCode)
{
case IOCTL_SYSENTERHOOK_HELLO:
{
break;
}
default:
ntStatus = STATUS_INVALID_PARAMETER;
dprintf("unknown IRP_MJ_DEVICE_CONTROL/n");
break;
}
return ntStatus;
}