⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 driver.c

📁 直接IRP操作文件的实现问题
💻 C
📖 第 1 页 / 共 3 页
字号:
	}
	else
	{
		ExitApc = ExAllocatePool(NonPagedPool, sizeof(KAPC));

		if (!ExitApc)
			return STATUS_INSUFFICIENT_RESOURCES;

		KeInitializeApc(	ExitApc,
							Thread,
							OriginalApcEnvironment,
							PsExitSpecialApc,
							NULL,
							0,
							KernelMode,
							ULongToPtr(ExitStatus));

		if (!KeInsertQueueApc(ExitApc, ExitApc, NULL, 2))
		{
			ExFreePool(ExitApc);
			return STATUS_UNSUCCESSFUL;
		}
	}

	return STATUS_SUCCESS;
}

#define PROCESS_PAGE_DIR_BASE             0xC0300000
#define PROCESS_PAGE_TABLE_BASE           0xC0000000
typedef unsigned long* PPTE;

/**************************************************************************
* GetPteAddress - Returns a pointer to the page table entry corresponding 
*           to a given memory address.                     
*   
* Parameters:
*     PVOID VirtualAddress - Address you wish to acquire a pointer to the
*                     page table entry for.               
*   
* Return - Pointer to the page table entry for VirtualAddress or an error 
*       code.                                       
*   
* Error Codes:                                         
*     ERROR_PTE_NOT_PRESENT - The page table for the given virtual 
*                     address is not present in memory.       
*     ERROR_PAGE_NOT_PRESENT - The page containing the data for the     
*                     given virtual address is not present in   
*                     memory.                         
**************************************************************************/
PPTE GetPteAddress( PVOID VirtualAddress )                       
{   
    PPTE pPTE = 0;                                   
    __asm                                         
    {                                             
          cli               //disable interrupts           
          pushad                                   
          mov esi, PROCESS_PAGE_DIR_BASE                   
          mov edx, VirtualAddress                         
          mov eax, edx                               
          shr eax, 22                                 
          lea eax, [esi + eax*4] //pointer to page directory entry 
          test [eax], 0x80     //is it a large page?         
          jnz Is_Large_Page     //it's a large page           
          mov esi, PROCESS_PAGE_TABLE_BASE                   
          shr edx, 12                                 
          lea eax, [esi + edx*4] //pointer to page table entry (PTE)
          mov pPTE, eax                               
          jmp Done                                   
    
          //NOTE: There is not a page table for large pages because 
          //the phys frames are contained in the page directory.   
          Is_Large_Page:                               
          mov pPTE, eax                               
    
          Done:                                     
          popad                                     
          sti             //reenable interrupts           
    }//end asm                                       
    
    return pPTE;                                     
    
}//end GetPteAddress                                     
    
/**************************************************************************
* GetPhysicalFrameAddress - Gets the base physical address in memory where 
*                   the page is mapped. This corresponds to the   
*                   bits 12 - 32 in the page table entry.       
*   
* Parameters -                                         
*     PPTE pPte - Pointer to the PTE that you wish to retrieve the 
*     physical address from.                               
*   
* Return - The physical address of the page.                     
**************************************************************************/
ULONG GetPhysicalFrameAddress( PPTE pPte )                       
{   
    ULONG Frame = 0;                                   
    
    __asm                                         
    {                                             
          cli                                     
          pushad                                   
          mov eax, pPte                               
          mov ecx, [eax]                               
          shr ecx, 12 //physical page frame consists of the       
                  //upper 20 bits
          mov Frame, ecx                               
          popad                                     
          sti                                     
    }//end asm                                       
    return Frame;                                     
    
}//end GetPhysicalFrameAddress                               

#define HIGHEST_USER_ADDRESS 0x80000000
#define ERROR_PAGE_NOT_IN_LIST 0

typedef struct _HIDDEN_CODE_LIST
{
	PVOID ExecuteView;
	PVOID ReadWriteView;
	ULONG PageNumber;
	PVOID LoadExecutePage;
	PEPROCESS PageOwner;
} HIDDEN_CODE_LIST, *PHIDDEN_CODE_LIST;

ULONG OldInt0EHandler = 0;

VOID
EnableWriteProtect(
	BOOLEAN Enable
	)
{
	if (!Enable)
	{
		__asm
		{
			mov		eax, cr0;
			and		eax, 0xFFFEFFFF; // CR0 16 BIT = 0
			mov		cr0, eax;
		}
	}
	else
	{
		__asm
		{
			mov		eax, cr0;
			or		eax, 0x10000
			mov		cr0, eax;
		}
	}
}

void __declspec(naked) NewInt0EHandler(void)
{
	__asm
	{
		pushad
//		mov		edx, dword ptr [esp + 0x20] //PageFault.ErrorCode
//		test	edx, 0x04 //if the processor was in user mode, then
//		jnz		PassDown   //pass it down

		mov		eax, cr2
		cmp		eax, HIGHEST_USER_ADDRESS
		jae		PassDown

		push	eax
//		call	FindPageInHookedList
		mov		ebp, eax
		cmp		ebp, ERROR_PAGE_NOT_IN_LIST
		jz		PassDown

		mov		eax, cr2
		mov		esi, PROCESS_PAGE_DIR_BASE
		mov		ebx, eax
		shr		ebx, 22
		lea		ebx, [esi + ebx * 4] //ebx = pPTE for large page
		test	[ebx], 0x80     //check if its a large page
		jnz		IsLargePage                       

		mov		esi, PROCESS_PAGE_TABLE_BASE
		mov		ebx, eax
		shr		ebx, 12
		lea		ebx, [esi + ebx * 4] //ebx = pPTE

IsLargePage:
		cmp		[esp + 0x24], eax   //Is due to an attepmted execute?
		jne		LoadDTLB

		cli
		or		dword ptr [ebx], 0x01
		mov		eax, [ebx]
		and		eax, 0xFFFFF000
		push	eax
		call	[ebp].LoadExecutePage	//Eax返回新的执行页

		mov		eax, [ebp].ExecuteView
		mov		edi, [ebx]
		and		edi, 0x00000FFF //preserve the lower 12 bits of the faulting page's PTE
		and		eax, 0xFFFFF000 //isolate the physical address in the "fake" page's PTE
		or		eax, edi
		mov		edx, [ebx]		//保存原来的PTE
		mov		[ebx], eax		//替换物理帧
		mov		eax, cr2		//页失败地址
		mov		eax, dword ptr [eax]		//载入ITLB
		mov		[ebx], edx		//还原PTE
		and		dword ptr [ebx], 0xFFFFFFFE
		sti
		jmp		ReturnWithoutPassdown

LoadDTLB:
		cli
		or		dword ptr [ebx], 0x01
		mov		eax, dword ptr [eax]		//载入DTLB
		and		dword ptr [ebx], 0xFFFFFFFE
		sti

ReturnWithoutPassDown:
		popad
		add		esp, 4
		iretd

PassDown:
		popad
		jmp		OldInt0EHandler
	}
}
/*
void HookMemoryPage(
	PVOID ExecutePage,
	PVOID ReadWritePage,
	ULONG PageNumber
	)
{
	HOOKED_LIST_ENTRY HookedPage = {0};

	HookedPage.ExecuteView = ExecutePage;
	HookedPage.ReadWriteView = pReadWritePage;   
	HookedPage.PageNumber = PageNumber;
	HookedPage.PageOwner = PsGetCurrentProcess();

	__asm cli //disable interrupts

	if (g_OldInt0EHandler == NULL)
	{
		HookInt(&g_OldInt0EHandler, (unsigned long)NewInt0EHandler, 0x0E);
	}

	HookedPage.pExecutePte = GetPteAddress(pExecutePage);
	HookedPage.pReadWritePte = GetPteAddress(pReadWritePage);

	//Insert the hooked page into the list
	PushPageIntoHookedList(HookedPage);

	//Enable the global page feature
	EnableGlobalPageFeature(HookedPage.pExecutePte);

	//Mark the page non present
	MarkPageNotPresent(HookedPage.pExecutePte);

	//Go ahead and flush the TLBs. We want to guarantee that all
	//subsequent accesses to this hooked page are filtered
	//through our new page fault handler.
	__asm invlpg ExecutePage

	__asm sti //reenable interrupts
}//*/

typedef struct tagIDTR
{
	WORD IDTLimit;
	WORD LowIDTbase;
	WORD HiIDTbase;
} IDTR, *PIDTR;

typedef struct tagIDTENTRY
{
	WORD OffsetLow;
	WORD selector;
	WORD unused_lo : 13;
	WORD DPL : 2;
	WORD P : 1;
	WORD OffsetHigh;
} IDTENTRY, *PIDTENTRY;

VOID
EnableInt0EHook(
	BOOLEAN Enable
	)
{
	IDTR idtr;
	PIDTENTRY OIdt;
	PIDTENTRY NIdt;

	if (Enable)
	{
		__asm sidt idtr

		OIdt = (PIDTENTRY)MAKELONG(idtr.LowIDTbase,idtr.HiIDTbase);
		NIdt = &(OIdt[0x0e]);

		__asm cli

		OldInt0EHandler = MAKELONG(OIdt[0x0e].OffsetLow,OIdt[0x0e].OffsetHigh);
		NIdt->OffsetLow = LOWORD(NewInt0EHandler);
		NIdt->OffsetHigh = HIWORD(NewInt0EHandler);

		__asm lidt idtr
		__asm sti
	}
	else if (OldInt0EHandler)
	{
		__asm sidt idtr

		OIdt = (PIDTENTRY)MAKELONG(idtr.LowIDTbase,idtr.HiIDTbase);
		NIdt = &(OIdt[0x0e]);

		__asm cli

		NIdt->OffsetLow = LOWORD(OldInt0EHandler);
		NIdt->OffsetHigh = HIWORD(OldInt0EHandler);
		OldInt0EHandler = 0;

		__asm lidt idtr
		__asm sti
	}
}

NTSTATUS
DispatchRoutine(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP Irp
	)
{
	PIO_STACK_LOCATION irp_stack;
	NTSTATUS status;

	irp_stack = IoGetCurrentIrpStackLocation(Irp);
	status = STATUS_INVALID_DEVICE_REQUEST;

	switch (irp_stack->MajorFunction)
	{
	case IRP_MJ_CREATE:
	case IRP_MJ_CLOSE:
	case IRP_MJ_CLEANUP:
		status = STATUS_SUCCESS;
		break;
	}

	Irp->IoStatus.Status = status;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);

	return status;
}

NTSTATUS
ControlRoutine(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP Irp
	)
{
	PIO_STACK_LOCATION IrpStack;
	ULONG IoControlCode;
	PVOID InputBuffer, OutputBuffer;
	ULONG InputBufferLength, OutputBufferLength;
	NTSTATUS status;

	IrpStack = IoGetCurrentIrpStackLocation(Irp);
	IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
	InputBuffer = Irp->AssociatedIrp.SystemBuffer;
	OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
	InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
	OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;

	switch (IoControlCode)
	{
	case IOCTL_FILE_CREATE:
		status = fnCreateFile(	InputBuffer,
								InputBufferLength,
								&Irp->IoStatus);
		break;

	case IOCTL_FILE_DELETE:
		if (InputBufferLength < sizeof(PVOID))
		{
			status = STATUS_BUFFER_TOO_SMALL;
			break;
		}
		status = fnDeleteFile(*(HANDLE *)InputBuffer);
		break;

	case IOCTL_FILE_READ:
		status = fnReadFile(	InputBuffer,
								InputBufferLength,
								&Irp->IoStatus);
		break;

	case IOCTL_HANDLE_INFO:
		if (InputBufferLength < sizeof(QUERY_HANDLE_INFO) ||
			OutputBufferLength <= 1)
		{
			status = STATUS_BUFFER_TOO_SMALL;
			break;
		}
		status = QueryHandleInfo(	(PQUERY_HANDLE_INFO)InputBuffer,
									OutputBuffer,
									OutputBufferLength);
		break;

	case IOCTL_TEST_FUNCTION:
		DbgPrint(("IOCTL_TEST_FUNCTION\n"));

		if (InputBufferLength != sizeof(ULONG))
		{
			status = STATUS_INVALID_PARAMETER;
			break;
		}

		*(PULONG)InputBuffer = 0x12345678;
		Irp->IoStatus.Information = 4;
		status = STATUS_SUCCESS;
		break;

	default:
		Irp->IoStatus.Information = 0;
		status = STATUS_INVALID_DEVICE_REQUEST;
		break;
	}

	Irp->IoStatus.Status = status;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);

	return status;
}

VOID
DriverUnload(
	IN PDRIVER_OBJECT DriverObject
	)
{
	UNICODE_STRING DeviceLink;

	DbgPrint(("Unloading driver (%p)\n", DriverObject));
	RtlInitUnicodeString(&DeviceLink, L"\\DosDevices\\drvTest");
	IoDeleteSymbolicLink(&DeviceLink);
	IoDeleteDevice(DriverObject->DeviceObject);
}

NTSTATUS
DriverEntry(
	IN PDRIVER_OBJECT DriverObject,
	IN PUNICODE_STRING RegistryPath
	)
{
	UNICODE_STRING DeviceName;
	UNICODE_STRING DeviceLink;
	PDEVICE_OBJECT DeviceObject;
	ULONG i;
	NTSTATUS status;

	DbgPrint(("My driver entry!\n"));

	RtlInitUnicodeString(&DeviceName, L"\\Device\\drvTest");
	RtlInitUnicodeString(&DeviceLink, L"\\DosDevices\\drvTest");

	status = IoCreateDevice(DriverObject,
							0,
							&DeviceName,
							FILE_DEVICE_UNKNOWN,
							0,
							FALSE,
							&DeviceObject);

	if (!NT_SUCCESS(status))
		return status;

	status = IoCreateSymbolicLink(&DeviceLink, &DeviceName);

	if (!NT_SUCCESS(status))
	{
		IoDeleteDevice(DeviceObject);
		return status;
	}

	for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
		DriverObject->MajorFunction[i] = DispatchRoutine;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ControlRoutine;
	DriverObject->DriverUnload = DriverUnload;

	return STATUS_SUCCESS;
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -