Handmade Hero»Forums»Code
117 posts
Code hacker/developer
Win32 Memory Space of Foreign Process
I'm trying to make a program which writes and reads to the notepad memory directly. Unfortunately, I am a total newbie to the WIN32 API and frankly I don't know how to use VirtualProcessEx but I gave it my best guess. You can see what I'm trying to do, but just to summarize: 1. Get the notepad process handle 2. Read the text from the provided memory address which is in the notepad process. 3. Write some new text in there.

Without VirtualProcessEx I was getting an access denied code 998 error, but I read somewhere that I can give READWRITE access to the page which should solve this. I'm sort of on pins and needles here as there really isn't much about this online. I also own Programming Windows Fifth Edition by Charles Petzold and WriteProcessMemory is no where to be found in there either. One of the toughest parts for me is converting the code to support 64 bit. I have no idea if the PINT64 is how to do that, but the original instructions for this said to use a PBYTE but that can't be right. The machine is 64 bit as well as the notepad program. Please see code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <stdio.h>
#include <Windows.h>


int main()
{
  BOOL retVal;
  char* newValue = "Macho Man Randy Savage";
  HWND hwnd = FindWindowA(NULL, "Untitled - Notepad");
  if(hwnd == NULL)
    {
      printf("Cannot find window.\n");
      Sleep(3000);
      exit(-1);
    }
  else
    {
      DWORD procID;
      GetWindowThreadProcessId(hwnd, &procID);
      HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID);

      if(!procID)
	{
	  printf("Cannot obtain process.\n");
	  Sleep(3000);
	  exit(-1); 
	}
      else
	{
	  int old = 0;
	  INT64 mem = 0x1DB17214AA0;
	  char container[50];
	  ReadProcessMemory(handle,(PINT64*)0x1DB1725D600,&container[0],sizeof(container),0);
	  container[50] = '\0';
	  printf("Message: %s\n", container);
	  VirtualProcessEx(handle,(PINT64*)mem,sizeof(mem),PAGE_EXECUTE_READWRITE, &old);
	 retVal =  WriteProcessMemory(handle, (LPVOID)0x1DB17214AA0,&newValue,sizeof(newValue),0);
	 if(retVal == 0)
	   {
	     printf("Write failed. Error Code: \t %d",GetLastError());
	   }
	}
    }
  return (EXIT_SUCCESS);
}
Mārtiņš Možeiko
2562 posts / 2 projects
Win32 Memory Space of Foreign Process
Edited by Mārtiņš Možeiko on
Your code assumes notepad memory will be always located in address 0x1DB1725D600 and 0x1DB17214AA0. Are you sure this is right assumption? Usually applications randomize address they are loaded (or the memory they allocate).

PINT64 is just a typedef for int64_t*. It doesn't matter to what type you cast address value for ReadProcessMemory or v functions. They accept void* anyway (see the docs on MSDN), so just cast to void* and ddn't worry about types there.

VirtualProcess calls are needed to change memory protection flags. Each memory page on x86 can have combination of these three flags - READ, WRITE and EXECUTE. OS uses that for safety reasons. For example, memory that contains code should have only READ and EXECUTE flags. No need to WRITE to code memory. Memory that belongs to heap should have only READ and WRITE flags, no need to execute it, right? In some special situation, for example. when you are writing runtime compiler (JIT) you might want to change heap flags from RW to RX, because first you need to generate code, and later execute it.

Anyway VirtualProtect is not relevant to you if you want to change data that notepad changes itself. Because if notepad can change data that means memory has READ and WRITE flags set. So you should also be able to READ and WRITE it. No need to use VirtualProtect. If code crashes on Read/WriteProcessMemory that means you have wrong address. How did you get virtual address you are using? Verify your assumptions and find the mistake there.
117 posts
Code hacker/developer
Win32 Memory Space of Foreign Process
Edited by Todd on
mmozeiko,

Thank you for that info. I put that memory address in there just as an example, I am aware that it does change and I used a memory scanner to find the specific address on a case-by-case basis for now... And because frankly I have no idea how to make a program that dynamically finds the address of given text every time but I suspect I could do so by writing a memory scanner and combining it with the program that also writes to memory.

The thing is, I've seen very spotty reliability with this stuff. For example, sometimes the code works and I can change or read a value and other times it doesn't, despite me updating the value to what the memory scanner tells me is the correct address. I even followed a tutorial video series to make a memory scanner and I wrote the code word-for-word that the instructor had said and it only worked n percent of the time, other times it would completely fail. I was wondering if there were some other permission-related variables at play here and also whether programs or the OS can actually lock me out from editing memory or if it can always be overcome with a C program. The reason I ask this is because sometimes I get access denied errors, even if I use, for example Cheat Engine to try and edit the notepad text. The only other thing I could guess is that the memory locations are changing all the time and somehow I am not editing fast enough before it changes again. Another thing I've heard about is something called "Debug Mode" which apparently debuggers and Cheat Engine use to be able to do the things they do, but that's also a mystery to me at this point. There are also some folks out there that say "The OS won't allow one program to write to another's address space." Is this really true or is this bogus?

EDIT: I'm able to get ReadProcessMemory to work and read it successfully, but unable to write to the same memory address due to error code 998 access denied.
Mārtiņš Možeiko
2562 posts / 2 projects
Win32 Memory Space of Foreign Process
As long a you are same user as process (or with higher privileges) you can read memory of other processes.
You could try this code to get debug privileges for your process (which theoretically should allow you to do anything that debugger can): https://msdn.microsoft.com/en-us/...ry/windows/hardware/ff541528.aspx

But I never needed to do that to read or write to other process memory.