Skip to content
forked from kalikex1/LyMemory

一款免费的内核级内存读写工具,可突破驱动保护,强制读写任意应用层进程内存数据。 A free kernel level memory reading and writing tool, which can break through driver protection and force reading and writing memory data of any application layer process.

License

Notifications You must be signed in to change notification settings

Aopodo/LyMemory

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

内核级内存读写驱动


image


Build status Crowdin OSCS Status


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

  • 请勿用于非法用途,上号很容易拉闸,谨慎使用!
    • 问:你这个东西是什么读写原理? 答:目前支持物理页,CR3,内存拷贝,MDL(默认)
    • 问:你这个东西会拉闸吗? 答:会,拉闸的速度取决于你读写的是什么游戏。
    • 问:拉闸后我该怎么办?答:等着封号10年,建议另起炉灶!

兼容版本:Windows 10.0.18363


免责声明

该项目仅用于安全技术研究与交流,禁止非法读写(突破)网络游戏保护,不得用于商业用途,本人不承担任何法律责任,另外不要拿我的驱动和商业驱动相比,毕竟那个是按天收费的,我是无私奉献只为点个Start交个朋友,请勿对我的作品二次包装出售,安全圈子就这么小,以后有幸见到,我们还是老乡见老乡,两眼泪汪汪。


读写函数预览

非持续读写函数,读写时需要传入进程PID以及读写地址,此类读写方式适合非持续访问,常用于一次性改写,一次性读取的场景,目前非持续读写包括了如下20个读写子功能。

导出函数 函数作用
BOOL SwitchDriver(PCHAR pSwitchName) 切换读写模式
BYTE ReadProcessMemoryByte(DWORD Pid, ULONG64 Address) 读内存字节
BOOL WriteProcessMemoryByte(DWORD Pid, ULONG64 Address, BYTE bytef) 写内存字节
DWORD ReadProcessMemoryInt32(DWORD Pid, ULONG64 Address) 读内存32位整数型
DWORD ReadProcessMemoryInt64(DWORD Pid, ULONG64 Address) 读内存64位整数型
BOOL WriteProcessMemoryInt32(DWORD Pid, ULONG64 Address, DWORD write) 写内存32位整数型
BOOL WriteProcessMemoryInt64(DWORD Pid, ULONG64 Address, DWORD write) 写内存64位整数型
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) 写内存双精度浮点数
INT32 ReadProcessDeviationInt32(ProcessDeviationIntMemory *read_offset_struct) 读多级偏移32位整数
INT64 ReadProcessDeviationInt64(ProcessDeviationIntMemory *read_offset_struct) 读多级偏移64位整数
BOOL WriteProcessDeviationInt32(ProcessDeviationIntMemory *write_offset_struct) 写多级偏移32位整数
BOOL WriteProcessDeviationInt64(ProcessDeviationIntMemory *write_offset_struct) 写多级偏移64位整数
DWORD ReadDeviationMemory32(ProcessDeviationMemory *read_offset_struct) 读多级偏移32位内存
DWORD64 ReadDeviationMemory64(ProcessDeviationMemory *read_offset_struct) 读多级偏移64位内存
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号,后期的调用将不需要再传入进程PID号,此类读写适合长期读,某些参数例如人物数组,坐标等,需要持续不间断读取。

导出函数 函数作用
BOOL SetPid(DWORD Pid) 设置全局进程PID
BOOL Read(DWORD pid, ULONG64 address, T* ret) 全局读内存
BOOL Write(DWORD pid, ULONG64 address, T data) 全局写内存
void ReadMemoryDWORD(DWORD pid, ULONG64 addre, DWORD * ret) 读内存DWORD
void ReadMemoryDWORD64(DWORD pid, ULONG64 addre, DWORD64 * ret) 读内存DWORD64
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) 写内存字节
void WriteMemoryDWORD(DWORD pid, ULONG64 addre, DWORD ret) 写内存DWORD
void WriteMemoryDWORD64(DWORD pid, ULONG64 addre, DWORD64 ret) 写内存DWORD64
void WriteMemoryFloat(DWORD pid, ULONG64 addre, float ret) 写内存浮点数
void WriteMemoryDouble(DWORD pid, ULONG64 addre, double ret) 写内存双精度浮点数
DWORD64 GetModuleAddress(DWORD pid, std::string dllname) 驱动读取进程模块基地址
DWORD GetProcessID(std::string procname) 根据进程名称获取进程PID
DWORD64 GetSystemRoutineAddress(std::string funcname) 获取系统函数内存地址
DWORD64 CreateRemoteMemory(DWORD length) 在对端分配内存空间
DWORD DeleteRemoteMemory(DWORD64 address, DWORD length) 销毁对端内存

动态调用驱动

驱动读写目前支持两种调用模式,使用Engine.dll模块可动态调用驱动功能,如下图所示,如果用户采用动态调用模式则需要首先使用LoadLibrary加载该引擎,通过GetProcAddress函数拿到内存指针,之后才能调用功能。

image

项目中的dllexport.h以及struct.h是用于参考的调用函数定义,为了能直观的演示功能,我们以内核读取模块基地址,内存读写字节,内存字节反汇编,读写多级指针,四个功能作为演示,以让用户能够更好的理解。

在开始之前安装驱动都是必须要做的,通过调用Engine.dll模块实现对LyMemory.sys驱动的安装与卸载很容易,如下代码即可实现动态加载。

#include <iostream>
#include <Windows.h>

// 定义安装与卸载驱动
typedef void(*InstallDriver)();
typedef void(*RemoveDriver)();

int main(int argc, char *argv[])
{
	// 动态加载
	HMODULE hmod = LoadLibrary(L"Engine32.dll");

	// 获取到函数地址
	InstallDriver InstallDrivers = (InstallDriver)GetProcAddress(hmod, "InstallDriver");
	RemoveDriver RemoveDrivers = (RemoveDriver)GetProcAddress(hmod, "RemoveDriver");
	
	// 安装驱动
	InstallDrivers();

	Sleep(5000);

	// 卸载驱动
	RemoveDrivers();
	
	return 0;
}

内核读取模块基地址: 内核中强制读取指定进程中模块的基地址。

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

// 定义安装与卸载驱动
typedef void(*InstallDriver)();
typedef void(*RemoveDriver)();

typedef DWORD64 (*GetModuleAddress)(DWORD pid, std::string dllname);

int main(int argc, char *argv[])
{
	// 动态加载驱动
	HMODULE hmod = LoadLibrary(L"Engine32.dll");

	InstallDriver InstallDrivers = (InstallDriver)GetProcAddress(hmod, "InstallDriver");
	RemoveDriver RemoveDrivers = (RemoveDriver)GetProcAddress(hmod, "RemoveDriver");

	InstallDrivers();

	// 读取模块基址
	GetModuleAddress get_module_address = (GetModuleAddress)GetProcAddress(hmod, "GetModuleAddress");

	// 调用
	DWORD64 address = get_module_address(6764, "user32.dll");
	printf("dllbase = 0x%016I64x \n", address);

	getchar();
	RemoveDrivers();
	return 0;
}

user32.dll模块为例,读取效果如下所示;

image

内存读写字节: 以内存读取作为第一个演示对象,动态调用ReadProcessMemoryByte可以这样来写,首先定义typedef动态指针,并通过GetProcAddress函数得到内存地址,最后调用指针read_process_memory_byte实现读取内存字节的功能。

#include <iostream>
#include <Windows.h>

// 定义安装与卸载驱动
typedef void(*InstallDriver)();
typedef void(*RemoveDriver)();

// 读内存字节
typedef BYTE(*ReadProcessMemoryByte)(DWORD pid, ULONG64 address);

int main(int argc, char *argv[])
{
	// 动态加载驱动
	HMODULE hmod = LoadLibrary(L"Engine32.dll");

	InstallDriver InstallDrivers = (InstallDriver)GetProcAddress(hmod, "InstallDriver");
	RemoveDriver RemoveDrivers = (RemoveDriver)GetProcAddress(hmod, "RemoveDriver");

	InstallDrivers();

	// 得到内存地址
	ReadProcessMemoryByte read_process_memory_byte = \
		(ReadProcessMemoryByte)GetProcAddress(hmod, "ReadProcessMemoryByte");

	// 调用得到数据
	BYTE ref = read_process_memory_byte(6764, 0x0057e070);

	printf("输出数据:%x | 十进制:%d \n", ref, ref);

	getchar();
	RemoveDrivers();
	return 0;
}

运行这段代码,即可得到进程PID为6764地址0x0057e070处一个字节的数据,如下所示;

image

内存字节反汇编: 读内存字节功能不仅可以用于读取内存中的数值,配合capstone反汇编引擎可以实现对特定区域的反汇编。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <Windows.h>
#include <inttypes.h>
#include <capstone\capstone.h>

#pragma comment(lib,"capstone32.lib")

// 定义安装与卸载驱动
typedef void(*InstallDriver)();
typedef void(*RemoveDriver)();

// 读内存字节
typedef BYTE(*ReadProcessMemoryByte)(DWORD pid, ULONG64 address);

int main(int argc, char *argv[])
{
	// 动态加载驱动
	HMODULE hmod = LoadLibrary(L"Engine32.dll");

	InstallDriver InstallDrivers = (InstallDriver)GetProcAddress(hmod, "InstallDriver");
	RemoveDriver RemoveDrivers = (RemoveDriver)GetProcAddress(hmod, "RemoveDriver");

	InstallDrivers();

	// 得到内存地址
	ReadProcessMemoryByte read_process_memory_byte = \
		(ReadProcessMemoryByte)GetProcAddress(hmod, "ReadProcessMemoryByte");


	BYTE arr[1024] = { 0 };

	for (size_t i = 0; i < 1023; i++)
	{
		BYTE by = read_process_memory_byte(6764, 0x005800b8 + i);

		arr[i] = by;
	}

	csh handle;
	cs_insn *insn;
	size_t count;

	int size = 1023;

	// 打开句柄
	if (cs_open(CS_ARCH_X86, CS_MODE_32, &handle) != CS_ERR_OK)
	{
		return 0;
	}

	// 反汇编代码,地址从0x1000开始,返回总条数
	count = cs_disasm(handle, (unsigned char *)arr, size, 0x402c00, 0, &insn);

	if (count > 0)
	{
		size_t index;
		for (index = 0; index < count; index++)
		{
			for (int x = 0; x < insn[index].size; x++)
			{
				// printf("机器码: %d -> %02X \n", x, insn[index].bytes[x]);
			}

			printf("地址: 0x%"PRIx64" | 长度: %d 反汇编: %s %s \n", \
			insn[index].address, insn[index].size, insn[index].mnemonic, insn[index].op_str);
		}

		cs_free(insn, count);
	}
	else
	{
		printf("反汇编返回长度为空 \n");
	}

	cs_close(&handle);

	getchar();
	RemoveDrivers();
	return 0;
}

如上代码我们反汇编进程内0x005800b8地址,向下反汇编1024字节,输出反汇编效果如下;

image

读写多级指针: 读取整数浮点数与读字节一致这里不再演示了,重点看下多级偏移如何读写,读取多级偏移需要动态调用ReadProcessDeviationInt32函数。

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

// 定义安装与卸载驱动
typedef void(*InstallDriver)();
typedef void(*RemoveDriver)();

// 读写内存偏移整数型
typedef struct
{
	DWORD pid;
	ULONG64 base_address;
	DWORD offset[32];
	DWORD offset_len;
	INT64 data;
}ProcessDeviationIntMemory;

// 定义指针
typedef INT32(*ReadProcessDeviationInt32)(ProcessDeviationIntMemory);

int main(int argc, char *argv[])
{
	// 动态加载驱动
	HMODULE hmod = LoadLibrary(L"Engine32.dll");

	InstallDriver InstallDrivers = (InstallDriver)GetProcAddress(hmod, "InstallDriver");
	RemoveDriver RemoveDrivers = (RemoveDriver)GetProcAddress(hmod, "RemoveDriver");

	InstallDrivers();

	// 读取多级偏移整数型
	ReadProcessDeviationInt32 read_process_deviation_int32 = (ReadProcessDeviationInt32) \
		GetProcAddress(hmod, "ReadProcessDeviationInt32");

	ProcessDeviationIntMemory read_memory = { 0 };

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

	DWORD ref = read_process_deviation_int32(read_memory);

	printf("读取参数: %d \n", ref);

	getchar();
	RemoveDrivers();
	return 0;
}

读取多级偏移效果如下:

image


静态调用驱动

与动态调用相比,静态库则需要在编程时使用特定的库文件,目前LyMemory只提供了64位库文件,编译程序时也必须使用x64模式,使用时需要手动引用到项目内,至于如何引用到项目中此处就不再赘述了。

相比于动态加载来说,静态库调用就方便了许多,一般可以直接使用如下的方式实现调用,如下过程看起来还是有些复杂,不过你可以将其整合起来封装成Memory.InstallAndRun()这可以为后期的调用提供便利。

#include <LyMemoryLib.h>

#pragma comment(lib,"LyMemoryLib.lib")

int main(int argc, char* argv[])
{
	LyMemoryDrvCtrl Memory;

	char szSysFile[MAX_PATH] = { 0 };
	char szSvcLnkName[] = "LyMemory";;
	BOOL ref = FALSE;

	// 获取完整路径
	Memory.GetAppPath(szSysFile);
	strcat(szSysFile, "LyMemory.sys");
	printf("路径: %s \n", szSysFile);

	// 安装驱动
	ref = Memory.Install(szSysFile, szSvcLnkName, szSvcLnkName);
	printf("状态: %d \n", ref);

	// 启动驱动
	ref = Memory.Start();
	printf("状态: %d \n", ref);

	ref = Memory.Open("\\\\.\\LyMemory");
	printf("状态: %d \n", ref);

	// 关闭移除驱动
	ref = Memory.Stop();
	ref = Memory.Remove();
	printf("状态: %d \n", ref);

	getchar();
	return 0;
}

程序运行后则会输出驱动具体路径以及安装状态,安装成功即可看到打印信息。

image

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

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

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

int main(int argc, char *argv[])
{
	// 驱动类
	LyMemoryDrvCtrl Memory;

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

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

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

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

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

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

image

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

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

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

int main(int argc, char *argv[])
{
	// 驱动类
	LyMemoryDrvCtrl Memory;

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

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

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

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

image

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

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

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

int main(int argc, char *argv[])
{
	// 驱动类
	LyMemoryDrvCtrl Memory;

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

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

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

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

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

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

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

读数值类型效果:

image

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

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

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

int main(int argc, char *argv[])
{
	// 驱动类
	LyMemoryDrvCtrl Memory;

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

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

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

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

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

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

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

内核读取模块基地址: 内核中强制读取指定进程中模块的基地址。

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

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

int main(int argc, char *argv[])
{
	LyMemoryDrvCtrl Memory;
	Memory.InstallAndRun();

	DWORD64 dllbase = Memory.GetModuleAddress(952, "user32.dll");
	printf("dllbase = 0x%016I64x \n", dllbase);

	Memory.RemoveAndStop();
	system("pause");
	return 0;
}

读取效果如下:

image

根据进程名得到进程PID: 传入进程名,获取到该进程的PID序号。

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

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

int main(int argc, char *argv[])
{
	LyMemoryDrvCtrl Memory;
	Memory.InstallAndRun();

	DWORD pid = Memory.GetProcessID("dbgview64.exe");
	printf("进程PID: %d \n", pid);

	Memory.RemoveAndStop();
	system("pause");
	return 0;
}

效果如下:

image

获取系统函数内存地址: 获取SSDT内核函数的内存地址。

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

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

int main(int argc, char *argv[])
{
	LyMemoryDrvCtrl Memory;
	Memory.InstallAndRun();

	DWORD64 addr = Memory.GetSystemRoutineAddress("NtReadFile");
	printf("模块地址: 0x%016I64x \n", addr);

	Memory.RemoveAndStop();
	system("pause");
	return 0;
}

效果如下:

image

开辟释放堆空间: 在对端内存中开辟,或者释放堆空间,带有读写执行属性。

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

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

int main(int argc, char *argv[])
{
	LyMemoryDrvCtrl Memory;
	Memory.InstallAndRun();

	// 设置全局PID
	Memory.SetPid(952);

	// 开辟空间
	DWORD64 ref = Memory.CreateRemoteMemory(1024);
	printf("create = %x \n", ref);

	DWORD del_flag = Memory.DeleteRemoteMemory(ref, 1024);
	printf("del flag = %d \n", del_flag);

	Memory.RemoveAndStop();
	system("pause");
	return 0;
}

效果如下:

image

传统模式读写封装: 传统模式读写封装函数可对整数,浮点数,字节进行灵活读写。

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

int main(int argc, char *argv[])
{
	LyMemoryDrvCtrl Memory;
	Memory.InstallAndRun();

	DWORD ref = Memory.ReadProcessMemoryInt32(6056, 0x003AF4CC);
	printf("驱动读取:value = %d \n", ref);

	DWORD64 dref = Memory.ReadProcessMemoryInt64(6056, 0x003AF4CC);
	printf("驱动读取:value64 = %d \n", dref);


	FLOAT float_ref = Memory.ReadProcessMemoryFloat(6056, 0x01A1BC90);
	printf("驱动读取:value = %f \n", float_ref);

	FLOAT double_ref = Memory.ReadProcessMemoryDouble(6056, 0x01A1BC90);
	printf("驱动读取:value = %f \n", double_ref);

	BYTE byf = Memory.ReadProcessMemoryByte(6056, 0x01A1BC90);
	printf("驱动读取:value = %x \n", byf);

	for (size_t i = 0; i < 10; i++)
	{
		BYTE byf1 = Memory.ReadProcessMemoryByte(6056, 0x01A1BC90 + i);
		printf("驱动读取:value = %x \n", byf1);
	}

	system("pause");
	return 0;
}

读取效果如下:

image

写入功能与读取一致,这里以读写整数为案例。

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

int main(int argc, char *argv[])
{
	LyMemoryDrvCtrl Memory;
	Memory.InstallAndRun();

	// 写出9999
	Memory.WriteProcessMemoryInt32(6056, 0x003AF4CC, 9999);

	// 读取测试
	DWORD ref = Memory.ReadProcessMemoryInt32(6056, 0x003AF4CC);
	printf("驱动读取:value = %d \n", ref);

	system("pause");
	return 0;
}

写出效果如下:

image

内存多级偏移读写: 此功能并不是读写偏移中的数据,而是通过基地址计算出动态地址的一个函数,后续的读写可以自定义操作。

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

int main(int argc, char *argv[])
{
	LyMemoryDrvCtrl Memory;
	Memory.InstallAndRun();

	ProcessDeviationMemory read_offset_struct = { 0 };

	read_offset_struct.pid = 3124;                  // 进程PID
	read_offset_struct.base_address = 0x6566e0;     // 基地址
	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;            // 四级

	// 定位到动态地址
	DWORD ref = Memory.ReadDeviationMemory32(&read_offset_struct);

	printf("计算出基地址:0x%x \n", ref);

	system("pause");
	return 0;
}

定位内存地址如下:

image

内存整数多级偏移读写: 一个简单的案例实现对内存整数型偏移读写。

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

int main(int argc, char *argv[])
{
	LyMemoryDrvCtrl Memory;
	Memory.InstallAndRun();

	// 写入内存偏移地址
	ProcessDeviationIntMemory write_offset_struct = { 0 };

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

	// 写出
	Memory.WriteProcessDeviationInt32(&write_offset_struct);

	// 读取写入后的地址
	ProcessDeviationIntMemory read_offset_struct = { 0 };

	read_offset_struct.pid = 3124;                // 进程PID
	read_offset_struct.base_address = 0x6566e0;   // 基地址
	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;

	// 读入偏移整数
	DWORD ref = Memory.ReadProcessDeviationInt32(&read_offset_struct);

	printf("当前偏移内的数据:%d \n", ref);

	system("pause");
	return 0;
}

读写效果如下:

image

读取多级偏移字节型: 读取偏移数据内的字节数据,可循环多次读写。

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

int main(int argc, char *argv[])
{
	LyMemoryDrvCtrl Memory;
	Memory.InstallAndRun();

	ProcessDeviationMemory read_offset_struct = { 0 };

	read_offset_struct.pid = 3124;               // 进程PID
	read_offset_struct.base_address = 0x6566e0;  // 基地址
	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;

	// 读取多级偏移字节
	DWORD ref = Memory.ReadDeviationByte(&read_offset_struct);
	printf("%x \n", ref);


	for (size_t i = 0; i < 10; i++)
	{
		read_offset_struct.pid = 3124;                    // 进程PID
		read_offset_struct.base_address = 0x6566e0 + i;   // 基地址
		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;

		// 读取多级偏移字节
		DWORD ref = Memory.ReadDeviationByte(&read_offset_struct);
		printf("%x ", ref);

	}

	system("pause");
	return 0;
}

读取效果如下:

image

写入多级偏移字节型: 如读取一致,传入偏移,以及写出的字节即可替代目标字节。

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

int main(int argc, char *argv[])
{
	LyMemoryDrvCtrl Memory;
	Memory.InstallAndRun();

	ProcessDeviationMemory write = { 0 };

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

	// 写内存字节
	Memory.WriteDeviationByte(&write, 0x90);

	ProcessDeviationMemory read_offset_struct = { 0 };

	read_offset_struct.pid = 3124;                 // 进程PID
	read_offset_struct.base_address = 0x6566e0;    // 基地址
	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;

	// 读取多级偏移字节
	BYTE ref = Memory.ReadDeviationByte(&read_offset_struct);
	printf("读出数据:%x \n", ref);

	system("pause");
	return 0;
}

写出后,原始指针失效:

image

读取字节并反汇编: 运用反汇编引擎可实现对读出字节反汇编输出。

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

#include <inttypes.h>
#include <capstone/capstone.h>

#pragma comment(lib,"capstone32.lib")

int main(int argc, char *argv[])
{
	LyMemoryDrvCtrl Memory;
	Memory.InstallAndRun();


	BYTE arr[1024] = { 0 };

	for (size_t i = 0; i < 1023; i++)
	{
		BYTE by = Memory.ReadProcessMemoryByte(3344, 0x402c00 + i);

		arr[i] = by;
	}

	csh handle;
	cs_insn *insn;
	size_t count;

	int size = 1023;

	printf("By: LyShark \n\n");
	// 打开句柄
	if (cs_open(CS_ARCH_X86, CS_MODE_32, &handle) != CS_ERR_OK)
	{
		return 0;
	}

	// 反汇编代码,地址从0x1000开始,返回总条数
	count = cs_disasm(handle, (unsigned char *)arr, size, 0x402c00, 0, &insn);

	if (count > 0)
	{
		size_t index;
		for (index = 0; index < count; index++)
		{
			for (int x = 0; x < insn[index].size; x++)
			{
				// printf("机器码: %d -> %02X \n", x, insn[index].bytes[x]);
			}

			printf("地址: 0x%"PRIx64" | 长度: %d 反汇编: %s %s \n", \
			insn[index].address, insn[index].size, insn[index].mnemonic, insn[index].op_str);
		}

		cs_free(insn, count);
	}
	else
	{
		printf("反汇编返回长度为空 \n");
	}

	cs_close(&handle);
	system("pause");
	return 0;
}

反汇编效果:

image


项目地址

https://github.com/lyshark/LyMemory

About

一款免费的内核级内存读写工具,可突破驱动保护,强制读写任意应用层进程内存数据。 A free kernel level memory reading and writing tool, which can break through driver protection and force reading and writing memory data of any application layer process.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C++ 94.2%
  • C 5.8%