驱动开发: 封装内核级驱动读写

Posted 孤风洗剑

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了驱动开发: 封装内核级驱动读写相关的知识,希望对你有一定的参考价值。


内核级别的内存读写可用于绕过各类驱动保护,从而达到强制读写对端内存的目的,本人闲暇之余封装了一个驱动级的内核读写接口,使用此接口可实现对远程字节,字节集,整数,浮点数,多级偏移读写等。

项目地址:GitHub LyMemory

一款完全免费的内核级内存读写工具,可强制读写任意应用层进程内存数据,驱动工具目前支持读写整数,字节,字节集,单精度浮点数,双精度浮点数,多级偏移读写,取模块地址,分配远程内存等功能,读写效率高,速度快,兼容性好,使用时需自己签名或在测试模式下。

如下将简单介绍该内核读写工具各类API接口是如何调用的,鉴于驱动读写商业价值较大故暂时不放出源码(后期考虑)。

驱动读写首先要看的就是驱动支持的控制信号,如下是我封装的几个驱动控制器。

// 通用读写系列
#define IOCTL_IO_ReadProcessMemory        0x801
#define IOCTL_IO_WriteProcessMemory       0x802
#define IOCTL_IO_ReadDeviationIntMemory   0x803
#define IOCTL_IO_WriteDeviationIntMemory  0x804
#define IOCTL_IO_ReadProcessMemoryByte    0x805
#define IOCTL_IO_WriteProcessMemoryByte   0x806

// 全局读写系列
#define IOCTL_IO_SetPID                   CTL_CODE(FILE_DEVICE_UNKNOWN, 0x807, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_IO_ReadMemory               CTL_CODE(FILE_DEVICE_UNKNOWN, 0x808, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_IO_WriteMemory              CTL_CODE(FILE_DEVICE_UNKNOWN, 0x809, METHOD_BUFFERED, FILE_ANY_ACCESS)

// 模块操作系列
#define IOCTL_IO_GetModuleAddress         CTL_CODE(FILE_DEVICE_UNKNOWN, 0x810, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_IO_GetProcessID             CTL_CODE(FILE_DEVICE_UNKNOWN, 0x811, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_IO_GetSystemRoutineAddr     CTL_CODE(FILE_DEVICE_UNKNOWN, 0x812, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_IO_CreateAllocMemory        CTL_CODE(FILE_DEVICE_UNKNOWN, 0x813, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_IO_RemoveAllocMemory        CTL_CODE(FILE_DEVICE_UNKNOWN, 0x814, METHOD_BUFFERED, FILE_ANY_ACCESS)

// 版本升级后的新功能 2022-09-24
#define IOCTL_IO_ReadDeviationMemory    0x815

内核驱动读写类库在2022年9月24日升级了功能,函数列表功能一览。

传统读写函数是每次都会附加到进程中,这种方式效率较低,但也还是可以使用的。

// 读内存字节
BYTE ReadProcessMemoryByte(DWORD Pid, ULONG64 Address)

// 写内存字节
BOOL WriteProcessMemoryByte(DWORD Pid, ULONG64 Address, BYTE bytef)

// 读内存32位整数型
DWORD ReadProcessMemoryInt32(DWORD Pid, ULONG64 Address)

// 读内存64位整数型
DWORD ReadProcessMemoryInt64(DWORD Pid, ULONG64 Address)

// 写内存32位整数型
BOOL WriteProcessMemoryInt32(DWORD Pid, ULONG64 Address, DWORD write)

// 写内存64位整数型
BOOL WriteProcessMemoryInt64(DWORD Pid, ULONG64 Address, DWORD write)

// 读内存单精度浮点数
FLOAT ReadProcessMemoryFloat(DWORD Pid, ULONG64 Address)

// 读内存双精度浮点数
DOUBLE ReadProcessMemoryDouble(DWORD Pid, ULONG64 Address)

// 写内存单精度浮点数
BOOL WriteProcessMemoryFloat(DWORD Pid, ULONG64 Address, FLOAT write)

// 写内存双精度浮点数
BOOL WriteProcessMemoryDouble(DWORD Pid, ULONG64 Address, DOUBLE write)

// 读多级偏移32位整数型
INT32 ReadProcessDeviationInt32(ProcessDeviationIntMemory *read_offset_struct)

// 读多级偏移64位整数型
INT64 ReadProcessDeviationInt64(ProcessDeviationIntMemory *read_offset_struct)

// 写多级偏移32位整数型
BOOL WriteProcessDeviationInt32(ProcessDeviationIntMemory *write_offset_struct)

// 写多级偏移64位整数型
BOOL WriteProcessDeviationInt64(ProcessDeviationIntMemory *write_offset_struct)

// 读多级偏移32位内存地址
DWORD ReadDeviationMemory32(ProcessDeviationMemory *read_offset_struct)

// 读多级偏移64位内存地址
DWORD64 ReadDeviationMemory64(ProcessDeviationMemory *read_offset_struct)

// 读多级偏移字节型
BYTE ReadDeviationByte(ProcessDeviationMemory *read_offset_struct)

// 读多级偏移单精度浮点数
FLOAT ReadDeviationFloat(ProcessDeviationMemory *read_offset_struct)

// 写多级偏移字节型
BOOL WriteDeviationByte(ProcessDeviationMemory *write_offset_struct,BYTE write_byte)

// 写多级偏移单精度浮点数
BOOL WriteDeviationFloat(ProcessDeviationMemory *write_offset_struct,FLOAT write_float)

全局读写函数封装相对于传统驱动读写,虽然也传入PID但本质上可以SetPid只设置一次PID即可实现后续直接读写内存。

// 设置全局进程PID
BOOL SetPid(DWORD Pid)

// 全局读内存
BOOL Read(DWORD pid, ULONG64 address, T* ret)

// 全局写内存
BOOL Write(DWORD pid, ULONG64 address, T data)

// 读内存DWORD
void ReadMemoryDWORD(DWORD pid, ULONG64 addre, DWORD * ret)

// 读内存DWORD64
void ReadMemoryDWORD64(DWORD pid, ULONG64 addre, DWORD64 * ret)

// 读内存字节
void ReadMemoryBytes(DWORD pid, ULONG64 addre, BYTE **ret, DWORD sizes)

// 读内存浮点数
void ReadMemoryFloat(DWORD pid, ULONG64 addre, float* ret)

// 读内存双精度浮点数
void ReadMemoryDouble(DWORD pid, ULONG64 addre, double* ret)

// 写内存字节
void WriteMemoryBytes(DWORD pid, ULONG64 addre, BYTE * data, DWORD sizes)

// 写内存DWORD
void WriteMemoryDWORD(DWORD pid, ULONG64 addre, DWORD ret)

// 写内存DWORD64
void WriteMemoryDWORD64(DWORD pid, ULONG64 addre, DWORD64 ret)

// 写内存浮点数
void WriteMemoryFloat(DWORD pid, ULONG64 addre, float ret)

// 写内存双精度浮点数
void WriteMemoryDouble(DWORD pid, ULONG64 addre, double ret)

// 驱动读取进程模块基地址
DWORD64 GetModuleAddress(DWORD pid, std::string dllname)

// 根据进程名称获取进程PID
DWORD GetProcessID(std::string procname)

// 获取系统函数内存地址
DWORD64 GetSystemRoutineAddress(std::string funcname)

// 在对端分配内存空间
DWORD64 CreateRemoteMemory(DWORD length)

// 销毁对端内存
DWORD DeleteRemoteMemory(DWORD64 address, DWORD length)

内核读/写字节集: 对远端指定内存地址出读写字节集数组,该功能可用于强制代码注入等。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <Windows.h>
#include <LyMemoryKernel.h>

#pragma comment(lib,"user32.lib")
#pragma comment(lib,"advapi32.lib")

int main(int argc, char *argv[])

	// 驱动类
	cDrvCtrl DriveControl;

	// 安装驱动
	DriveControl.InstallAndRun();

	// 内存读字节集
	BYTE buffer[8] =  0 ;
	BYTE* bufferPtr = buffer;

	// 读
	DriveControl.ReadMemoryBytes(2564, 0x7713639c, &bufferPtr, sizeof(buffer));

	for (int x = 0; x < 8; x++)
	
		printf("读取字节: 0x%x \\n", buffer[x]);
	

	// 卸载驱动
	DriveControl.RemoveAndStop();
	system("pause");
	return 0;

内核读取字节集效果如下:

与读取对应的一个函数是写入,写入代码如下。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <Windows.h>
#include <LyMemoryKernel.h>

#pragma comment(lib,"user32.lib")
#pragma comment(lib,"advapi32.lib")

int main(int argc, char *argv[])

	// 驱动类
	cDrvCtrl DriveControl;

	// 安装驱动
	DriveControl.InstallAndRun();

	// 写内存字节集
	BYTE writebuff[8] =  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 ;
	DriveControl.WriteMemoryBytes(2564, 0x7713639c, writebuff, sizeof(writebuff));

	// 卸载驱动
	DriveControl.RemoveAndStop();
	system("pause");
	return 0;

写入后再次查看内存会发现已经变更了。

读写内核数值类型: 数值类型包括了,整数,64位整数,浮点数,双精度浮点等类型。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <Windows.h>
#include <LyMemoryKernel.h>

#pragma comment(lib,"user32.lib")
#pragma comment(lib,"advapi32.lib")

int main(int argc, char *argv[])

	// 驱动类
	cDrvCtrl DriveControl;

	// 安装驱动
	DriveControl.InstallAndRun();

	DWORD data;
	DWORD64 data64;
	FLOAT floats;
	DOUBLE doubles;

	// 读DWORD
	DriveControl.ReadMemoryDWORD(2564, 0x771362fc, &data);
	printf("dword = %d \\n", data);

	// 读DWORD64
	DriveControl.ReadMemoryDWORD64(2564, 0x771362fc, &data64);
	printf("dword = %d \\n", data);
	printf("dword = %d \\n", data+4);

	// 读取Float
	DriveControl.ReadMemoryFloat(2564, 0x771362fc, &floats);
	printf("float = %f \\n", floats);

	// 读double
	DriveControl.ReadMemoryDouble(2564, 0x771362fc, &doubles);
	printf("double = %f \\n", doubles);

	// 卸载驱动
	DriveControl.RemoveAndStop();
	system("pause");
	return 0;

读数值类型效果:

驱动写数值类型与读取类似,这里给出如何应用的案例。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <Windows.h>
#include <LyMemoryKernel.h>

#pragma comment(lib,"user32.lib")
#pragma comment(lib,"advapi32.lib")

int main(int argc, char *argv[])

	// 驱动类
	cDrvCtrl DriveControl;

	// 安装驱动
	DriveControl.InstallAndRun();

	DWORD data;
	DWORD64 data64;
	FLOAT floats;
	DOUBLE doubles;

	// 写DWORD
	DriveControl.WriteMemoryDWORD(2564, 0x771362fc, 100);

	// 写DWORD64
	DriveControl.WriteMemoryDWORD64(2564, 0x771362fc, 100);

	// 写Float
	DriveControl.WriteMemoryFloat(2564, 0x771362fc, 10.5);

	// 写double
	DriveControl.WriteMemoryDouble(2564, 0x771362fc, 100.5);

	// 卸载驱动
	DriveControl.RemoveAndStop();
	system("pause");
	return 0;

结构体版读整数: 传递结构体解析参数读取。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <Windows.h>
#include <LyMemoryKernel.h>

#pragma comment(lib,"user32.lib")
#pragma comment(lib,"advapi32.lib")

int main(int argc, char *argv[])

	// 驱动类
	cDrvCtrl DriveControl;

	// 安装驱动
	DriveControl.InstallAndRun();

	// 写
	ProcessIntMemory write_struct;

	write_struct.pid = 6348;                // 指定Pid
	write_struct.address = 0x748c405c;         // 地址
	write_struct.bytes_toread = 4;          // 写入长度4字节
	write_struct.data = 999;                // 写入数据
	DriveControl.IoControl(0x802, &write_struct, sizeof(write_struct), 0, 0, 0);

	// 读
	ProcessIntMemory read_struct;

	read_struct.pid = 6348;                // 指定Pid
	read_struct.address = 0x748c405c;         // 地址
	read_struct.bytes_toread = 2;          // 读取长度4字节
	read_struct.data = 0;                  // 读取的数据

	DriveControl.IoControl(0x801, &read_struct, sizeof(read_struct), &read_struct, sizeof(read_struct), 0);
	std::cout << "read: " << (int)read_struct.data << std::endl;

	// 卸载驱动
	DriveControl.RemoveAndStop();
	system("pause");
	return 0;

结构版本与类内函数调用方式不同,结构板需要手动调用控制器。

结构版读写字节集: 同理与整数读写一致,需要调用控制器,传入控制信号以及结构体。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <Windows.h>
#include <LyMemoryKernel.h>

#pragma comment(lib,"user32.lib")
#pragma comment(lib,"advapi32.lib")

int main(int argc, char *argv[])

	// 驱动类
	cDrvCtrl DriveControl;

	// 安装驱动
	DriveControl.InstallAndRun();

	// 写
	ProcessByteMemory write_byte_struct;

	write_byte_struct.pid = 6348;
	write_byte_struct.base_address = 0x76295a04;
	write_byte_struct.OpCode =  0x90 ;

	DriveControl.IoControl(0x806, &write_byte_struct, sizeof(write_byte_struct), 0, 0, 0);

	// 读
	ProcessByteMemory read_byte_struct;
	BYTE read_byte = 0;

	for (int x = 0; x < 10; x++)
	
		read_byte_struct.pid = 6348;                       // 指定Pid
		read_byte_struct.base_address = 0x76295a04 + x;       // 地址
		DriveControl.IoControl(0x805, &read_byte_struct, sizeof(read_byte_struct), &read_byte, sizeof(read_byte), 0);
		if (read_byte == 0)
		
			break;
		
		printf("0x%02X ", read_byte);
	

	// 卸载驱动
	DriveControl.RemoveAndStop();
	system("pause");
	return 0;

写入后在读取,效果如下:

结构版多级偏移读写: 针对整数型读写的封装,增加了多级偏移读写机制。读写多级偏移整数型(最大32级)

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <Windows.h>
#include <LyMemoryKernel.h>

#pragma comment(lib,"user32.lib")
#pragma comment(lib,"advapi32.lib")

int main(int argc, char *argv[])

	cDrvCtrl DriveControl;
	DriveControl.InstallAndRun();

	// 读
	ProcessDeviationIntMemory read_offset_struct;

	read_offset_struct.pid = 1468;               // 进程PID
	read_offset_struct.base_address = 0x601660;   // 基地址
	read_offset_struct.offset_len = 4;           // 偏移长度
	read_offset_struct.data = 0;                 // 读入的数据
	read_offset_struct.offset[0] = 0x18;            // 一级偏移
	read_offset_struct.offset[1] = 0x0;         // 二级偏移
	read_offset_struct.offset[2] = 0x14;
	read_offset_struct.offset[3] = 0x0c;

	DriveControl.IoControl(0x803, &read_offset_struct, sizeof(read_offset_struct), &read_offset_struct, sizeof(read_offset_struct)

驱动开发:内核封装TDI网络通信接口

以上是关于驱动开发: 封装内核级驱动读写的主要内容,如果未能解决你的问题,请参考以下文章

Windows驱动开发-内核常用内存函数

Unix/Linux环境C编程新手教程(12) openSUSECCPP以及Linux内核驱动开发环境搭建

5Linux内核模块开发

linux 驱动模块开发初体验

驱动开发:内核CR3切换读写内存

求教怎么学习linux内核驱动