我的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。但是托管字符串并不包含它。
也许我可以分配足够大的缓冲区以包含终止空值,然后再次调用WriteProcessMemory
来写入null;或者我可以创建一个足够大的byte[]
来保存字符串+ null,将两者都写入数组,然后像这样传递它。
但这个问题有更优雅的解决方案吗?
答案 0 :(得分:2)
声明一个像这样的重载:
[DllImport("kernel32", SetLastError = true)]
[return : MarshalAs(UnmanagedType.Bool)]
static extern bool WriteProcessMemory(
IntPtr hProcess,
IntPtr baseAddress,
string bufferToWrite,
uint numBytesToWrite,
out uint numBytesWritten
);
这样就强制marshaller将null终止字符串。
您可以将数据作为IntPtr
传递并使用Marshal.StringToPtrAnsi
。但是你需要管理内存。
如果文本是Unicode,请使用CharSet.Unicode
选项。
答案 1 :(得分:0)
您还可以分配字符串加上空终止符。例如。如果你想写字符串
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,或者你本地需要的任何东西(例如宽字符串)。