当前位置: 首页 > news >正文

c++辅助修改游戏内存

打印程序目标地址附近内存

#include <stdio.h>   // printf、scanf 所需头文件
#include <sys/ptrace.h>  // ptrace 系统调用头文件
#include <sys/types.h>   // 部分系统下 ptrace 依赖的类型定义int main(void)
{printf("Ptrace\n");// 输入目标进程 PIDint pid;printf("please input pid:");scanf("%d", &pid);// 输入要读取的内存地址(十六进制)long address;printf("please input address:");scanf("%lX", &address);  // %lX 匹配 long 类型的十六进制输入// 附加到目标进程long ret = ptrace(PTRACE_ATTACH, pid, NULL, NULL);printf("PTRACE_ATTACH:%d\n", ret);// 读取目标进程内存数据print("%X",address)int num = 40;for(int i = 0; i < num; i++){ret = ptrace(PTRACE_PEEKDATA, pid, address, NULL);printf("%d\t", ret);  // 输出读取的内存值(十进制)address += 0x4;if((i+1)%4==0){//每输出4个地址,便输出一个换行。print("\n");if(i != (num-1)){print("%X",address);}}}// 与目标进程分离ret = ptrace(PTRACE_DETACH, pid, NULL, NULL);printf("PTRACE_DETACH:%d\n", ret);  // 补充原代码遗漏的分离结果打印return 0;
}

常用函数

ptrace()函数

ptrace(PTRACE_POKEDATA,pid,address,data);//写入数据

proc函数

int main(void)
{char * mem_path = "/proc/30044/mem";int fd = open(mem_path,O_RDWR);long int address = 0xBCF5D83C;//读取地址int res = 0;lseek(fd,address,SEEK_SET);read(fd,&res,sizeof(int));print("lX read int %d\n",address,res);close(fd);return 0;
}

Leek函数

lseek(mem_file, addr, SEEK_SET)

mem_file对应一个 /proc/[pid]/mem

调用 lseek(mem_file, addr, SEEK_SET) 后:
后续 read(mem_file, ...) 会读取进程虚拟地址 addr 处的数据。
后续 write(mem_file, ...) 会修改进程虚拟地址 addr 处的内容(需权限)。

proc读取libc相关地址

软件加载libc时,libc存放的位置/proc/pid/maps,里面有libc加载到的地址。

addrBegin-addrEnd     读写权限        地址信息使用指令筛选
grep target_libc_name /proc/pid/maps

int main(){mem_file = open ("/proc/6312/mem",O_WORD);FILE *libnative = popen("grep libnative.so /proc/6312/maps","r");char temp[10];int i = 0;int ch = fgetc("libnative");while(ch != '-'){temp[i] = ch;ch = fgetc("libnative");i+=1;}temp[i]='\0';unintptr_t addr;sscanf(tmp,"%lx",&addr);    // 将char类型转换为16进制}

process_vm

syscall(__NR_process_vm_readv,30044);//参数:系统调用函数名,被调函数参数(pid)

MFC界面辅助编写

MFC编写注意事项

  • 窗口句柄注意不要和已知软件名称重复。

调试信息

弹窗提示

CString msg;  // 定义字符串变量
msg.Format(_T("成功获取PID:%d"), pid);
AfxMessageBox(msg);
AfxMessageBox(_T("获取 进程句柄 失败"));

C++编写代码读取内存地址

项目创建

使用VS Studio:创建新项目-> c++ ->MFC项目
VS安装MFC


弹出来的选项:
应用程序类型:基于对话框
使用MFC:在静态库文中使用MFC

项目创建完成后,主对话框位置:资源文件->MFCApplication1.rc,双击,MFCApplication1->Dialog->IDD_MFCAPPLICATION1_DIALOG。

添加选择框和编辑框和按钮
使用static Text,和Edit Control,Button

设置窗口标题
右键窗口空白部分,选择属性。选择外观->描述文字

编辑框添加变量
右键编辑框->添加变量->输入变量名称,类型默认即可。 // 后续用这个名字来操纵编辑框

给按钮添加事件
双击按钮

void CMFCApplication1Dlg::OnBnClickedButton1()
{HWND 窗口句柄 = ::FindWindow(NULL, L"诛仙");    //找窗口句柄if (窗口句柄 == NULL){// 未找到窗口:输出调试信息AfxMessageBox(_T("未找到标题为“诛仙”的窗口!"));  // 弹窗提示OutputDebugString(_T("FindWindow 失败:未找到“诛仙”窗口\n"));  // 输出到调试窗口return;  // 若未找到,可提前退出函数,避免后续无效操作}else{// 找到窗口:输出成功信息(可选)AfxMessageBox(_T("成功找到“诛仙”窗口!"));OutputDebugString(_T("FindWindow 成功:已找到“诛仙”窗口\n"));}DWORD pid;GetWindowThreadProcessId(窗口句柄, &pid);if (pid == 0){AfxMessageBox(_T("pid未找到"));return;}else{CString msg;  // 定义字符串变量msg.Format(_T("成功获取PID:%d"), pid);AfxMessageBox(msg);}HANDLE 进程句柄 = OpenProcess(PROCESS_VM_READ, FALSE, pid);if (进程句柄 == NULL){AfxMessageBox(_T("获取 进程句柄 失败"));return;}QWORD 当前气血;ReadProcessMemory(进程句柄, (LPCVOID)0x14176E868, &当前气血, sizeof(当前气血), NULL);    //目标进程的基址。ReadProcessMemory(进程句柄, (LPCVOID)(当前气血 + 0x60), &当前气血, sizeof(当前气血), NULL);//偏移ReadProcessMemory(进程句柄, (LPCVOID)(当前气血 + 0x558), &当前气血, sizeof(当前气血), NULL);//二级偏移//wchar_t juseming[30];    //读取字符串,读取角色名。//ReadProcessMemory(进程句柄, (LPCVOID)0x14135D8A8, &角色名, sizeof(角色名), NULL);//基址//ReadProcessMemory(进程句柄, (LPCVOID)(角色名 + 0x40), &角色名, sizeof(角色名), NULL);////ReadProcessMemory(进程句柄, (LPCVOID)(角色名 + 0x80), &角色名, sizeof(角色名), NULL);//将角色名+0x80指向的地址赋值给角色名//ReadProcessMemory(进程句柄, (LPCVOID)(角色名 + 0), juseming, sizeof(juseming), NULL);CString str;str.Format(L"%d", 当前气血);edit当前气血.SetWindowTextW(str);
}

生成软件
选择realse->生成解决方案,在命令输出框中找到输出路径

注意用管理员启动

MFC的DLL注入技及C语言指针读取

项目创建选择MFC动态连接库,静态链接到MFC的常规DLL。
选择资源文件->xxxx.rc双击打开资源视图。


右键图示文件,添加资源,Dialog。
右键新建的Dialog窗口,添加类,类名不要取中文。
然后切换到解决方案,源文件->MFCLibrary1.cpp,添加头文件#include "mydialog.h"

打开MFCLibrary1.cpp

myDialog* mywindow;//定义全局指针
DWORD WINAPI 显示窗口(LPARAM lpDate)
{mywindow = new myDialog;//创建对象mywindow->DoModal();delete mywindow;//释放内存FreeLibraryAndExitThread(theApp.m_hInstance,1);//释放DLLreturn TRUE;}// CMFCLibrary1App 初始化BOOL CMFCLibrary1App::InitInstance()
{CWinApp::InitInstance();::CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)显示窗口,NULL,NULL,NULL);return TRUE;
}

生成文件
记住MFCLibrary1.dll的位置,打开游戏和CE
CE选择游戏后打开查看内存->工具->注入DLL

然后成功注入并且游戏和CE也都蹦掉了。

指针读取

void myDialog::OnBnClickedButton2()
{//ReadProcessMemory(进程句柄, (LPCVOID)0x14176E868, &当前气血, sizeof(当前气血), NULL);    //目标进程的基址。//ReadProcessMemory(进程句柄, (LPCVOID)(当前气血 + 0x60), &当前气血, sizeof(当前气血), NULL);//偏移//ReadProcessMemory(进程句柄, (LPCVOID)(当前气血 + 0x558), &当前气血, sizeof(当前气血), NULL);//二级偏移/*0x14176E868+60+558*/QWORD 当前气血 = *(QWORD*)0x14176E868;    //  注意如果访问了错误的指针,指针的值不存在会导致游戏崩溃。当前气血 = *(QWORD*)(当前气血 + 0x60);当前气血 = *(QWORD*)(当前气血 + 0x558);CString str;str.Format(L"%d", 当前气血);edit当前气血.SetWindowTextW(str);}

使用后闪退不清楚原因。

DLL注入功能代码实现

创建项目->MFC应用->应用程序类型:基于对话框->使用MFC:在静态库中使用MFC

BOOL DLL注入(HANDLE 进程句柄,const char*DLL完整路径)
{LPVOID 地址 =  VirtualAllocEx(进程句柄,NULL,256,MEM_COMMIT,PAGE_READWRITE);//成功返回申请空间的地址if (地址 == NULL){AfxMessageBox(_T("地址失败"));return FALSE;}BOOL ret =WriteProcessMemory(进程句柄, 地址, DLL完整路径, strlen(DLL完整路径) + 1, NULL);if (ret = NULL) {return FALSE;}HANDLE 线程句柄 = 	CreateRemoteThread(进程句柄, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryA, 地址, NULL, NULL);//Load参数加载DLL完整路径if (线程句柄 == NULL) {VirtualFreeEx(进程句柄, 地址, 0, MEM_RELEASE);AfxMessageBox(_T("获取 线程句柄 失败"));return FALSE;}AfxMessageBox(_T("运行到这里成功"));WaitForSingleObject(线程句柄, INFINITE);CloseHandle(线程句柄);VirtualFreeEx(进程句柄, 地址, 0, MEM_RELEASE);return TRUE;
}
void CMFCApplication1Dlg::OnBnClickedButton2()
{HWND 窗口句柄 = ::FindWindow(NULL, L"诛仙");DWORD pid;GetWindowThreadProcessId(窗口句柄, &pid);if (pid == NULL){AfxMessageBox(_T("获取 pid 失败"));return;}else{CString msg;  // 定义字符串变量msg.Format(_T("成功获取PID:%d"), pid);AfxMessageBox(msg);}HANDLE 进程句柄 = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD,FALSE ,pid);//注意需要权限CString msg;  // 定义字符串变量msg.Format(_T("成功获取进程句柄:%d"), 进程句柄);AfxMessageBox(msg);DLL注入(进程句柄, "D:\\project\\vstudio\\C++\\MFCLibrary1\\x64\\Release\\MFCLibrary1.dll");CloseHandle(进程句柄);
}

参考链接

BV184AMeMELE?spm_id_from=333.788.player.switch&vd_source=d24c2772c59c9d862438971bcb05f991&p=6

http://www.sczhlp.com/news/5344/

相关文章:

  • 2025徐老师React1819课程含项目实战
  • 系统升级windows11 24H2之后蓝牙无法识别
  • 完整教程:【0基础PS】Photoshop (PS) 理论知识
  • 栈的两种存储结构(顺序存储和链式存储)
  • Gitee推出移动软件工厂解决方案 解决嵌入式与涉密场景研发困局
  • Taro on HarmonyOS 技术架构深度解析
  • 线上机器CPU占用高分析实践
  • 五百人企业-医疗医药行业Tita绩效解决方案
  • SpringBoot学习之使用idea打包jar文件
  • 2025 年五大品牌CRM精准匹配企业场景化需求
  • Linux提权之通配符提权
  • CRM 实战干货:从选型到落地
  • python例子Anaconda3、spyder
  • 反射内存基础:什么是反射内存卡
  • curl库schannel.c中TLS数据传输的整数溢出漏洞分析
  • 分布漂移下的实时异常检测技术
  • XCPC Contest Records ep.1
  • OI Contest Records ep.1
  • 3ds Max 手绘风格渲染插件 Pencil+ 4.25 使用与安装指引
  • infp.?
  • 去除打开方式/选择其他应用残留
  • 请说出Vue.cli项目中src目录每个文件夹和文件的用法?
  • GeoHash是一种将二维地理坐标(经纬度)转换为一维字符串的技术,通过递归划分地球表面区域实现高效索引。
  • docker运行java容器
  • Debian 10 执行 sudo apt update 报错的解决办法
  • 武器切换和隐藏功能
  • 英语_课本_8A_Unit04_Then and now
  • 图片时间定位修改工具:一键重塑照片时空信息的神器
  • 智能体三强争霸:Coze、Dify、FastGPT谁是企业AI化的最优解?
  • Ubuntu 22.04-字符界面下挂载u盘