如何从运行中的程序读取并修改变量?C语言跨程序操作问询
如何读取/修改运行中程序的内部变量
核心结论
完全可以实现读取和修改操作,这两类能力都由操作系统提供的进程内存访问接口支持,只要你拥有目标进程的对应操作权限即可完成需求。
操作前提
- 先获取目标程序的进程ID(PID),Linux下可通过
ps命令获取,Windows下可通过任务管理器获取 - 提前定位到目标变量
a在目标进程虚拟地址空间中的准确地址,可通过gdb、x64dbg等调试工具预先获取
各平台实现方案
Linux平台
Linux下可通过ptrace系统调用完成进程附加、内存读写操作,示例代码如下:
#include <sys/ptrace.h> #include <sys/wait.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> int main(int argc, char* argv[]) { if (argc != 3) { printf("用法: %s <目标PID> <变量a的16进制地址>\n", argv[0]); return 1; } pid_t pid = atoi(argv[1]); uint64_t addr = strtoul(argv[2], NULL, 16); // 附加到目标进程,附加后目标进程会暂停运行 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1) { perror("attach失败"); return 1; } waitpid(pid, NULL, 0); // 读取变量a的值 long a_val = ptrace(PTRACE_PEEKDATA, pid, addr, NULL); printf("读取到的a当前值: %ld\n", a_val); // 修改a的值为100 if (ptrace(PTRACE_POKEDATA, pid, addr, 100) == -1) { perror("修改失败"); ptrace(PTRACE_DETACH, pid, NULL, NULL); return 1; } printf("已将a的值修改为100\n"); // 分离进程,恢复目标程序运行 ptrace(PTRACE_DETACH, pid, NULL, NULL); return 0; }
使用方式:用gcc编译后,以root权限运行,传入目标PID和变量地址即可完成操作。
Windows平台
Windows下可通过系统API OpenProcess、ReadProcessMemory、WriteProcessMemory完成操作,示例代码如下:
#include <windows.h> #include <stdio.h> int main() { DWORD pid = 1234; // 替换为目标程序的实际PID LPVOID addr = (LPVOID)0x12345678; // 替换为变量a的实际地址 int a_val; SIZE_T read_bytes, write_bytes; // 打开目标进程,获取读写权限 HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, pid); if (hProcess == NULL) { printf("打开进程失败,错误码: %d\n", GetLastError()); return 1; } // 读取变量a的值 if (ReadProcessMemory(hProcess, addr, &a_val, sizeof(a_val), &read_bytes) && read_bytes == sizeof(a_val)) { printf("读取到的a当前值: %d\n", a_val); } else { printf("读取内存失败\n"); CloseHandle(hProcess); return 1; } // 修改a的值为100 int new_val = 100; if (WriteProcessMemory(hProcess, addr, &new_val, sizeof(new_val), &write_bytes) && write_bytes == sizeof(new_val)) { printf("已将a的值修改为100\n"); } else { printf("写入内存失败\n"); CloseHandle(hProcess); return 1; } CloseHandle(hProcess); return 0; }
使用方式:编译后以管理员权限运行即可。
注意事项
- 如果目标程序开启了地址空间布局随机化(ASLR),每次运行时变量的虚拟地址都会变化,不可硬编码地址,需要动态定位变量地址
- 跨用户操作进程需要更高的系统权限,普通权限默认只能操作同用户启动的进程
- 栈变量的地址只有在对应栈帧未销毁时有效,本示例中
a是main函数内的栈变量,程序运行全程栈帧不会销毁,地址固定可安全操作 - 这类内存修改操作目标程序本身无感知,除非程序本身做了内存完整性校验
内容的提问来源于stack exchange,提问作者yulaf lif
相关产品推荐
相关产品推荐

