如何通过DllImport正确调用未公开函数ZwAllocateVirtualMemoryEx?
修复ZwAllocateVirtualMemoryEx的DllImport配置问题
你的代码无法运行的核心原因是参数类型、传递方式和调用约定不匹配,以下是修正后的定义及关键说明:
正确的DllImport定义
using System.Runtime.InteropServices; private const string NTDLL = "ntdll.dll"; [DllImport(NTDLL, CallingConvention = CallingConvention.Winapi, SetLastError = true)] public static extern uint ZwAllocateVirtualMemoryEx( IntPtr hProcess, ref IntPtr lpAddress, UIntPtr zeroBits, ref UIntPtr dwSize, uint flAllocationType, uint flProtect, IntPtr extendedParameters, uint extendedParameterCount );
关键修正点
- lpAddress:原代码用
IntPtr,但该参数是输入输出(函数会返回实际分配的内存地址),必须改为ref IntPtr - ZeroBits参数:原代码遗漏了这个必填参数,对应原生函数中的
ULONG_PTR ZeroBits,用UIntPtr适配32/64位系统 - dwSize:原代码用
uint,但该参数是输入输出(函数会返回实际分配的内存大小),需改为ref UIntPtr以兼容32/64位的SIZE_T类型 - ExtendedParameters:原代码用
int,实际该参数是指向MEM_EXTENDED_PARAMETER结构体数组的指针,需用IntPtr - ExtendedParameterCount:原代码用
ulong,原生函数中是ULONG类型,对应C#的uint - 调用约定:显式指定
CallingConvention.Winapi(Windows下等价于StdCall),匹配ntdll的函数调用规范 - SetLastError:启用后可通过
Marshal.GetLastWin32Error()获取错误码,方便调试
MEM_EXTENDED_PARAMETER结构体参考(可选)
如果需要使用扩展参数,需定义对应的结构体:
[StructLayout(LayoutKind.Sequential)] public struct MEM_EXTENDED_PARAMETER { public UIntPtr Type; public UIntPtr Reserved; public UIntPtr Value; }
使用时需分配结构体数组,转换为IntPtr传入:
// 示例:创建一个扩展参数 var param = new MEM_EXTENDED_PARAMETER(); param.Type = (UIntPtr)0; // 根据需求设置参数类型 param.Value = (UIntPtr)0; // 设置参数值 // 分配非托管内存存放参数 IntPtr paramPtr = Marshal.AllocHGlobal(Marshal.SizeOf(param)); Marshal.StructureToPtr(param, paramPtr, false); // 调用函数 UIntPtr size = (UIntPtr)0x1000; IntPtr addr = IntPtr.Zero; uint status = ZwAllocateVirtualMemoryEx( processHandle, ref addr, UIntPtr.Zero, ref size, 0x1000 | 0x2000, // MEM_COMMIT | MEM_RESERVE 0x40, // PAGE_EXECUTE_READWRITE paramPtr, 1 ); // 释放非托管内存 Marshal.FreeHGlobal(paramPtr);
内容的提问来源于stack exchange,提问作者John Black
相关产品推荐
相关产品推荐

