Marshal.Copy vs ReadProcessMemory / WriteProcessMemory win32 api - in the same process

1.9k views Asked by At

I am wondering if someone can outline the main differences, pro-s and con-s of using ReadProcessMemory/WriteProcessMemory over Marshal.Copy in Windows .NET (C#/VB.net) applications to read from / write to the application's process' memory (not memory of other processes). In particular for operations involving arbitrary addresses in process' memory and dealing with memory block as byte arrays (i.e. reading/writing raw data).

Would Marshal.Copy work in all cases where ReadProcessMemory/WriteProcessMemory works, or is it more limiting?

Does Marshal.Copy's implementation use ReadProcessMemory/WriteProcessMemory APIs internally?

To clarify: I am talking about reading from / writing to the calling (owning) process's memory only, not the memory of other processes!

Thanks.

2

There are 2 answers

7
David Heffernan On BEST ANSWER

ReadProcessMemory and WriteProcessMemory are native Win32 APIs that allow you to read and write from and to the memory of a different processes. You only ever need to use those APIs when trying to read and write memory in a different process. As you may imagine, they are not often used in routine development.

Marshal.Copy is used to copy between managed and unmanaged memory, but within the same process.

Would Marshal.Copy work in all cases where ReadProcessMemory/WriteProcessMemory works, or is it more limiting?

No, Marshal.Copy it is limited to operating within a single process.

Does Marshal.Copy's implementation use ReadProcessMemory/WriteProcessMemory APIs internally?

No.

To clarify: I am talking about reading from / writing to the calling (owning) process's memory only, not the memory of other processes!

In which case, ReadProcessMemory and WriteProcessMemory are simply not pertinent to your needs.

1
Hans Passant On

Marshal.Copy() is not a substitute for Read/WriteProcessMemory(). It cannot reach into the address space of a process and access memory owned by that process. The strongest hint that this is so is that it doesn't have an overload that takes a process handle.

Keep in mind that every process in Windows has its own virtual memory address space. Pointers in one process are not usable in another. This is a big part of the process isolation that Windows provides, keeping processes from destabilizing each other. And providing security guarantees, using ReadProcessMemory() requires admin rights if the processes are not owned by the same user. The process handle must be acquired by specifying PROCESS_VM_READ/WRITE in the OpenProcess() call, a high privilege.

This is not an issue if you are accessing a pointer in your own process. In that case, you are simply relying on the Marshal.Copy() built into the pinvoke marshaller. Nicely hidden from view but certainly not faster than Copy() since you are adding the overhead of making the pinvoke call and Windows executing the function. Marshal.Copy() is simple and fast, just the equivalent of memcpy().