MmCopyVirtualMemory vs KeReadProcessMemory vs ZwReadVirtualMemory

There seems to be multiple ways to read a process’s memory: MmCopyVirtualMemory vs KeReadProcessMemory vs ZwReadVirtualMemory. Which one is suitable when, and why?

Aren’t these all undocumented? Assuming so, the answer is simple: None of them are suitable for use at any time.

What are you trying to accomplish? Or is you asking just because you’re curious?

Peter

KeReadProcessMemory is not an function? or i do not just see it in the exports. Do you mean KeStackAttachProcess()? I would go with MmCopyVirtualmemory :slight_smile:

@“Peter_Viscarola_(OSR)” said:
Aren’t these all undocumented? Assuming so, the answer is simple: None of them are suitable for use at any time.

What are you trying to accomplish? Or is you asking just because you’re curious?

Peter

I am not trying to accomplish anything in particular. I am only curious. I don’t understand why none of them are suitable for use at any time. There are kernel mode drivers which use them.

They are not suitable for use by drivers because they are not documented, and there is nothing, absolutely nothing, that these functions do that you cannot do using documented functions.

Hence, “not suitable for use for anything at any time.”

Peter

@“Peter_Viscarola_(OSR)” said:
They are not suitable for use by drivers because they are not documented, and there is nothing, absolutely nothing, that these functions do that you cannot do using documented functions.

Hence, “not suitable for use for anything at any time.”

Peter

Then which function should I use to write to or read a process’s memory from other than MmCopyVirtualMemory?

Then which function should I use to write to or read a process’s memory from other than MmCopyVirtualMemory?

Before we proceed any further,consider what happens if

  1. The target address becomes invalid because the target process has already freed the range that you are trying to access, and it has happened transparently to your code
  2. The target address in itself is valid, but the page is not currently loaded in RAM

Therefore, your only reasonable option seems to be calling KeStackAttachProcess(), and then allocating → probing-and-locking → mapping an MDL in context of your target process

Anton Bassov

Then which function should I use to write to or read a process’s memory

It depends on what you want to do and the context in which your executing.

Look: No offense, but I have a policy of not answering purely hypothetical questions asked for the sake of somebody’s amusement. If you’re a driver dev and you’ve got a real problem that you need help with, I will try to help you without limit and to the best of my ability. But my experience with answering questions people ask “just because they’re curious” hasn’t been good. Ever. So, I don’t do it.

Having said that, what Anton said is reasonable. And if you take the time to walk into or disassemble some of the functions you’re asking about (which should be prerequisite for asking any questions of mere curiosity here) you’ll see that they are indeed wrapper around pretty much what Anton described.

Best of luck learning what you seek to know.

Peter

@anton_bassov said:

Then which function should I use to write to or read a process’s memory from other than MmCopyVirtualMemory?

Before we proceed any further,consider what happens if

  1. The target address becomes invalid because the target process has already freed the range that you are trying to access, and it has happened transparently to your code
  2. The target address in itself is valid, but the page is not currently loaded in RAM

Therefore, your only reasonable option seems to be calling KeStackAttachProcess(), and then allocating → probing-and-locking → mapping an MDL in context of your target process

Anton Bassov

@“Peter_Viscarola_(OSR)” said:

Then which function should I use to write to or read a process’s memory

It depends on what you want to do and the context in which your executing.

Look: No offense, but I have a policy of not answering purely hypothetical questions asked for the sake of somebody’s amusement. If you’re a driver dev and you’ve got a real problem that you need help with, I will try to help you without limit and to the best of my ability. But my experience with answering questions people ask “just because they’re curious” hasn’t been good. Ever. So, I don’t do it.

Having said that, what Anton said is reasonable. And if you take the time to walk into or disassemble some of the functions you’re asking about (which should be prerequisite for asking any questions of mere curiosity here) you’ll see that they are indeed wrapper around pretty much what Anton described.

Best of luck learning what you seek to know.

Peter

Dear Peter,
Dear Anton,
Thank you very much for all the effort you put into this forum. It is truly an amazing platform to learn.
I am sorry, I did not know that you didn’t like answering hypothetical questions. The reason that I was asking the question was that I was genuinely interested in the answer. Amusement? Very unlikely. I am a driver developer but am still inexperienced.

My aim was to create a driver which communicates with a user-mode program to read or write to a video game’s memory. My driver uses only MmCopyVirtualMemory for memory management. The reason that I develop a kernel mode driver is to bypass the anti-cheat software because anti-cheat software protect game processes by setting call-backs in the kernel that fire on things like process or thread handles being created or duplicated using ObRegisterCallbacks.

It does not matter if the target address becomes invalid because the user-mode program does all the required checks, such as comparing the values read from the process’s memory and not continuing execution if the result of the comparison is invalid. The user-mode program communicates with the driver to read/follow a pointer chain (or should I call it a linked list?) and write a certain value to a variable at the end of the pointer chain. In the worst case, the game will crash but it is not important to me.

For reading usermode memory, I would go with ZwReadVirtualMemory since it is de facto a system call implementation (and hence may be called from usermode code). Of course, you must be on guard since system services (system call implementations) behave a little bit differently when called from kernel mode.

But as others said, calling undocumented functions may be dangerous. Also, I am not sure whether this one is actually exported by all kernel versions, so you may need to find it first.

I would go with ZwReadVirtualMemory since it is de facto a system call implementation (and hence may be called from usermode code).

Is it even exported by ntoskrnl.exe via IAT? Please note that there are quite a few system calls that are not supposed to be
made by the KM code, so that ntoskrnl.exe does not export them. Certainly, you can try calling it anyway either by the address that is available from SSDT (effectively making a call in Nt… form) or via INT 0x2e (effectively making the same call in Zw… form) , but this is just a fool’s errand - there is a good chance that the “result” that you actually get this way is very different from the one you are expecting…

Anton Bassov

@anton_bassov said:

Then which function should I use to write to or read a process’s memory from other than MmCopyVirtualMemory?

Before we proceed any further,consider what happens if

  1. The target address becomes invalid because the target process has already freed the range that you are trying to access, and it has happened transparently to your code
  2. The target address in itself is valid, but the page is not currently loaded in RAM

Therefore, your only reasonable option seems to be calling KeStackAttachProcess(), and then allocating → probing-and-locking → mapping an MDL in context of your target process

Anton Bassov

@“Peter_Viscarola_(OSR)” said:

Then which function should I use to write to or read a process’s memory

It depends on what you want to do and the context in which your executing.

Look: No offense, but I have a policy of not answering purely hypothetical questions asked for the sake of somebody’s amusement. If you’re a driver dev and you’ve got a real problem that you need help with, I will try to help you without limit and to the best of my ability. But my experience with answering questions people ask “just because they’re curious” hasn’t been good. Ever. So, I don’t do it.

Having said that, what Anton said is reasonable. And if you take the time to walk into or disassemble some of the functions you’re asking about (which should be prerequisite for asking any questions of mere curiosity here) you’ll see that they are indeed wrapper around pretty much what Anton described.

Best of luck learning what you seek to know.

Peter

Dear Peter,
Dear Anton, thank you very much for all the effort you put into this forum. It is truly an amazing platform to learn.
I am sorry, I did not know that you didn’t like answering hypothetical questions. The reason that I was asking the question was that I was genuinely interested in the answer. Amusement? Very unlikely. I am a driver developer but am still inexperienced.

My aim was to create a driver which communicates with a user-mode program to read or write to a video game’s memory. My driver uses only MmCopyVirtualMemory for memory management. The reason that I develop a kernel mode driver is to bypass the anti-cheat software because anti-cheat software protect game processes by setting call-backs in the kernel that fire on things like process or thread handles being created or duplicated using ObRegisterCallbacks.

It does not matter if the target address becomes invalid because the user-mode program does all the required checks, such as comparing the values read from the process’s memory and not continuing execution if the result of the comparison is invalid. The user-mode program communicates with the driver to read/follow a pointer chain (or should I call it a linked list?) and write a certain value to a variable at the end of the pointer chain. In the worst case, the game will crash but it is not important to me.

I develop a kernel mode driver is to bypass the anti-cheat software

Sooooo… you’re asking us to help you cheat at games? Ah, well… who wouldn’t want to help you do that… :o

My driver uses only MmCopyVirtualMemory for memory management.

I’m going to repeat this one more time, then I promise to be out of this thread: This function is undocumented. There is absolutely no reason – aside from laziness or bad engineering judgment – to use this function. Walk into the code. You will see that this function is just a wrapper that calls several documented functions. That means that YOU could call these same functions from your driver, and thus achieve your goals in a supported, documented, way.

Using undocumented functions is sometimes necessary. This is not one of those situations.

I have now finished pontificating on this topic.

Peter

Sooooo… you’re asking us to help you cheat at games?

PUBLISH YOUR AVATAR NAME (etc)…

Anton Bassov

@“Peter_Viscarola_(OSR)” said:

I develop a kernel mode driver is to bypass the anti-cheat software

Sooooo… you’re asking us to help you cheat at games? Ah, well… who wouldn’t want to help you do that… :o

No. I am not a cheater. I am just curious if anti-cheat will detect that my driver is being used for cheating.