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 + -
显示快捷键?