使用Rust的windows_sys读取Assault Cube生命值内存始终为0求助
问题分析与修复方案
你的代码存在几个关键问题,导致无法正确读取Assault Cube的生命值:
1. 错误将PID直接作为进程句柄使用
process_id变量存储的是进程ID(13488),但你直接将它当作HANDLE传入ReadProcessMemory。实际上,进程ID和进程句柄是完全不同的概念——你需要通过OpenProcess函数获取具有读取权限的进程句柄,而非直接使用PID。
2. 使用空指针作为缓冲区
你将buffer设为null_mut(),这意味着没有分配任何内存来存储读取到的数据。即使ReadProcessMemory调用成功,也会因写入空指针导致未定义行为,最终得到0值。
3. 未检查函数调用返回值
你没有验证ReadProcessMemory是否执行成功。如果调用失败(比如权限不足、地址无效),无法及时发现问题根源。
4. 可能存在架构不匹配
Assault Cube是32位游戏,你的Rust程序需要编译为32位版本(否则64位程序的指针大小与32位游戏的地址不兼容,会导致读取错误)。
修复后的代码
use std::ffi::c_void; use windows_sys::Win32::{ Foundation::{BOOL, HANDLE, INVALID_HANDLE_VALUE}, System::Diagnostics::Debug::ReadProcessMemory, System::Threading::{OpenProcess, PROCESS_VM_READ}, }; fn main() { unsafe { let pid = 13488; // 替换为实际的Assault Cube进程ID let health_address = 0x005954FC as *const c_void; // 打开进程,获取具有读取权限的句柄 let process_handle = OpenProcess(PROCESS_VM_READ, 0, pid); if process_handle == INVALID_HANDLE_VALUE { println!("无法打开进程,可能权限不足"); return; } // 分配缓冲区存储生命值(i32类型,占4字节) let mut health: i32 = 0; let buffer = &mut health as *mut i32 as *mut c_void; let mut bytes_read: usize = 0; // 读取进程内存 let success: BOOL = ReadProcessMemory( process_handle, health_address, buffer, std::mem::size_of::<i32>(), &mut bytes_read, ); if success == 0 { println!("读取内存失败,错误码: {}", windows_sys::Win32::Foundation::GetLastError()); } else if bytes_read != std::mem::size_of::<i32>() { println!("未读取到完整数据,仅读取了{}字节", bytes_read); } else { println!("当前生命值: {}", health); } // 关闭进程句柄(良好实践) windows_sys::Win32::Foundation::CloseHandle(process_handle); } }
额外注意事项
- 确保以管理员权限运行你的Rust程序,否则可能无法获取进程读取权限。
- 编译时需指定32位目标:使用命令
cargo build --target i686-pc-windows-msvc(需提前安装32位编译工具链)。 - 确认
0x005954FC确实是Assault Cube当前版本的生命值静态地址(不同版本可能会变化)。
内容的提问来源于stack exchange,提问作者johnsc
相关产品推荐
相关产品推荐

