关于NtWow64AllocateVirtualMemory64无效句柄问题的技术咨询及测试代码
排查NtWow64AllocateVirtualMemory64无效句柄问题
从你的代码和问题描述来看,出现无效句柄错误的核心原因是进程句柄的使用不符合Wow64环境下的函数要求,另外还有参数类型不匹配的问题,下面详细拆解并给出解决方案:
问题原因分析
- 错误的进程句柄传递:你在代码里定义了
NtCurrentProcess()但实际调用时用了GetCurrentProcess()。在32位Wow64进程中,NtWow64AllocateVirtualMemory64这类跨位函数要求使用内核认可的特殊伪句柄(HANDLE)-1(也就是NtCurrentProcess()的定义),而GetCurrentProcess()返回的是32位进程的伪句柄,在64位内核调用上下文里会被解析成无效句柄。 - 参数类型不匹配:你用
PVOID pvBaseAddress来存储64位基地址,但32位进程的PVOID是32位指针,无法完整容纳64位地址值。函数的第二个参数PULONG64要求传入指向64位整数的指针,用来接收分配的64位基地址,用32位指针类型强制转换会导致地址截断或参数解析错误。
解决方法
- 替换进程句柄为NtCurrentProcess():直接使用你已经定义的
NtCurrentProcess()作为第一个参数,不要用GetCurrentProcess()。 - 修正基地址的参数类型:用
ULONG64类型变量来存储64位基地址,而不是PVOID,确保能完整接收64位地址值。 - 补全函数参数:确保
MEM_COMMIT搭配正确的内存分配类型(比如MEM_RESERVE),以及合理的内存保护属性(比如PAGE_READWRITE)。
修正后的测试代码示例
typedef NTSTATUS(NTAPI *ntalloc64t)( HANDLE ProcessHandle, PULONG64 BaseAddress, ULONG64 ZeroBits, PULONG64 RegionSize, ULONG AllocationType, ULONG Protect ); #define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1) int _tmain(int argc, _TCHAR* argv[]) { ULONG64 dwSize = 0x1000; ULONG64 baseAddr = 0; // 用64位变量存储基地址 ntalloc64t ntalloc64f = (ntalloc64t)GetProcAddress( GetModuleHandleA("ntdll"), "NtWow64AllocateVirtualMemory64" ); if (!ntalloc64f) { // 处理函数获取失败的情况 return 1; } NTSTATUS status = ntalloc64f( NtCurrentProcess(), // 使用正确的伪句柄 &baseAddr, // 传入64位地址的指针 0, &dwSize, MEM_COMMIT | MEM_RESERVE, // 补全分配类型 PAGE_READWRITE // 指定内存保护属性 ); if (NT_SUCCESS(status)) { // 分配成功,baseAddr就是64位的内存基地址 // 注意:32位进程无法直接访问这个64位地址,通常用于后续的Wow64内存操作 } else { // 处理错误,比如打印status值 } return 0; }
额外注意事项
- 32位进程无法直接访问
NtWow64AllocateVirtualMemory64分配的64位地址空间,这个函数通常是配合其他Wow64系列函数(比如NtWow64WriteVirtualMemory64)来操作64位进程的内存,或者用于特殊的内存场景。 - 确保你的程序是以32位编译的,因为这个函数只存在于32位的ntdll.dll中,64位进程不需要调用它。
内容的提问来源于stack exchange,提问作者sdevae




