通过P/Invoke将以null结尾的字符串作为字节数组发送给WriteProcessMemory()
本文关键字:数组 字节数 字节 WriteProcessMemory Invoke 将以 null 字符串 结尾 通过 | 更新日期: 2023-09-27 18:11:27
我的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,并将所有这些放在分配的内存中,因为我正在读取的"字符串"包括null。但是托管字符串不包含它。
也许我可以分配一个足够大的缓冲区来包含一个终止null,然后再调用WriteProcessMemory
来写null;或者我可以创建一个足够大的byte[]
来容纳字符串+ null,把它们都写入数组,然后像这样传递给它。
但是对于这个问题是否有更优雅的解决方案呢?
像这样声明一个重载:
[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
选项。
您还可以分配字符串加上空终止符。例如,如果你想写字符串
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,或任何你需要的东西(例如宽字符字符串)。