通过 P/Invoke 将空终止字符串作为字节数组发送到 WriteProcessMemory()
Send null terminated string as byte array to WriteProcessMemory() via P/Invoke
我的 P/Invoke WriteProcessMemory
方法目前看起来像这样:
[DllImport("kernel32", SetLastError = true)]
[return : MarshalAs(UnmanagedType.Bool)]
static extern bool WriteProcessMemory(
IntPtr hProcess,
IntPtr baseAddress,
byte[] bufferToWrite,
uint numBytesToWrite,
out IntPtr numBytesWritten
);
我需要将一个字符串发送到 bufferToWrite
参数,但它需要一个 byte[]
,所以我在传递它之前将其转换为 byte[]
。
我的问题是,由于 .NET 字符串不是以 null 结尾的,因此它不会将终止 null 写入远程内存。如果我在非托管代码中执行此操作,我将分配字符串的长度 + 终止空值,并将所有内容放入分配的内存中,因为我正在读取的 "string" 包含空值。但是托管字符串不包含它。
也许我可以分配一个足够大的缓冲区来包含终止空值,然后再次调用 WriteProcessMemory
来写入空值;或者我可以创建一个足够大的 byte[]
来容纳字符串 + null,将两者都写入数组,然后像那样传递它。
但是这个问题有更优雅的解决方案吗?
您还可以分配字符串加上空终止符。例如。如果你想写字符串
string szToWrite = "This is what I want to write";
我会将其转换为 byte[]
,例如使用 ASCII 转换
byte[] aBytes = Encoding.ASCII.GetBytes(szToWrite);
然后将它与一个额外的空字节连接起来。
aBytes = aBytes.Concat(new byte[] { 0x00 }).ToArray();
如果需要,创建您自己的函数 WriteProcessMemoryString
,让它接受 string
而不是 byte[]
并使用与上述相同的概念。另请注意,您可能希望使用与 ASCII 不同的编码,例如UTF7/UTF8,或任何您本机需要的东西(例如宽字符字符串)。
像这样声明重载:
[DllImport("kernel32", SetLastError = true)]
[return : MarshalAs(UnmanagedType.Bool)]
static extern bool WriteProcessMemory(
IntPtr hProcess,
IntPtr baseAddress,
string bufferToWrite,
uint numBytesToWrite,
out uint numBytesWritten
);
这样你就可以强制编组器以 null 终止字符串。
您可以将数据作为 IntPtr
传递并使用 Marshal.StringToPtrAnsi
。但是你需要管理内存。
如果文本是 Unicode,请使用 CharSet.Unicode
选项。
我的 P/Invoke WriteProcessMemory
方法目前看起来像这样:
[DllImport("kernel32", SetLastError = true)]
[return : MarshalAs(UnmanagedType.Bool)]
static extern bool WriteProcessMemory(
IntPtr hProcess,
IntPtr baseAddress,
byte[] bufferToWrite,
uint numBytesToWrite,
out IntPtr numBytesWritten
);
我需要将一个字符串发送到 bufferToWrite
参数,但它需要一个 byte[]
,所以我在传递它之前将其转换为 byte[]
。
我的问题是,由于 .NET 字符串不是以 null 结尾的,因此它不会将终止 null 写入远程内存。如果我在非托管代码中执行此操作,我将分配字符串的长度 + 终止空值,并将所有内容放入分配的内存中,因为我正在读取的 "string" 包含空值。但是托管字符串不包含它。
也许我可以分配一个足够大的缓冲区来包含终止空值,然后再次调用 WriteProcessMemory
来写入空值;或者我可以创建一个足够大的 byte[]
来容纳字符串 + null,将两者都写入数组,然后像那样传递它。
但是这个问题有更优雅的解决方案吗?
您还可以分配字符串加上空终止符。例如。如果你想写字符串
string szToWrite = "This is what I want to write";
我会将其转换为 byte[]
,例如使用 ASCII 转换
byte[] aBytes = Encoding.ASCII.GetBytes(szToWrite);
然后将它与一个额外的空字节连接起来。
aBytes = aBytes.Concat(new byte[] { 0x00 }).ToArray();
如果需要,创建您自己的函数 WriteProcessMemoryString
,让它接受 string
而不是 byte[]
并使用与上述相同的概念。另请注意,您可能希望使用与 ASCII 不同的编码,例如UTF7/UTF8,或任何您本机需要的东西(例如宽字符字符串)。
像这样声明重载:
[DllImport("kernel32", SetLastError = true)]
[return : MarshalAs(UnmanagedType.Bool)]
static extern bool WriteProcessMemory(
IntPtr hProcess,
IntPtr baseAddress,
string bufferToWrite,
uint numBytesToWrite,
out uint numBytesWritten
);
这样你就可以强制编组器以 null 终止字符串。
您可以将数据作为 IntPtr
传递并使用 Marshal.StringToPtrAnsi
。但是你需要管理内存。
如果文本是 Unicode,请使用 CharSet.Unicode
选项。