如何在C语言中向其他程序的指针地址写入数据?
嘿,正在折腾Undertale无敌作弊器的朋友,这个练习对理解Windows进程内存机制太合适了!结合你提到的需求,我帮你把代码补全并梳理清楚核心要点,让你不仅能跑通程序,还能明白背后的内存操作逻辑。
完整实现代码
先给你能直接用的完整代码,记得替换成你用Cheat Engine找到的真实内存地址:
#include <stdio.h> #include <Windows.h> int main(void) { // 可调整的最大生命值,Undertale默认Frisk满生命值是20 const double MAX_HEALTH = 20.0; // 替换成你通过Cheat Engine找到的生命值内存地址 const uintptr_t HEALTH_ADDRESS = 0x00000000; // 这里改真实地址! // 第一步:找到Undertale的游戏窗口 HWND undertaleWindow = FindWindowA(NULL, "Undertale"); if (!undertaleWindow) { printf("找不到Undertale窗口!请先启动游戏~ \n"); return 1; } // 第二步:获取游戏进程ID DWORD processId; GetWindowThreadProcessId(undertaleWindow, &processId); if (processId == 0) { printf("获取进程ID失败,错误码:%d\n", GetLastError()); return 1; } // 第三步:打开游戏进程,申请内存写入权限 HANDLE processHandle = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, processId); if (!processHandle) { printf("打开进程失败,错误码:%d\n", GetLastError()); return 1; } printf("已成功连接到Undertale,开始锁定生命值为%.1f...\n按Ctrl+C即可退出程序\n", MAX_HEALTH); // 第四步:循环持续写入最大生命值,实现无敌 while (1) { BOOL writeSuccess = WriteProcessMemory( processHandle, (LPVOID)HEALTH_ADDRESS, &MAX_HEALTH, sizeof(MAX_HEALTH), NULL ); if (!writeSuccess) { printf("写入内存失败,错误码:%d\n", GetLastError()); break; } Sleep(100); // 每100毫秒写一次,避免占用过多CPU } // 收尾:关闭进程句柄 CloseHandle(processHandle); return 0; }
关键知识点解析(针对你关注的内存机制)
- 进程内存隔离:Windows下每个进程的内存是独立的,所以必须通过
OpenProcess获取目标进程的句柄,才能跨进程读写内存。 - 权限控制:
OpenProcess必须指定PROCESS_VM_WRITE(写入权限)和PROCESS_VM_OPERATION(内存操作权限),不然系统会拒绝你的写入请求。 - 动态地址处理:如果你用Cheat Engine找到的是动态地址(游戏重启后地址会变),那不能直接写死地址,得用基地址+偏移的方式:
这样每次游戏重启,// 举个例子,假设基地址来自Undertale.exe模块,偏移是0x1234 uintptr_t baseModule = (uintptr_t)GetModuleHandleA("Undertale.exe"); uintptr_t healthAddress = baseModule + 0x1234;GetModuleHandleA会自动拿到最新的模块基地址,加上固定偏移就能找到正确的生命值内存位置。 - 循环写入的必要性:游戏会在运行中随时更新生命值(比如受伤害、回血),所以必须循环覆盖这个地址的值,才能保证角色一直处于无敌状态。
注意事项
- 编译时要确保用的是和游戏同架构的编译器(比如游戏是32位,你就用32位编译器编译程序),不然内存地址会不匹配。
- 如果运行时提示权限不足,右键以管理员身份运行你的作弊程序。
内容的提问来源于stack exchange,提问作者Nim
相关产品推荐
相关产品推荐

