如何修复Rust调用NtAllocateVirtualMemory时的0xc0000005 STATUS_ACCESS_VIOLATION错误
问题根因分析
1. 参数传递存在两处致命错误
你触发访问违规的核心原因是完全不符合NtAllocateVirtualMemory的参数传递约定,先看该函数的标准原型:
NTSYSAPI NTSTATUS NtAllocateVirtualMemory( [in] HANDLE ProcessHandle, [in, out] PVOID *BaseAddress, [in] ULONG_PTR ZeroBits, [in, out] PSIZE_T RegionSize, [in] ULONG AllocationType, [in] ULONG Protect );
你代码里的错误点:
- 第二个参数要求传入存储基地址的变量的二级指针,你写的
*buffer是对空指针直接解引用,内核尝试写入空地址直接触发0xc0000005错误 - 第四个参数要求传入存储分配大小的变量的二级指针,你直接把0x1000强转为指针传入,内核会尝试往0x1000这个非法用户地址写入实际分配大小,也是访问违规的诱因
- 还存在语法错误:
0x1000 as *mut _后漏写逗号,编译阶段就会触发语法告警
2. 为什么VirtualAllocEx可以正常工作
VirtualAllocEx是kernel32.dll封装的上层接口,内部已经帮你完成了Nt系列接口的参数适配:你传入给VirtualAllocEx的是直接的地址和大小数值,它内部会自动在栈上申请临时变量存储这两个值,再把变量的二级指针传给底层的NtAllocateVirtualMemory,调用完成后再把分配结果返回给上层,你不需要自行处理二级指针的传递逻辑,自然不会踩到参数传递的坑。
修复后的可运行代码
Cargo.toml不需要修改,直接替换main.rs内容即可:
use ntapi::ntmmapi::NtAllocateVirtualMemory; use ntapi::ntpsapi::NtCurrentProcess; use winapi::um::winnt::{MEM_COMMIT, MEM_RESERVE, PAGE_READWRITE}; use winapi::shared::ntdef::NT_SUCCESS; use std::ptr::null_mut; fn main() { unsafe { let mut buffer = null_mut(); let mut region_size = 0x1000; let status = NtAllocateVirtualMemory( NtCurrentProcess, &mut buffer, 0, &mut region_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE, ); if !NT_SUCCESS(status) { println!("Allocation Fails, status: {:#x}", status); } else { println!("Allocation Success, base address: {:p}, size: {:#x}", buffer, region_size); } } }
内容的提问来源于stack exchange,提问作者her0mx
相关产品推荐
相关产品推荐

