保护模式阶段测试-模拟3环0环调用

保护模式阶段测试-模拟3环0环调用

最近又复习了一下保护模式相关的内容,然后打算搞个能够把段页的大部分知识能够串联起来的测试代码
最终想到的一个项目如下:

三环部分:
0.编写一个函数读取高2g的地址内容
1.通过设备通信到0环告诉0环我新增加的函数地址
2.通过3环0环共享的数据结构取到新增加的中断号
3.调用中断号读取高2G地址内容
驱动部分:
0。接收到3环的函数地址
1.插入一个中断门,中断门的函数地址为3环传进来的那个
2.申请一个物理页里面填充一个数据结构,此数据结构中存放我们新的中断号

测试代码:

驱动代码

#include <ntddk.h>
//#include <ntifs.h>
#define NTSTRSAFE_LIB
#include <ntstrsafe.h>
#include <intrin.h>

extern NTSTATUS PsLookupProcessByProcessId(
	  HANDLE    ProcessId,
	PEPROCESS* Process
);

PDEVICE_OBJECT g_pDev = NULL;
UNICODE_STRING devName = { 0 };
UNICODE_STRING symName = { 0 };
DWORD32 g_idtNum = 0;
PVOID sharedMem;

VOID Unload(PDRIVER_OBJECT pDriver) {
	KdPrint(("unload"));
	IoDeleteSymbolicLink(&symName);
	IoDeleteDevice(g_pDev);

}

typedef struct _IDTR {
	UINT16 limit;
	UINT16 base_low;
	UINT16 base_hight;
}IDTR, *PIDTR;
#define DEVICE_OBJECT_NAME L"\\Device\\systest"
#define DEVICE_LINK_NAME L"\\??\\systest"
#define MAKE_WORD(a,b) ((a) + (b << 16))
#define MAKE_BASE(a) (DWORD32)(((a >> 32) & 0x00000000ffff0000) + ((a & 0x000000000000ffff)))
#define IOCTL_SYS_INJECTIDT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, \
										METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SYS_MAKE_SHAREDPAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, \
										METHOD_BUFFERED, FILE_ANY_ACCESS)

NTSTATUS InjectIDT(UINT64 new_idte , PDWORD32 idtNum) 
{
	// 获取idt表
	IDTR idtr = { 0 };
	__sidt(&idtr);
	KdPrint(("idt base=0x%x, limit=0x%x\r\n", MAKE_WORD(idtr.base_low, idtr.base_hight), idtr.limit));
	// 构造中断描述符

	//UINT64 new_idte = 0x0;
	

	// 寻找未使用的位置插入描述符
	PDWORD64 idteArr = (PDWORD64)MAKE_WORD(idtr.base_low, idtr.base_hight);
	for (size_t i = 0; i < (idtr.limit >> 3); i++)
	{
		if (MAKE_BASE(idteArr[i]) == 0x0) {
			idteArr[i] = new_idte;
			KdPrint(("中断号:0x%x", i));
			*idtNum = i;
			g_idtNum = i;
			return STATUS_SUCCESS;
		}
	}
	return STATUS_UNSUCCESSFUL;
}

NTSTATUS MakeSharedPage(UINT32 pid, DWORD32 addr)
{
	NTSTATUS status = STATUS_SUCCESS;
	PEPROCESS pEprocess = NULL;
	DWORD32 oldCr3 = 0;
	DWORD32 newCr3 = 0;
	DWORD32* pdt_va = (DWORD32*)0xc0300000;
	UCHAR* ptt_va = (UCHAR*)0xc0000000;


	__try {
		status = PsLookupProcessByProcessId((HANDLE)pid, &pEprocess);
		if (!NT_SUCCESS(status)) {
			KdPrint(("get eprocess failed!\r\n"));
			return STATUS_UNSUCCESSFUL;
		}
		newCr3 = *(DWORD32*)((UINT8*)pEprocess + 0x18);
		sharedMem = ExAllocatePool(PagedPool, 0x1000);
		if (sharedMem == NULL) {
			KdPrint(("alloc memory failed!\r\n"));
			return STATUS_UNSUCCESSFUL;
		}
		//拆分new_va
		KdPrint(("开始拆分线性地址"));
		DWORD32 new_va_10_1 = addr >> 0x16;
		DWORD32 new_va_10_2 = addr << 0xa;
		new_va_10_2 >>= 0x16;
		DWORD32 new_va_12 = addr & 0x00000fff;
		KdPrint(("addr:0x%x, 10:0x%x, 10:0x%x, 12:0x%x \r\n", addr, new_va_10_1, new_va_10_2, new_va_12));

		DWORD32 old_va_10_1 = (DWORD32)sharedMem >> 0x16;
		DWORD32 old_va_10_2 = (DWORD32)sharedMem << 0xa;
		old_va_10_2 >>= 0x16;
		DWORD32 old_va_12 = (DWORD32)sharedMem & 0x00000fff;
		KdPrint(("addr:0x%p, 10:0x%x, 10:0x%x, 12:0x%x \r\n", sharedMem, old_va_10_1, old_va_10_2, old_va_12));
		DbgBreakPoint();
		//挂载物理页
		KdPrint(("开始挂载物理页"));
		KIRQL irql = KeRaiseIrqlToDpcLevel();
		oldCr3 = __readcr3();
		__writecr3(newCr3);
		KeLowerIrql(irql);

		DWORD32* sys_pte = (ptt_va + ((new_va_10_1 << 12) + (new_va_10_2 << 2)));
		DWORD32* user_pte = (ptt_va + ((old_va_10_1 << 12) + (old_va_10_2 << 2)));
		KdPrint(("0x%p---0x%p\r\n", sys_pte, user_pte));
		*user_pte = *sys_pte;
		
		irql = KeRaiseIrqlToDpcLevel();
		__writecr3(oldCr3);
		KeLowerIrql(irql);
		//向共享页写入数据
		RtlMoveMemory(sharedMem, &g_idtNum, sizeof(g_idtNum));
	}
	__except (1) {
		KdPrint(("exception happened!\n"));
		return STATUS_UNSUCCESSFUL;
	}
	return STATUS_SUCCESS;
}

NTSTATUS DeviceControl(PDEVICE_OBJECT pDev, PIRP pIrp)
{
	NTSTATUS status = STATUS_SUCCESS;
	ULONG_PTR Informaiton = 0;
	ULONG ioControlCode = 0;
	PVOID input = NULL;
	ULONG inputLen = 0;
	PVOID output = NULL;
	ULONG outputLen = 0;
	PIO_STACK_LOCATION pIoStackLocation = IoGetCurrentIrpStackLocation(pIrp);
	ioControlCode = pIoStackLocation->Parameters.DeviceIoControl.IoControlCode;
	input = pIrp->AssociatedIrp.SystemBuffer;
	output = pIrp->AssociatedIrp.SystemBuffer;
	inputLen = pIoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
	outputLen = pIoStackLocation->Parameters.DeviceIoControl.OutputBufferLength;
	switch (ioControlCode)
	{
	case IOCTL_SYS_INJECTIDT:
	{
		if (input == NULL || output ==NULL || inputLen <= 0 || outputLen <= 0) {
			status = STATUS_UNSUCCESSFUL;
			break;
		}
		UINT64 newIdte = *((PUINT64)input);
		status = InjectIDT(newIdte, (PDWORD32)output);
		if (NT_SUCCESS(status)) {
			Informaiton = sizeof(DWORD32);
		}
		break;
	}
	case IOCTL_SYS_MAKE_SHAREDPAGE:
	{
		if (input == NULL || output == NULL || inputLen <= 0 || outputLen <= 0) {
			status = STATUS_UNSUCCESSFUL;
			break;
		}
		DWORD32* data = (DWORD32*)input;
		UINT32 pid = data[0];
		DWORD32 addr = data[1];
		status = MakeSharedPage(pid, addr);
		if (!NT_SUCCESS(status)) {
			KdPrint(("failed make shared page!\n"));
		}
		break;
	}
	default:
		break;
	}
	pIrp->IoStatus.Status = status;
	pIrp->IoStatus.Information = Informaiton;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return status;
}

NTSTATUS PassFunc(PDEVICE_OBJECT pDev, PIRP pIrp)
{
	pIrp->IoStatus.Information = 0;
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pRegPath) {
	NTSTATUS status = STATUS_SUCCESS;
	
	
	pDriver->DriverUnload = Unload;
	for (size_t i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
	{
		pDriver->MajorFunction[i] = PassFunc;
	}
	pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControl;
	do
	{
		KdPrint(("begin\r\n"));
		//创建设备对象
		
		RtlInitUnicodeString(&devName, DEVICE_OBJECT_NAME);
		status = IoCreateDevice(pDriver, 0, &devName, FILE_DEVICE_UNKNOWN, 0, FALSE, &g_pDev);
		if (!NT_SUCCESS(status)) {
			KdPrint(("Create Dev Object Failed!\r\n"));
			break;
		}
		RtlInitUnicodeString(&symName, DEVICE_LINK_NAME);
		status = IoCreateSymbolicLink(&symName, &devName);
		if (!NT_SUCCESS(status)) {
			KdPrint(("Create Sym Link Failed!\r\n"));
			IoDeleteDevice(g_pDev);
			break;
		}
		g_pDev->Flags |= DO_BUFFERED_IO;

	} while (FALSE);
	
	

	
	return status;
}

应用层代码:

// test1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <windows.h>

#define DEVICE_LINK_NAME L"\\\\.\\systest"
#define IOCTL_SYS_INJECTIDT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, \
										METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SYS_MAKE_SHAREDPAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, \
										METHOD_BUFFERED, FILE_ANY_ACCESS)

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE devHandle = CreateFile(DEVICE_LINK_NAME,
		GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_READ|FILE_SHARE_WRITE,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	if (devHandle == NULL || devHandle == INVALID_HANDLE_VALUE) {
		printf("open dev failed\n");
		return 0;
	}
	UINT32 idtNum = 0;
	UINT64 idte = 0x0102030405060708;
	DWORD returnLen = 0;
	BOOL IsOK = DeviceIoControl(devHandle,
		IOCTL_SYS_INJECTIDT,
		&idte,
		sizeof(UINT64),
		&idtNum,
		4,
		&returnLen,
		NULL);
	if (IsOK) {
		printf("idt num 0x%x\n", idtNum);
	} else {
		printf("control dev failed\n");
	}

	//创建共享内存
	LPVOID buf = VirtualAlloc(NULL, 1024, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
	UINT32 indata[2] = {GetCurrentProcessId(), (UINT32)buf};
	IsOK = DeviceIoControl(devHandle,
		IOCTL_SYS_MAKE_SHAREDPAGE,
		indata,
		sizeof(indata),
		indata,
		sizeof(indata),
		&returnLen,
		NULL);
	if (IsOK) {
		printf("idt num 0x%x\n", (UINT32*)buf);
	} else {
		printf("make shared page failed\n");
	}


	CloseHandle(devHandle);
	devHandle = NULL;

	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值