fileiomonitor.c
来自「SSDT拦截文件读写,提供接口供ring3通讯」· C语言 代码 · 共 446 行
C
446 行
/************************************************************************/
/* 实现文件读写监控 */
/* 周钢 2008/6/2 */
/************************************************************************/
#include "ntddk.h"
#include "FileIOMonitor.h"
//主入口
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
int i;
UNICODE_STRING nameString, linkString;
PDEVICE_OBJECT deviceObject;
NTSTATUS status;
WCHAR wBuffer[200];
nameString.Buffer = wBuffer;
nameString.MaximumLength = 200;
DriverObject->DriverUnload = DriverUnload;
DriverObject->DriverExtension->AddDevice = ALL_PASS;
RtlInitUnicodeString(&nameString, DRIVER_NANE);
status = IoCreateDevice(
DriverObject,
0, // 无设备扩展
&nameString,
FILE_DEVICE_UNKNOWN,
0,
TRUE,
&deviceObject
);
if (!NT_SUCCESS( status ))
return status;
deviceObject->Flags |= DO_BUFFERED_IO;
RtlInitUnicodeString(&linkString, DRIVER_SYMLINK_NAME);
status = IoCreateSymbolicLink (&linkString, &nameString);
if (!NT_SUCCESS( status ))
{
IoDeleteDevice (DriverObject->DeviceObject);
return status;
}
for(i=0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
{
DriverObject->MajorFunction[i] = DriverDispatch;
}
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DriverDispatchIoCtl;
RtlZeroMemory(ext, 2048);
strcat(ext, ".txt/.doc/.abc/.123/.dll");
ProcessNameOffset = GetProcessNameOffset();
return STATUS_SUCCESS;
}
static NTSTATUS ALL_PASS(IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject)
{
return STATUS_SUCCESS;
}
static NTSTATUS DriverDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
NTSTATUS status;
PIO_STACK_LOCATION irpSp;
UNREFERENCED_PARAMETER(DeviceObject);
//得到当前IRP (I/O请求包)
irpSp = IoGetCurrentIrpStackLocation( Irp );
IoCompleteRequest(Irp, 0);
return STATUS_SUCCESS;
}
static NTSTATUS DriverDispatchIoCtl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PIO_STACK_LOCATION IrpStack;
NTSTATUS status;
ULONG ControlCode;
ULONG InputLength,OutputLength;
TCHAR wInputBuffer[200];
TCHAR OutMsg[] = "Message send by driver";
// 得到当前IRP (IO请求包)
IrpStack = IoGetCurrentIrpStackLocation(Irp);
// 得到DeviceIoControl传来的功能调用号
ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
// 得到DeviceIoControl传来的输入缓冲区长度
InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
// 得到DeviceIoControl的输出缓冲区长度
OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
/*
DbgPrint("\nIOCTL_EVENT_MSG=0x%p",IOCTL_EVENT_MSG);
DbgPrint("\nIOCTL_HOOK_MSG=0x%p",IOCTL_HOOK_MSG);
DbgPrint("\nIOCTL_UNHOOK_MSG=0x%p",IOCTL_UNHOOK_MSG);
DbgPrint("\nIOCTL_CHANGE_EXT_MSG=0x%p",IOCTL_CHANGE_EXT_MSG);
DbgPrint("\nIOCTL_CALL_BACK_MSG=0x%p",IOCTL_CALL_BACK_MSG);
*/
switch (ControlCode)
{
case IOCTL_EVENT_MSG:
//DbgPrint("IOCTL_EVENT_MSG\n");
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, OutMsg, sizeof(OutMsg));
Irp->IoStatus.Status = STATUS_SUCCESS;
OutputLength = sizeof(OutMsg);
Irp->IoStatus.Information = OutputLength;
break;
case IOCTL_HOOK_MSG: //建立Hook
Hook();
break;
case IOCTL_UNHOOK_MSG: //取消Hook
UnHook();
break;
case IOCTL_CHANGE_EXT_MSG: //改变后缀名
strncpy(ext,IrpStack->Parameters.DeviceIoControl.Type3InputBuffer, (int)InputLength);
//返回数据给应用程序
break;
case IOCTL_CALL_BACK_MSG: //设置回调函数
//回调函数
break;
default:
break;
}
status = Irp->IoStatus.Status;
IoCompleteRequest(Irp, 0);
return status;
}
void DriverUnload (IN PDRIVER_OBJECT pDriverObject)
{
UNICODE_STRING nameString;
RtlInitUnicodeString(&nameString, DRIVER_SYMLINK_NAME);
IoDeleteSymbolicLink(&nameString);
IoDeleteDevice(pDriverObject->DeviceObject);
DbgPrint("\nDriverUnload OK!");
return;
}
//解锁ServiceDescriptorTable数据区
/*
void UNLOCKSDT()
{
PMDL pMyMDL = MmCreateMdl(NULL,KeServiceDescriptorTable.ServiceTableBase,
KeServiceDescriptorTable.NumberOfServices * 4 );
MmBuildMdlForNonPagedPool(pMyMDL);
pMyMDL->MdlFlags = pMyMDL->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
NewSystemCallTable = MmMapLockedPages(pMyMDL, KernelMode);
}*/
static void Hook()
{
//UNLOCKSDT();
//拦截HOOK
//HOOK("ZwWriteFile", NewZwWriteFile, oldZwWriteFile);
//HOOK("ZwReadFile", NewZwReadFile, oldZwReadFile);
_asm
{
CLI
MOV EAX, CR0
AND EAX, NOT 10000H
MOV CR0, EAX
}
oldZwWriteFile = (ZWWRITEFILE)InterlockedExchange((PLONG)(&SYSTEMSERVICE(ZwWriteFile)), (long)NewZwWriteFile);
oldZwReadFile = (ZWREADFILE)InterlockedExchange((PLONG)(&SYSTEMSERVICE(ZwReadFile)), (long)NewZwReadFile);
_asm
{
MOV EAX, CR0
OR EAX, 10000H
MOV CR0, EAX
STI
}
}
static void UnHook()
{
DbgPrint("\nUnhook start...");
//恢复入口
_asm
{
CLI
MOV EAX, CR0
AND EAX, NOT 10000H
MOV CR0, EAX
}
InterlockedExchange((PLONG)(&SYSTEMSERVICE(ZwWriteFile)), (long)oldZwWriteFile);
InterlockedExchange((PLONG)(&SYSTEMSERVICE(ZwReadFile)), (long)oldZwReadFile);
_asm
{
MOV EAX, CR0
OR EAX, 10000H
MOV CR0, EAX
STI
}
DbgPrint("\nUnhook OK!");
}
NTSTATUS NewZwWriteFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL,
IN PULONG Key OPTIONAL
)
{
NTSTATUS status;
CHAR BUFF[500];
LONG ProcessId;
RtlZeroMemory(BUFF, 500);
status = GetFullNameFromFileHandle(FileHandle,BUFF);
if (status == STATUS_SUCCESS)
{
if (ISSpecialFile((CHAR*)BUFF))
{
ProcessId = (LONG)PsGetCurrentProcessId();
GetProcessName(ProcessName);
DbgPrint("\n%s[%d] calling NewZwWriteFile Special filename=%s", ProcessName, ProcessId, BUFF);
}
}
//获取进程
//获取文件名字
//判断是否特殊指定文件名序列,是,拦截,并回调Java的方法
status = oldZwWriteFile(FileHandle,
Event,
ApcRoutine,
ApcContext,
IoStatusBlock,
Buffer,
Length,
ByteOffset,
Key);
return status;
}
NTSTATUS NewZwReadFile(
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset OPTIONAL,
IN PULONG Key OPTIONAL
)
{
NTSTATUS status;
LONG ProcessId;
CHAR BUFF[500];
RtlZeroMemory(BUFF, 500);
status = GetFullNameFromFileHandle(FileHandle,BUFF);
if (status == STATUS_SUCCESS)
{
if (ISSpecialFile((CHAR*)BUFF))
{
ProcessId = (LONG)PsGetCurrentProcessId();
GetProcessName(ProcessName);
DbgPrint("\n%s[%d] calling nNewZwReadFile Special filename=%s", ProcessName, ProcessId, BUFF);
}
}
//获取进程
//获取文件名字
//判断是否特殊指定文件名序列,是,拦截
status = oldZwReadFile(FileHandle,
Event,
ApcRoutine,
ApcContext,
IoStatusBlock,
Buffer,
Length,
ByteOffset,
Key);
return status;
}
static NTSTATUS ISSpecialFile(CHAR *FileName)
{
NTSTATUS status = 0;
int i = 0;
int found = 0;
char BUFF[1024];
char *p = NULL;
RtlZeroMemory(BUFF, 1024);
if( p = strrchr(FileName, '.'))
{
strcat(BUFF, p);
}
else
{
return FALSE;
}
status = strstr(BUFF, ext)!=NULL? FALSE:TRUE;
return status;
}
static NTSTATUS GetFullNameFromFileHandle(IN HANDLE FileHandle, CHAR *Buffer)
{
NTSTATUS status;
PFILE_OBJECT FileObject = NULL;
ANSI_STRING AnsiString;
UNICODE_STRING DosName;
CHAR cBuffer[500];
WCHAR wBuffer[500];
RtlZeroMemory(cBuffer,500);
AnsiString.Buffer = cBuffer;
AnsiString.MaximumLength = 500;
DosName.Buffer = wBuffer;
DosName.MaximumLength = 500;
//获取文件对象FILE_OBJECT
status = ObReferenceObjectByHandle(FileHandle, 0, NULL, KernelMode, &FileObject, NULL);
if (status == STATUS_SUCCESS)
{
status = IoVolumeDeviceToDosName(FileObject->DeviceObject, &DosName);
if (status == STATUS_SUCCESS)
{
RtlUnicodeStringToAnsiString(&AnsiString, &DosName, FALSE);
strcat(Buffer, AnsiString.Buffer);
RtlUnicodeStringToAnsiString(&AnsiString, &FileObject->FileName, FALSE);
strcat(Buffer, AnsiString.Buffer);
//DbgPrint("%s", Buffer);
return STATUS_SUCCESS;
}
}
return INVALID_HANDLE_VALUE;
}
ULONG GetProcessNameOffset()
{
PEPROCESS curproc;
int i;
curproc = PsGetCurrentProcess();
//
// Scan for 12KB, hopping the KPEB never grows that big!
//
for( i = 0; i < 3*PAGE_SIZE; i++ ) {
if( !strncmp( SYSNAME, (PCHAR) curproc + i, strlen(SYSNAME) )) {
return i;
}
}
//
// Name not found - oh, well
//
return 0;
}
VOID GetProcessName( PCHAR Name )
{
PEPROCESS curproc;
char *nameptr;
ULONG i;
if( ProcessNameOffset ) {
curproc = PsGetCurrentProcess();
nameptr = (PCHAR) curproc + ProcessNameOffset;
strncpy( Name, nameptr, 16 );
} else {
strcpy( Name, "???");
}
}
/*
1,建立设备 OK
2,卸载设备 OK
3,DeviceIoCtl消息处理 OK
4,正常IRP包消息处理
5,Hook OK
6,UnHook OK
7,动态库接口
8,Java接口
9,Debug
10,测试,解Bug
*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?