最近又复习了一下保护模式相关的内容,然后打算搞个能够把段页的大部分知识能够串联起来的测试代码
最终想到的一个项目如下:
三环部分:
0.编写一个函数读取高2g的地址内容
1.通过设备通信到0环告诉0环我新增加的函数地址
2.通过3环0环共享的数据结构取到新增加的中断号
3.调用中断号读取高2G地址内容
驱动部分:
0。接收到3环的函数地址
1.插入一个中断门,中断门的函数地址为3环传进来的那个
2.申请一个物理页里面填充一个数据结构,此数据结构中存放我们新的中断号
测试代码:
驱动代码
#include
//#include
#define NTSTRSAFE_LIB
#include
#include
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
#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;
}