驱动开发:内核读写内存多级偏移

news2024/9/22 15:48:46

让我们继续在《内核读写内存浮点数》的基础之上做一个简单的延申,如何实现多级偏移读写,其实很简单,读写函数无需改变,只是在读写之前提前做好计算工作,以此来得到一个内存偏移值,并通过调用内存写入原函数实现写出数据的目的。

以读取偏移内存为例,如下代码同样来源于本人的LyMemory读写驱动项目,其中核心函数为WIN10_ReadDeviationIntMemory()该函数的主要作用是通过用户传入的基地址与偏移值,动态计算出当前的动态地址。

函数首先将基地址指向要读取的变量,并将其转换为LPCVOID类型的指针。然后将指向变量值的缓冲区转换为LPVOID类型的指针。接下来,函数使用PsLookupProcessByProcessId函数查找目标进程并返回其PEPROCESS结构体。随后,函数从偏移地址数组的最后一个元素开始迭代,每次循环都从目标进程中读取4字节整数型数据,并将其存储在Value变量中。然后,函数将基地址指向Value和偏移地址的和,以便在下一次循环中读取更深层次的变量。最后,函数将基地址指向最终变量的地址,读取变量的值,并返回。

如下案例所示,用户传入进程基址以及offset偏移值时,只需要动态计算出该偏移地址,并与基址相加即可得到动态地址。

#include <ntifs.h>
#include <ntintsafe.h>
#include <windef.h>

// 普通Ke内存读取
NTSTATUS KeReadProcessMemory(PEPROCESS Process, PVOID SourceAddress, PVOID TargetAddress, SIZE_T Size)
{
	PEPROCESS SourceProcess = Process;
	PEPROCESS TargetProcess = PsGetCurrentProcess();
	SIZE_T Result;
	if (NT_SUCCESS(MmCopyVirtualMemory(SourceProcess, SourceAddress, TargetProcess, TargetAddress, Size, KernelMode, &Result)))
		return STATUS_SUCCESS;
	else
		return STATUS_ACCESS_DENIED;
}

// 读取整数内存多级偏移
/*
  Pid: 目标进程的进程ID。
  Base: 变量的基地址。
  offset: 相对基地址的多级偏移地址,用于定位变量。
  len: 偏移地址的数量。
*/
INT64 WIN10_ReadDeviationIntMemory(HANDLE Pid, LONG Base, DWORD offset[32], DWORD len)
{
	INT64 Value = 0;
	LPCVOID pbase = (LPCVOID)Base;
	LPVOID rbuffer = (LPVOID)&Value;

	PEPROCESS Process;
	PsLookupProcessByProcessId((HANDLE)Pid, &Process);

	for (int x = len - 1; x >= 0; x--)
	{
		__try
		{
			KeReadProcessMemory(Process, pbase, rbuffer, 4);
			pbase = (LPCVOID)(Value + offset[x]);
		}
		__except (EXCEPTION_EXECUTE_HANDLER)
		{
			return 0;
		}
	}

	__try
	{
		DbgPrint("读取基址:%x \n", pbase);
		KeReadProcessMemory(Process, pbase, rbuffer, 4);
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		return 0;
	}

	return Value;
}

// 驱动卸载例程
VOID UnDriver(PDRIVER_OBJECT driver)
{
	DbgPrint("Uninstall Driver \n");
}

// 驱动入口地址
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	DbgPrint("Hello LyShark \n");

	DWORD PID = 4884;
	LONG PBase = 0x6566e0;
	LONG Size = 4;
	DWORD Offset[32] = { 0 };

	Offset[0] = 0x18;
	Offset[1] = 0x0;
	Offset[2] = 0x14;
	Offset[3] = 0x0c;

	// 读取内存数据
	INT64 read = WIN10_ReadDeviationIntMemory(PID, PBase, Offset, Size);

	DbgPrint("PID: %d 基址: %p 偏移长度: %d \n", PID, PBase, Size);
	DbgPrint("[+] 1级偏移: %x \n", Offset[0]);
	DbgPrint("[+] 2级偏移: %x \n", Offset[1]);
	DbgPrint("[+] 3级偏移: %x \n", Offset[2]);
	DbgPrint("[+] 4级偏移: %x \n", Offset[3]);

	DbgPrint("[ReadMemory] 读取偏移数据: %d \n", read);

	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

编译并运行如上这段代码,则可获取到PID=4884PBase的动态地址中的数据,如下图所示;

至于如何将数据写出四级偏移的基址上面,则只需要取出pbase里面的基址,并通过原函数WIN10_WriteProcessMemory直接写出数据即可,此出的原函数在《内核MDL读写进程内存》中已经做了详细介绍,实现写出代码如下所示;

#include <ntifs.h>
#include <ntintsafe.h>
#include <windef.h>

// 普通Ke内存读取
NTSTATUS KeReadProcessMemory(PEPROCESS Process, PVOID SourceAddress, PVOID TargetAddress, SIZE_T Size)
{
	PEPROCESS SourceProcess = Process;
	PEPROCESS TargetProcess = PsGetCurrentProcess();
	SIZE_T Result;
	if (NT_SUCCESS(MmCopyVirtualMemory(SourceProcess, SourceAddress, TargetProcess, TargetAddress, Size, KernelMode, &Result)))
		return STATUS_SUCCESS;
	else
		return STATUS_ACCESS_DENIED;
}

// Win10 内存写入函数
BOOLEAN WIN10_WriteProcessMemory(HANDLE Pid, PVOID Address, SIZE_T BYTE_size, PVOID VirtualAddress)
{
	PVOID buff1;
	VOID *buff2;
	int MemoryNumerical = 0;
	KAPC_STATE KAPC = { 0 };

	PEPROCESS Process;
	PsLookupProcessByProcessId((HANDLE)Pid, &Process);

	__try
	{
		//分配内存
		buff1 = ExAllocatePoolWithTag((POOL_TYPE)0, BYTE_size, 1997);
		buff2 = buff1;
		*(int*)buff1 = 1;
		if (MmIsAddressValid((PVOID)VirtualAddress))
		{
			// 复制内存
			memcpy(buff2, VirtualAddress, BYTE_size);
		}
		else
		{
			return FALSE;
		}

		// 附加到要读写的进程
		KeStackAttachProcess((PRKPROCESS)Process, &KAPC);
		if (MmIsAddressValid((PVOID)Address))
		{
			// 判断地址是否可写
			ProbeForWrite(Address, BYTE_size, 1);
			// 复制内存
			memcpy(Address, buff2, BYTE_size);
		}
		else
		{
			return FALSE;
		}
		// 剥离附加的进程
		KeUnstackDetachProcess(&KAPC);
		ExFreePoolWithTag(buff2, 1997);
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		return FALSE;
	}
	return FALSE;
}

// 写入整数内存多级偏移
INT64 WIN10_WriteDeviationIntMemory(HANDLE Pid, LONG Base, DWORD offset[32], DWORD len, INT64 SetValue)
{
	INT64 Value = 0;
	LPCVOID pbase = (LPCVOID)Base;
	LPVOID rbuffer = (LPVOID)&Value;

	PEPROCESS Process;
	PsLookupProcessByProcessId((HANDLE)Pid, &Process);

	for (int x = len - 1; x >= 0; x--)
	{
		__try
		{
			KeReadProcessMemory(Process, pbase, rbuffer, 4);
			pbase = (LPCVOID)(Value + offset[x]);
		}
		__except (EXCEPTION_EXECUTE_HANDLER)
		{
			return 0;
		}
	}

	__try
	{
		KeReadProcessMemory(Process, pbase, rbuffer, 4);
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		return 0;
	}

	// 使用原函数写入
	BOOLEAN ref = WIN10_WriteProcessMemory(Pid, (void *)pbase, 4, &SetValue);
	if (ref == TRUE)
	{
		DbgPrint("[内核写成功] # 写入地址: %x \n", pbase);
		return 1;
	}
	return 0;
}

// 驱动卸载例程
VOID UnDriver(PDRIVER_OBJECT driver)
{
	DbgPrint("Uninstall Driver \n");
}

// 驱动入口地址
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	DbgPrint("Hello LyShark \n");

	DWORD PID = 4884;
	LONG PBase = 0x6566e0;
	LONG Size = 4;
	INT64 SetValue = 100;

	DWORD Offset[32] = { 0 };

	Offset[0] = 0x18;
	Offset[1] = 0x0;
	Offset[2] = 0x14;
	Offset[3] = 0x0c;

	// 写出内存数据
	INT64 write = WIN10_WriteDeviationIntMemory(PID, PBase, Offset, Size, SetValue);

	DbgPrint("PID: %d 基址: %p 偏移长度: %d \n", PID, PBase, Size);
	DbgPrint("[+] 1级偏移: %x \n", Offset[0]);
	DbgPrint("[+] 2级偏移: %x \n", Offset[1]);
	DbgPrint("[+] 3级偏移: %x \n", Offset[2]);
	DbgPrint("[+] 4级偏移: %x \n", Offset[3]);

	DbgPrint("[WriteMemory] 写出偏移数据: %d \n", SetValue);

	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

运行如上代码将在0x6566e0所在的基址上,将数据替换为100,实现效果图如下所示;

那么如何实现读写内存浮点数,字节集等多级偏移呢?

其实我们可以封装一个WIN10_ReadDeviationMemory函数,让其只计算得出偏移地址,而所需要写出的类型则根据自己的实际需求配合不同的写入函数完成,也就是将两者分离开,如下则是一段实现计算偏移的代码片段,该代码同样来自于本人的LyMemory驱动读写项目;

#include <ntifs.h>
#include <ntintsafe.h>
#include <windef.h>

// 普通Ke内存读取
NTSTATUS KeReadProcessMemory(PEPROCESS Process, PVOID SourceAddress, PVOID TargetAddress, SIZE_T Size)
{
	PEPROCESS SourceProcess = Process;
	PEPROCESS TargetProcess = PsGetCurrentProcess();
	SIZE_T Result;
	if (NT_SUCCESS(MmCopyVirtualMemory(SourceProcess, SourceAddress, TargetProcess, TargetAddress, Size, KernelMode, &Result)))
		return STATUS_SUCCESS;
	else
		return STATUS_ACCESS_DENIED;
}

// 读取多级偏移内存动态地址
DWORD64 WIN10_ReadDeviationMemory(HANDLE Pid, LONG Base, DWORD offset[32], DWORD len)
{
	INT64 Value = 0;
	LPCVOID pbase = (LPCVOID)Base;
	LPVOID rbuffer = (LPVOID)&Value;

	PEPROCESS Process;
	PsLookupProcessByProcessId((HANDLE)Pid, &Process);

	for (int x = len - 1; x >= 0; x--)
	{
		__try
		{
			KeReadProcessMemory(Process, pbase, rbuffer, 4);
			pbase = (LPCVOID)(Value + offset[x]);
		}
		__except (EXCEPTION_EXECUTE_HANDLER)
		{
			return 0;
		}
	}

	return pbase;
}

// 驱动卸载例程
VOID UnDriver(PDRIVER_OBJECT driver)
{
	DbgPrint("Uninstall Driver \n");
}

// 驱动入口地址
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	DbgPrint("Hello LyShark \n");

	DWORD PID = 4884;
	LONG PBase = 0x6566e0;
	LONG Size = 4;

	DWORD Offset[32] = { 0 };

	Offset[0] = 0x18;
	Offset[1] = 0x0;
	Offset[2] = 0x14;
	Offset[3] = 0x0c;

	// 写出内存数据
	DWORD64 offsets = WIN10_ReadDeviationMemory(PID, PBase, Offset, Size);

	DbgPrint("PID: %d 基址: %p 偏移长度: %d \n", PID, PBase, Size);
	DbgPrint("[+] 1级偏移: %x \n", Offset[0]);
	DbgPrint("[+] 2级偏移: %x \n", Offset[1]);
	DbgPrint("[+] 3级偏移: %x \n", Offset[2]);
	DbgPrint("[+] 4级偏移: %x \n", Offset[3]);

	DbgPrint("[CheckMemory] 计算偏移地址: %x \n", offsets);

	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

运行如上代码将动态计算出目前偏移地址的pbase实际地址,实现效果图如下所示;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/690326.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt绘图高级编程-绘制文本

注意&#xff1a;以下代码是在paintEvent函数中使用的&#xff0c;坐标是在文本的左下角。 1、设置字体样式 /*-----------1、设置字体样式-----------*///设置画家写字的字体//字体名&#xff0c; 字体大小&#xff0c;粗体&#xff0c;是否斜体QFont font( "楷体"…

芝奇幻锋戟Z5 RGB DDR5-7200 24GB内存评测:稳上7800MHz、温度只有56度

一、前言&#xff1a;7200MHz CL36高频内存仅需1.35V电压 在DDR4年代&#xff0c;三星B-Die是当之无愧的超频王者&#xff0c;而今DDR5已然成为主流&#xff0c;大家公认的最好超频的颗粒是SK海力士A-Die。 但并不是每一款采用了海力士A-Die颗粒的内存条都会有强悍的超频能力&a…

B+数的设计步骤

1.节点的结构&#xff08;如下图&#xff09; &#xff08;1&#xff09;键值对--key是标识&#xff1b;value是存储的具体数据 &#xff08;2&#xff09;节点的子节点--存储的是具体的子节点 &#xff08;3&#xff09;节点的后节点--标记后一个节点 &#xff08;4&#xff0…

9 MFC CFileDialog

// SystemWndDlg.cpp: 实现文件 //#include "pch.h" #include "framework.h" #include "SystemWnd.h" #include "SystemWndDlg.h" #include "afxdialogex.h"#ifdef _DEBUG #define new DEBUG_NEW #endif// CSystemWndDlg 对…

git提交忽略target文件

背景 项目如果没有设置.ignore文件&#xff0c;则我们的idea待提交区域有好多红色的新增的target文件、.iml文件等。 解决 本来未忽略前如下&#xff1a; 在.ignore文件中新增如下命令 #忽略所有.svn目录 .svn/ #忽略所有target目录 target/ #忽略所有.idea目录 .idea/ #…

C#,保持亮度的动态直方图均衡化(Brightness Preserving Dynamic Histogram Equalization:BPDHE)源代码

图像增强的主要目的是显示隐藏的图像细节&#xff0c;或者用新的动态范围增加图像对比度。直方图均衡&#xff08;HE&#xff09;是用于图像对比度增强的最流行的技术之一&#xff0c;因为HE在计算上快速且易于实现。HE通过基于输入灰度级的概率分布重新映射图像的灰度级来执行…

学生使用的台灯该怎么选择?学生台灯应该这样选

随着时代快速发展&#xff0c;目前我国近视人数达到了7亿&#xff0c;呈现低龄化趋势&#xff0c;儿童及青少年人数占了53.8%。而且现在的学生学业负担都很重&#xff0c;每个家长都不希望自己的孩子近视或加深近视了&#xff0c;都会想尽一切办法保护视力。而护眼台灯就成了家…

光伏储能电能管理系统解决方案蓄电池管理

概述 在我国新型电力系统中&#xff0c;新能源装机容量逐年提高&#xff0c;但是新能源比如光伏发电、风力发电是不稳定的能源&#xff0c;所以要维持电网稳定&#xff0c;促进新能源发电的消纳&#xff0c;储能将成为至关重要的一环&#xff0c;是分布式光伏、风电等新能源消…

怎么用ai作图?简单几步教会你ai绘画

当我和我的朋友们闲聊的时候&#xff0c;一个话题引起了我们的兴趣——更新社交媒体头像。其中有一个朋友提出&#xff0c;想要制作一个与真人无异、美观大方的头像&#xff0c;但是却不知道该如何下手。于是乎&#xff0c;我们开始讨论ai绘画头像软件。大家都纷纷表示听说过&a…

基于Java+SpringBoot+vue的实验室管理系统设计与实现

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

cubemx hal stm32 atgm336h GPS 北斗 定位 模块 驱动代码

代码部分 atgm336h.c #include "atgm336h.h" #include "stdio.h" #include "string.h"char rxdatabufer; u16 point1 0;_SaveData Save_Data; LatitudeAndLongitude_s g_LatAndLongData {.E_W 0,.N_S 0,.latitude 0.0,.longitude 0.0 };…

Docker网络架构三剑客CNM,Libnetwork和Driver

Docker网络架构主要由三部分组成&#xff1a;CNM&#xff0c;Libnetwork和Driver。 1.CNM CNM&#xff08;Container Network Model&#xff09;是一种网络模型&#xff0c;用于定义容器的网络架构和实现容器之间的通信。 这其中也有三要素&#xff1a; 沙盒&#xff1a;Sand…

基于matlab使用无限阵列分析对大型阵列中的互耦进行建模(附源码)

一、前言 此示例使用无限数组分析对大型有限数组进行建模。晶胞上的无限阵列分析揭示了特定频率下的扫描阻抗行为。此信息与隔离元件图案和阻抗的知识一起使用&#xff0c;以计算扫描元件图案。然后&#xff0c;使用数组中的每个元素都具有相同扫描元素模式的假设对大型有限数组…

造纸工厂配电室环境监控系统的应用案例与硬件选型

摘要&#xff1a;智能配电室环境监控系统可实现自动巡检、自动预警等功能&#xff0c;减少人员到现场巡视次数&#xff0c;能及早发现设备的潜在风险&#xff0c;迅速检测故障&#xff0c;节约维护保养时长&#xff0c;为配电生产检修、运行、各业务的标准化、规范化管理提供有…

1:即使设计-ui:尺寸和单位

一&#xff1a; 1: 一倍尺寸 378*812 2:二倍尺寸 750*1624 3:三倍尺寸 1125*2436 二&#xff1a;PX和PT px&#xff1a;物理像素 pt&#xff1a;逻辑像素 pt只存在一倍图中 在一倍图&#xff0c;ptpx&#xff0c;二倍图 1px2pt 三&#xff1a;DP和SP

AI开源路在何方丨2023智源大会精彩回顾

导读 当下&#xff0c;AI开源已经成为了人类开源创新的主战场&#xff0c;是超大规模人类智力协同的最佳组织形式。得益于开源协作持续不断地推进&#xff0c;AI在这个时代飞速发展。可以说如果没有开源社区建设&#xff0c;就不会有今天人工智能的成就。 在2023智源大会AI开源…

【python】基于multiprocessing.Pool实现python并行化的坑和解决方案

坑1&#xff1a;apply_async调用的子函数不执行或执行不彻底的解决方案 解决&#xff1a;使用apply_async时传入error_callback检查报错 from multiprocessing import Pooldef processFolder(idx, folders, o_dir):train_mesh TrainMeshes(folders)output_path os.path.join…

python小游戏——骰子猜大小

❄️作者介绍&#xff1a;奇妙的大歪❄️ &#x1f380;个人名言&#xff1a;但行前路&#xff0c;不负韶华&#xff01;&#x1f380; &#x1f43d;个人简介&#xff1a;云计算网络运维专业人员&#x1f43d; 前言 我们已经基本学完了&#xff0c;逻辑判断和循环的用法&#…

Maven历史版本的下载

Maven历史版本的下载 打开Maven官网https://maven.apache.org/ 点击Download 点击Maven 3 archives

持续优化 XView 性能,大促弹窗搭投实践 | 京东云技术团队

背景 618 大促来了&#xff0c;对于业务团队来说&#xff0c;最重要的事情莫过于各种大促营销。如会场、直播带货、频道内营销等等。而弹窗作为一个极其重要的强触达营销工具&#xff0c;通常用来渲染大促氛围、引流主会场、以及通过频道活动来提升频道复访等。因此&#xff0…