Windows-Rootkits/ProtectFilex86/FileProtectX86.c

772 lines
22 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef CXX_FILEPROTECTX86_H
# include "FileProtectX86.h"
#endif
ULONG gC2pKeyCount = 0;
PDRIVER_OBJECT gDriverObject = NULL;
BOOLEAN bOk = FALSE;
ULONG_PTR IndexOffsetOfFunction = 0;
ULONG_PTR SSDTDescriptor = 0;
KIRQL Irql;
ULONG_PTR ulIndex = 0;
ULONG_PTR ulIndex1 = 0;
ULONG_PTR ulIndex2 = 0;
pfnNtSetInformationFile Old_NtSetInformationFileWinXP = NULL;
pfnNtDeleteFile Old_NtDeleteFileWinXP = NULL;
//pfnNtCreateFile Old_NtCreateFileWinXP = NULL;
pfnNtWriteFile Old_NtWriteFileWinXP = NULL;
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegisterPath)
{
ULONG i;
NTSTATUS status;
// 填写所有的分发函数的指针
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
{
DriverObject->MajorFunction[i] = c2pDispatchGeneral;
}
// 单独的填写一个Read分发函数。因为要的过滤就是读取来的按键信息
// 其他的都不重要。这个分发函数单独写。
DriverObject->MajorFunction[IRP_MJ_READ] = c2pDispatchRead;
// 单独的填写一个IRP_MJ_POWER函数。这是因为这类请求中间要调用
// 一个PoCallDriver和一个PoStartNextPowerIrp比较特殊。
DriverObject->MajorFunction [IRP_MJ_POWER] = c2pPower;
// 我们想知道什么时候一个我们绑定过的设备被卸载了(比如从机器上
// 被拔掉了所以专门写一个PNP即插即用分发函数
DriverObject->MajorFunction [IRP_MJ_PNP] = c2pPnP;
// 卸载函数。
DriverObject->DriverUnload = c2pUnload;
gDriverObject = DriverObject;
// 绑定所有键盘设备
status =c2pAttachDevices(DriverObject, RegisterPath);
SSDTDescriptor = (ULONG_PTR)GetFunctionAddressByNameFromNtosExport(L"KeServiceDescriptorTable");
IndexOffsetOfFunction = 1;
ulIndex = GetSSDTApiFunctionIndexFromNtdll("NtSetInformationFile");
ulIndex1 = GetSSDTApiFunctionIndexFromNtdll("NtWriteFile");
ulIndex2 = GetSSDTApiFunctionIndexFromNtdll("NtDeleteFile");
HookSSDT(ulIndex);
HookWrite(ulIndex1);
HookDelete(ulIndex2);
return STATUS_SUCCESS;
}
NTSTATUS
c2pDevExtInit(
IN PC2P_DEV_EXT devExt,
IN PDEVICE_OBJECT pFilterDeviceObject,
IN PDEVICE_OBJECT pTargetDeviceObject,
IN PDEVICE_OBJECT pLowerDeviceObject )
{
memset(devExt, 0, sizeof(C2P_DEV_EXT));
devExt->NodeSize = sizeof(C2P_DEV_EXT);
devExt->pFilterDeviceObject = pFilterDeviceObject;
KeInitializeSpinLock(&(devExt->IoRequestsSpinLock));
KeInitializeEvent(&(devExt->IoInProgressEvent), NotificationEvent, FALSE);
devExt->TargetDeviceObject = pTargetDeviceObject;
devExt->LowerDeviceObject = pLowerDeviceObject;
return( STATUS_SUCCESS );
}
// 这个函数经过改造。能打开驱动对象Kbdclass然后绑定
// 它下面的所有的设备:
NTSTATUS
c2pAttachDevices(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
NTSTATUS status = 0;
UNICODE_STRING uniNtNameString;
PC2P_DEV_EXT devExt;
PDEVICE_OBJECT pFilterDeviceObject = NULL;
PDEVICE_OBJECT pTargetDeviceObject = NULL;
PDEVICE_OBJECT pLowerDeviceObject = NULL;
PDRIVER_OBJECT KbdDriverObject = NULL;
KdPrint(("MyAttach\n"));
// 初始化一个字符串就是Kdbclass驱动的名字。
RtlInitUnicodeString(&uniNtNameString, KBD_DRIVER_NAME);
// 请参照前面打开设备对象的例子。只是这里打开的是驱动对象。
status = ObReferenceObjectByName (
&uniNtNameString,
OBJ_CASE_INSENSITIVE,
NULL,
0,
IoDriverObjectType,
KernelMode,
NULL,
&KbdDriverObject
);
// 如果失败了就直接返回
if(!NT_SUCCESS(status))
{
KdPrint(("MyAttach: Couldn't get the MyTest Device Object\n"));
return( status );
}
else
{
// 这个打开需要解应用。早点解除了免得之后忘记。
ObDereferenceObject(DriverObject);
}
// 这是设备链中的第一个设备
pTargetDeviceObject = KbdDriverObject->DeviceObject;
// 现在开始遍历这个设备链
while (pTargetDeviceObject)
{
// 生成一个过滤设备这是前面读者学习过的。这里的IN宏和OUT宏都是
// 空宏,只有标志性意义,表明这个参数是一个输入或者输出参数。
status = IoCreateDevice(
IN DriverObject,
IN sizeof(C2P_DEV_EXT),
IN NULL,
IN pTargetDeviceObject->DeviceType,
IN pTargetDeviceObject->Characteristics,
IN FALSE,
OUT &pFilterDeviceObject
);
// 如果失败了就直接退出。
if (!NT_SUCCESS(status))
{
KdPrint(("MyAttach: Couldn't create the MyFilter Filter Device Object\n"));
return (status);
}
// 绑定。pLowerDeviceObject是绑定之后得到的下一个设备。也就是
// 前面常常说的所谓真实设备。
pLowerDeviceObject =
IoAttachDeviceToDeviceStack(pFilterDeviceObject, pTargetDeviceObject);
// 如果绑定失败了,放弃之前的操作,退出。
if(!pLowerDeviceObject)
{
KdPrint(("MyAttach: Couldn't attach to MyTest Device Object\n"));
IoDeleteDevice(pFilterDeviceObject);
pFilterDeviceObject = NULL;
return( status );
}
// 设备扩展!下面要详细讲述设备扩展的应用。
devExt = (PC2P_DEV_EXT)(pFilterDeviceObject->DeviceExtension);
c2pDevExtInit(
devExt,
pFilterDeviceObject,
pTargetDeviceObject,
pLowerDeviceObject );
// 下面的操作和前面过滤串口的操作基本一致。这里不再解释了。
pFilterDeviceObject->DeviceType=pLowerDeviceObject->DeviceType;
pFilterDeviceObject->Characteristics=pLowerDeviceObject->Characteristics;
pFilterDeviceObject->StackSize=pLowerDeviceObject->StackSize+1;
pFilterDeviceObject->Flags |= pLowerDeviceObject->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE) ;
//next device
pTargetDeviceObject = pTargetDeviceObject->NextDevice;
}
return status;
}
VOID
c2pDetach(IN PDEVICE_OBJECT pDeviceObject)
{
PC2P_DEV_EXT devExt;
BOOLEAN NoRequestsOutstanding = FALSE;
devExt = (PC2P_DEV_EXT)pDeviceObject->DeviceExtension;
__try
{
__try
{
IoDetachDevice(devExt->TargetDeviceObject);
devExt->TargetDeviceObject = NULL;
IoDeleteDevice(pDeviceObject);
devExt->pFilterDeviceObject = NULL;
DbgPrint(("Detach Finished\n"));
}
__except (EXCEPTION_EXECUTE_HANDLER){}
}
__finally{}
return;
}
VOID
c2pUnload(IN PDRIVER_OBJECT DriverObject)
{
PDEVICE_OBJECT DeviceObject;
PDEVICE_OBJECT OldDeviceObject;
PC2P_DEV_EXT devExt;
LARGE_INTEGER lDelay;
PRKTHREAD CurrentThread;
//delay some time
lDelay = RtlConvertLongToLargeInteger(100 * DELAY_ONE_MILLISECOND);
CurrentThread = KeGetCurrentThread();
// 把当前线程设置为低实时模式,以便让它的运行尽量少影响其他程序。
KeSetPriorityThread(CurrentThread, LOW_REALTIME_PRIORITY);
UNREFERENCED_PARAMETER(DriverObject);
KdPrint(("DriverEntry unLoading...\n"));
// 遍历所有设备并一律解除绑定
DeviceObject = DriverObject->DeviceObject;
while (DeviceObject)
{
// 解除绑定并删除所有的设备
c2pDetach(DeviceObject);
DeviceObject = DeviceObject->NextDevice;
}
ASSERT(NULL == DriverObject->DeviceObject);
while (gC2pKeyCount)
{
KeDelayExecutionThread(KernelMode, FALSE, &lDelay);
}
UnHookSSDT(ulIndex);
UnHookSSDTWrite(ulIndex1);
UnHookSSDTDelete(ulIndex2);
KdPrint(("DriverEntry unLoad OK!\n"));
//return;
}
//处理我们不关心的所有IRP
NTSTATUS c2pDispatchGeneral(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
// 其他的分发函数直接skip然后用IoCallDriver把IRP发送到真实设备
// 的设备对象。
KdPrint(("Other Diapatch!"));
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(((PC2P_DEV_EXT)
DeviceObject->DeviceExtension)->LowerDeviceObject, Irp);
}
//只处理主功能号为IRP_MJ_POWER的IRP
NTSTATUS c2pPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PC2P_DEV_EXT devExt;
devExt =
(PC2P_DEV_EXT)DeviceObject->DeviceExtension;
PoStartNextPowerIrp( Irp );
IoSkipCurrentIrpStackLocation( Irp );
return PoCallDriver(devExt->LowerDeviceObject, Irp );
}
//设备被拔出时,需解除绑定,并删除过滤设备
NTSTATUS c2pPnP(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PC2P_DEV_EXT devExt;
PIO_STACK_LOCATION irpStack;
NTSTATUS status = STATUS_SUCCESS;
KIRQL oldIrql;
KEVENT event;
// 获得真实设备。
devExt = (PC2P_DEV_EXT)(DeviceObject->DeviceExtension);
irpStack = IoGetCurrentIrpStackLocation(Irp);
switch (irpStack->MinorFunction)
{
case IRP_MN_REMOVE_DEVICE:
KdPrint(("IRP_MN_REMOVE_DEVICE\n"));
// 首先把请求发下去
IoSkipCurrentIrpStackLocation(Irp);
IoCallDriver(devExt->LowerDeviceObject, Irp);
// 然后解除绑定。
IoDetachDevice(devExt->LowerDeviceObject);
// 删除我们自己生成的虚拟设备。
IoDeleteDevice(DeviceObject);
status = STATUS_SUCCESS;
break;
default:
// 对于其他类型的IRP全部都直接下发即可。
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(devExt->LowerDeviceObject, Irp);
}
return status;
}
// 这是一个IRP完成回调函数的原型
NTSTATUS c2pReadComplete(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
POBJECT_NAME_INFORMATION ObjetNameInfor;
ULONG* ulProcessNameLen;
PIO_STACK_LOCATION IrpSp;
ULONG buf_len = 0;
PUCHAR buf = NULL;
size_t i;
ULONG numKeys = 0;
IrpSp = IoGetCurrentIrpStackLocation( Irp );
// 如果这个请求是成功的。很显然,如果请求失败了,这么获取
// 进一步的信息是没意义的。
if( NT_SUCCESS( Irp->IoStatus.Status ) )
{
PKEYBOARD_INPUT_DATA pKeyData;
// 获得读请求完成后输出的缓冲区
buf = Irp->AssociatedIrp.SystemBuffer;
pKeyData = Irp->AssociatedIrp.SystemBuffer;
// 获得这个缓冲区的长度。一般的说返回值有多长都保存在
// Information中。
buf_len = Irp->IoStatus.Information;
numKeys = Irp->IoStatus.Information / sizeof(KEYBOARD_INPUT_DATA);
__try
{
if (NT_SUCCESS(IoQueryFileDosDeviceName((PFILE_OBJECT)IrpSp->FileObject, &ObjetNameInfor)))
{
if(wcsstr(ObjetNameInfor->Name.Buffer,L"Shine.txt")!=0)
{
DbgPrint("aaaaaaa");
}
}
}
__except(1)
{
DbgPrint("Exception:%x",GetExceptionCode());
}
//通过Process获得进程名称
for(i = 0; i < numKeys; i++)
{
// DbgPrint("%02X %d\n",pKeyData[i].MakeCode,pKeyData[i].Flags);
if(pKeyData[i].MakeCode == 0x1d && pKeyData[i].Flags == KEY_MAKE)
{
//左Ctrl
bOk = TRUE;
}
if(pKeyData[i].MakeCode == 0x2e && pKeyData[i].Flags == KEY_MAKE && bOk == TRUE ) //按下
{
pKeyData[i].MakeCode = 0x20;
bOk = FALSE;
DbgPrint("aaaaaaaaaaaaaa");
}
}
//… 这里可以做进一步的处理。我这里很简单的打印出所有的扫
// 描码。
// for(i=0;i<buf_len;++i)
// {
//DbgPrint("ctrl2cap: %2x\r\n", buf[i]);
// if(buf[i]==0x3a)
// {
// DbgPrint("SSSSSS");
// }
// }
}
gC2pKeyCount--;
if( Irp->PendingReturned )
{
IoMarkIrpPending( Irp );
}
return Irp->IoStatus.Status;
}
NTSTATUS c2pDispatchRead(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp )
{
NTSTATUS status = STATUS_SUCCESS;
PC2P_DEV_EXT devExt;
PIO_STACK_LOCATION currentIrpStack;
KEVENT waitEvent;
KeInitializeEvent( &waitEvent, NotificationEvent, FALSE );
if (Irp->CurrentLocation == 1)
{
ULONG ReturnedInformation = 0;
KdPrint(("Dispatch encountered bogus current location\n"));
status = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = ReturnedInformation;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(status);
}
// 全局变量键计数器加1
gC2pKeyCount++;
// 得到设备扩展。目的是之后为了获得下一个设备的指针。
devExt =
(PC2P_DEV_EXT)DeviceObject->DeviceExtension;
// 设置回调函数并把IRP传递下去。 之后读的处理也就结束了。
// 剩下的任务是要等待读请求完成。
currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine( Irp, c2pReadComplete,
DeviceObject, TRUE, TRUE, TRUE );
return IoCallDriver( devExt->LowerDeviceObject, Irp );
}
VOID HookSSDT(ULONG_PTR ulIndex)
{
PULONG32 ServiceTableBase = NULL;
ServiceTableBase = (PULONG32)((PSYSTEM_SERVICE_TABLE32)SSDTDescriptor)->ServiceTableBase; //数组首地址
Old_NtSetInformationFileWinXP = (pfnNtSetInformationFile)ServiceTableBase[ulIndex]; //先保存原先的函数地址
WPOFF();
ServiceTableBase[ulIndex] = (ULONG32)Fake_NtSetInformationFileWinXP; //将KeBugCheckEx函数的偏移地址放入SSDT表中
WPON();
}
VOID HookWrite(ULONG_PTR ulIndex)
{
PULONG32 ServiceTableBase = NULL;
ServiceTableBase = (PULONG32)((PSYSTEM_SERVICE_TABLE32)SSDTDescriptor)->ServiceTableBase; //数组首地址
Old_NtWriteFileWinXP = (pfnNtWriteFile)ServiceTableBase[ulIndex]; //先保存原先的函数地址
WPOFF();
ServiceTableBase[ulIndex] = (ULONG32)Fake_NtWriteFileWinXP; //将KeBugCheckEx函数的偏移地址放入SSDT表中
WPON();
}
VOID HookDelete(ULONG_PTR ulIndex)
{
PULONG32 ServiceTableBase = NULL;
ServiceTableBase = (PULONG32)((PSYSTEM_SERVICE_TABLE32)SSDTDescriptor)->ServiceTableBase; //数组首地址
Old_NtDeleteFileWinXP = (pfnNtDeleteFile)ServiceTableBase[ulIndex]; //先保存原先的函数地址
WPOFF();
ServiceTableBase[ulIndex] = (ULONG32)Fake_NtDeleteFileWinXP; //将KeBugCheckEx函数的偏移地址放入SSDT表中
WPON();
}
VOID
UnHookSSDT(ULONG_PTR ulIndex)
{
PULONG32 ServiceTableBase = NULL;
ServiceTableBase=(PULONG32)((PSYSTEM_SERVICE_TABLE32)SSDTDescriptor)->ServiceTableBase;
WPOFF();
ServiceTableBase[ulIndex] = (ULONG32)Old_NtSetInformationFileWinXP;
WPON();
}
VOID
UnHookSSDTWrite(ULONG_PTR ulIndex)
{
PULONG32 ServiceTableBase = NULL;
ServiceTableBase=(PULONG32)((PSYSTEM_SERVICE_TABLE32)SSDTDescriptor)->ServiceTableBase;
WPOFF();
ServiceTableBase[ulIndex] = (ULONG32)Old_NtWriteFileWinXP;
WPON();
}
VOID
UnHookSSDTDelete(ULONG_PTR ulIndex)
{
PULONG32 ServiceTableBase = NULL;
ServiceTableBase=(PULONG32)((PSYSTEM_SERVICE_TABLE32)SSDTDescriptor)->ServiceTableBase;
WPOFF();
ServiceTableBase[ulIndex] = (ULONG32)Old_NtDeleteFileWinXP;
WPON();
}
NTSTATUS Fake_NtSetInformationFileWinXP(
__in HANDLE FileHandle,
__out PIO_STATUS_BLOCK IoStatusBlock,
__in_bcount(Length) PVOID FileInformation,
__in ULONG Length,
__in FILE_INFORMATION_CLASS FileInformationClass
)
{
NTSTATUS Status;
PFILE_OBJECT hObject;
POBJECT_NAME_INFORMATION ObjetNameInfor;
Status = ObReferenceObjectByHandle(FileHandle,FILE_READ_DATA,0,KernelMode,&hObject, 0);
//通过进程句柄获取EProcess对象
if (NT_SUCCESS(IoQueryFileDosDeviceName((PFILE_OBJECT)hObject, &ObjetNameInfor)))
{
if(wcsstr((ObjetNameInfor->Name).Buffer,L"D:\\Shine.txt"))
{
if(FileInformationClass == FileRenameInformation)
{
return STATUS_ACCESS_DENIED;
}
}
}
return Old_NtSetInformationFileWinXP(FileHandle,IoStatusBlock,FileInformation,Length,FileInformationClass);
}
NTSTATUS
Fake_NtWriteFileWinXP (
__in HANDLE FileHandle,
__in_opt HANDLE Event,
__in_opt PIO_APC_ROUTINE ApcRoutine,
__in_opt PVOID ApcContext,
__out PIO_STATUS_BLOCK IoStatusBlock,
__in_bcount(Length) PVOID Buffer,
__in ULONG Length,
__in_opt PLARGE_INTEGER ByteOffset,
__in_opt PULONG Key
)
{
NTSTATUS Status;
PFILE_OBJECT hObject;
POBJECT_NAME_INFORMATION ObjetNameInfor;
Status = ObReferenceObjectByHandle(FileHandle,FILE_READ_DATA,0,KernelMode,&hObject, 0);
//通过进程句柄获取EProcess对象
if (NT_SUCCESS(IoQueryFileDosDeviceName((PFILE_OBJECT)hObject, &ObjetNameInfor)))
{
if(wcsstr((ObjetNameInfor->Name).Buffer,L"D:\\Shine.txt"))
{
return STATUS_ACCESS_DENIED;
}
}
return Old_NtWriteFileWinXP(FileHandle,Event,ApcRoutine,ApcContext,IoStatusBlock,Buffer,Length,ByteOffset,Key);
}
NTSTATUS Fake_NtDeleteFileWinXP(
__in POBJECT_ATTRIBUTES ObjectAttributes
)
{
if(wcsstr((ObjectAttributes->ObjectName)->Buffer,L"D:\\Shine.txt"))
{
return STATUS_ACCESS_DENIED;
}
return Old_NtDeleteFileWinXP(ObjectAttributes);
}
PVOID
GetFunctionAddressByNameFromNtosExport(WCHAR *wzFunctionName)
{
UNICODE_STRING uniFunctionName;
PVOID FunctionAddress = NULL;
if (wzFunctionName && wcslen(wzFunctionName) > 0)
{
RtlInitUnicodeString(&uniFunctionName, wzFunctionName);
FunctionAddress = MmGetSystemRoutineAddress(&uniFunctionName);
}
return FunctionAddress;
}
LONG GetSSDTApiFunctionIndexFromNtdll(char* szFindFunctionName)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PVOID MapBase = NULL;
PIMAGE_NT_HEADERS NtHeader;
PIMAGE_EXPORT_DIRECTORY ExportTable;
ULONG* FunctionAddresses;
ULONG* FunctionNames;
USHORT* FunctionIndexs;
ULONG ulIndex;
ULONG i;
CHAR* szFunctionName;
SIZE_T ViewSize=0;
ULONG_PTR ulFunctionAddress;
WCHAR wzNtdll[] = L"\\SystemRoot\\System32\\ntdll.dll";
Status = MapFileInUserSpace(wzNtdll, NtCurrentProcess(), &MapBase, &ViewSize);
if (!NT_SUCCESS(Status))
{
return STATUS_UNSUCCESSFUL;
}
else
{
__try{
NtHeader = RtlImageNtHeader(MapBase);
if (NtHeader && NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress){
ExportTable =(IMAGE_EXPORT_DIRECTORY*)((ULONG_PTR)MapBase + NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
FunctionAddresses = (ULONG*)((ULONG_PTR)MapBase + ExportTable->AddressOfFunctions);
FunctionNames = (ULONG*)((ULONG_PTR)MapBase + ExportTable->AddressOfNames);
FunctionIndexs = (USHORT*)((ULONG_PTR)MapBase + ExportTable->AddressOfNameOrdinals);
for(i = 0; i < ExportTable->NumberOfNames; i++)
{
szFunctionName = (LPSTR)((ULONG_PTR)MapBase + FunctionNames[i]);
if (_stricmp(szFunctionName, szFindFunctionName) == 0)
{
ulIndex = FunctionIndexs[i];
ulFunctionAddress = (ULONG_PTR)((ULONG_PTR)MapBase + FunctionAddresses[ulIndex]);
ulIndex=*(ULONG*)(ulFunctionAddress+IndexOffsetOfFunction);
break;
}
}
}
}__except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
if (ulIndex == -1)
{
DbgPrint("%s Get Index Error\n", szFindFunctionName);
}
ZwUnmapViewOfSection(NtCurrentProcess(), MapBase);
return ulIndex;
}
NTSTATUS
MapFileInUserSpace(WCHAR* wzFilePath,IN HANDLE hProcess OPTIONAL,
OUT PVOID *BaseAddress,
OUT PSIZE_T ViewSize OPTIONAL)
{
NTSTATUS Status = STATUS_INVALID_PARAMETER;
HANDLE hFile = NULL;
HANDLE hSection = NULL;
OBJECT_ATTRIBUTES oa;
SIZE_T MapViewSize = 0;
IO_STATUS_BLOCK Iosb;
UNICODE_STRING uniFilePath;
if (!wzFilePath || !BaseAddress){
return Status;
}
RtlInitUnicodeString(&uniFilePath, wzFilePath);
InitializeObjectAttributes(&oa,
&uniFilePath,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL
);
Status = IoCreateFile(&hFile,
GENERIC_READ | SYNCHRONIZE,
&oa,
&Iosb,
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 Status;
}
oa.ObjectName = NULL;
Status = ZwCreateSection(&hSection,
SECTION_QUERY | SECTION_MAP_READ,
&oa,
NULL,
PAGE_WRITECOPY,
SEC_IMAGE,
hFile
);
ZwClose(hFile);
if (!NT_SUCCESS(Status))
{
return Status;
}
if (!hProcess){
hProcess = NtCurrentProcess();
}
Status = ZwMapViewOfSection(hSection,
hProcess,
BaseAddress,
0,
0,
0,
ViewSize ? ViewSize : &MapViewSize,
ViewUnmap,
0,
PAGE_WRITECOPY
);
ZwClose(hSection);
if (!NT_SUCCESS(Status))
{
return Status;
}
return Status;
}
ULONG_PTR GetFunctionAddressByIndexFromSSDT32(ULONG_PTR ulIndex,ULONG_PTR SSDTDescriptor)
{
ULONG_PTR ServiceTableBase= 0 ;
PSYSTEM_SERVICE_TABLE32 SSDT = (PSYSTEM_SERVICE_TABLE32)SSDTDescriptor;
ServiceTableBase=(ULONG)(SSDT ->ServiceTableBase);
return (*(PULONG_PTR)(ServiceTableBase + 4 * ulIndex));
}
VOID WPOFF()
{
ULONG_PTR cr0 = 0;
Irql = KeRaiseIrqlToDpcLevel();
cr0 =__readcr0();
cr0 &= 0xfffffffffffeffff;
__writecr0(cr0);
//_disable();
}
VOID WPON()
{
ULONG_PTR cr0=__readcr0();
cr0 |= 0x10000;
//_enable();
__writecr0(cr0);
KeLowerIrql(Irql);
}