Tutorial ReadProcessMemory and WriteProcessMemory

  • Thread starter wtlyons
  • Start date
  • Replies 9
  • Views 12K
Hexui Undetected CSGO Cheats Sinkicheat PUBG Cheat
W

wtlyons

Hello Guided Hacking. I have decided to make this tutorial for the noobs who are just getting started. A big part of hacking is reading and writing to memory. This tutorial will cover the basics of how ReadProcessMemory and WriteProcessMemory work and hopefully clear up questions that beginner hackers have on it. I would first like to say this is going to be extreme over kill. I recommend before reading this you look at the MSDN page on RPM(ReadProcessMemory) and WPM(WriteProcessMemory) and if you understand that don't bother reading this tutorial. Links -
https://msdn.microsoft.com/en-us/library/windows/desktop/ms680553(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674(v=vs.85).aspx

So lets begin.

ReadProcessMemory and WriteProcessMemory are functions that are commonly used in making external hacks. Just about every external hack has Read or Write Process Memory in it so it is very important to learn! Lets look at a little code

C++:
 DWORD pLocalPlayer = { 0x509B74 };
DWORD playerObjectAddress = 0;
ReadProcessMemory(hProcHandle, (LPCVOID)pLocalPlayer, &playerObjectAddress, sizeof(playerObjectAddress), NULL);
Lets go over a few things first. This code will not do anything because there is no handle to the game we are potentially trying to hack so hProcHandle is undefined. Another thing to note is that when ever you use ReadProcessMemory and WriteProcessMemory you are going to want to include kernel32 library because WriteProcessMemory, ReadProcessMemory are all part of it. Not including it will cause WriteProcessMemory to show up as an error. I usually include windows.h instead of kernel32 because windows.h includes kernel32 and other libraries such as memoryapi.h and WinBase.h and these libraries have other useful features in them.

So the code seen above is finding the playerObjectAddress. If you are reading this you probably understand that there is a static pointer that always points to the player object address in a game. Since the player object address is dynamic every time the game closes and is opened the player object address changes so we have to read what pLocalPlayer (our static pointer that always points to the player address) points to every time the game is reopened. This is a perfect example of using RPM.

so lets break down RPM:
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
C++:
 ReadProcessMemory(hProcHandle, (LPCVOID)pLocalPlayer, &playerObjectAddress, sizeof(playerObjectAddress), NULL);
hProcHandle our first argument in the function is our handle to the window we are reading from in this case it would be a game

(LPCVOID)pLocalPlayer is the variable that is read. It takes what ever is stored in pLocalPlayer and reads that address that is why pLocalPlayer is of type DWORD but you may notice that there is (LPCVOID) infront of it. That is because we have to type cast our variable to LPCVOID because RPM only excepts LPCVOID for an argument and not DWORD. You can also just define your variable as LPCVOID in the beginning and not type cast anything. LPCVOID means constant pointer to any type.

The next argument is &playerObjectAddress. This is the variable that we are going to use to store what was read from pLocalPlayer. The & symbol is the address of operator and It simply returns the address of the variable that it operates on.

The next argument sizeof() is how many bytes of data we want to return or read. sizeof(playerObjectAddress) is just saying we want to read 4 bytes because playerObjectAddress is of type DWORD which is 4 bytes. We do sizeof(playerObjectAddress) so we never have to worry about returning the wrong number of bytes.

The next argument we keep NULL because it is a variable that stores the amount of bytes transferred. We don't care how many bytes we have read and setting it to NULL ignores this argument.

Broken down you can look at RPM as this and you can also use this as a template when writing code while you start out -
C++:
 ReadProcessMemory(handleToGame, (LPCVOID)addressToRead, &variableToStoreReadInformation, sizeof(variableToStoreReadInformation), NULL);
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
WPM is very similar to RPM and I am not going to go into as much detail. If you understand RPM then this should be self explanatory.

C++:
WriteProcessMemory(handleToGame, (LPVOID)addressToWriteTo, &variableContainingValueToWrite, sizeof(variableContainingValueToWrite), NULL);
Everything is the same as RPM except except address to read which is replaced with the variable containing the memory address in which you want to write to. The variable containing the address to write to is type casted to LPVOID and not LPCVOID.

The last change is that variableToStoreReadInformation is replaced with the variable containing the value you want to write. You can use the above WPM line of code as a template to help you out in writing your code. Look through some source code on this sight and try to follow the logic with RPM and WPM to get familiar with when and how people use these functions in there code.

Another thing to point out is that since WPM and RPM are functions you can't leave any arugements blank. That is why we write NULL instead of skipping over it. WPM and RPM are normal functions and there for have to be treated like them.
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
If you have any questions post them in the comments and I will try to answer them the best I can also I want to thank Rake for helping me rewrite some stuff. Happy Hacking!
 
Last edited:

Rake

Cesspool Admin
Administrator
Jan 21, 2014
12,073
78,998
2,371
awesome tutorial wes! Want to incorporate some of this into your tutorial and we can make it even more beastly?

I think misspoke when you said WPM and RPM are from the windows.h library, they are from the kernel32 library and will be imported from kernel32.dll at execution. They are defined in memoryapi.h which is included by WinBase.h which is in turn included by Windows.h

LPCVOID is a "pointer constant void" as declared in WinDef.h:
typedef CONST void *LPCVOID;

Pointer meaning it's value is meant to be an address, constant meaning it has a fixed value, void meaning of any type.

& is the "Address of operator", it doesn't have anything to do with pointers. It simply returns the address of the variable that it operates on. In RPM the third argument is LPVOID, a pointer to a buffer. That's why you use the address of operator, it needs the address of the buffer not the identifier of the buffer simply because that is how the function argument is written. All this extra work just to keep the WinAPI function happy :)

The sizeof operator returns the size in bytes of the variable, by using it, you never have to worry about reading/writing the wrong number of bytes

WPM uses LPVOID for the 2nd argument whilst RPM uses LPCVOID

Why use NULL as the fifth argument? We ignore the fifth argument because we don't care how many bytes are read/written

lpNumberOfBytesRead [out]
A pointer to a variable that receives the number of bytes transferred into the specified buffer. If lpNumberOfBytesRead is NULL, the parameter is ignored.
 
W

wtlyons

fixed the errors! Thanks for catching them :D
 
Last edited:

mambda

headass
Escobar Tier VIP
Trump Tier Donator
Jun 25, 2014
2,294
37,938
269
Cool stuff dude, but just fyi "void meaning of any type"

That's not entirely true, as void by itself is just that, void, nothing ( i.e. void function() { return; } ), a void * is technically what you'd mean by "any type", but that can still be confusing if you try to sizeof a void* ( changes from 4 to 8 bytes depending on x86 to x64 ).

All in all, great stuff mate!
 
W

wtlyons

Cool stuff dude, but just fyi "void meaning of any type"

That's not entirely true, as void by itself is just that, void, nothing ( i.e. void function() { return; } ), a void * is technically what you'd mean by "any type", but that can still be confusing if you try to sizeof a void* ( changes from 4 to 8 bytes depending on x86 to x64 ).

All in all, great stuff mate!
I took that part out for now thanks for catching it. I believe it is technically void* and not void after doing a quick search.
 

Rake

Cesspool Admin
Administrator
Jan 21, 2014
12,073
78,998
2,371
Yeah I guess we can simply rephrase that to say "constant pointer to any type", does that make more sense?

And the L = Long meaning 32 bit right?
 

TBA

Newbie
Full Member
Oct 1, 2012
23
307
1
This is gold!!
Being new to hacking this answers alot of questions thank you very much for this!


I couldnt bother you to make another tutorial on how
C++:
HWND hGameWindow = NULL;
works?
Basically how to check for your game if its running and how it attaches to the game and what not..
 
W

wtlyons

C++:
HWND hGameWindow = NULL;
	int timeSinceLastUpdate = clock();
	int GameAvailTMR = clock();
	int onePressTMR = clock();
	DWORD dwProcID = NULL;
	HANDLE hProcHandle = NULL;
	UpdateOnNextRun = true;
	std::string sAmmoStatus = "OFF";
	std::string sHealthStatus = "OFF";

	while (!GetAsyncKeyState(VK_INSERT))
	{

		if (clock() - GameAvailTMR > 100)
		{
			GameAvailTMR = clock();
			IsGameAvail = false;

			hGameWindow = FindWindow(NULL, "AssaultCube");
			if (hGameWindow)
			{
				dwProcID = 0;
				GetWindowThreadProcessId(hGameWindow, &dwProcID);
				if (dwProcID != 0)
				{
					if (hProcHandle != NULL)
					{
						CloseHandle(hProcHandle);
					}
					hProcHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcID);
					if ((hProcHandle == INVALID_HANDLE_VALUE) || (hProcHandle == NULL))
					{
						GameStatus = "Failed To Open Process For Valid Handle";
					}
					else
					{
						GameStatus = "AssaultCube Ready To Hack";
						IsGameAvail = true;
					}

				}
				else
				{
					GameStatus = "Failed To Get Process ID";
				}

			}
			else
			{
				GameStatus = "Failed To Get Process ID";
			}

		}

heres fleeps code. You use FindWindow function https://msdn.microsoft.com/en-us/library/windows/desktop/ms633499(v=vs.85).aspx Then your taking what findwindow returns and testing it. If it is false then it closes the handle ect... Don't focus on the timers(how often it checks the hanlde) and game status (its just a string for user to see) just look at that code and hopefully you will see a handle is created. It's a little more complicated and I might make a tutorial on it.

the handle is hProcHandle and that is what we can then use in our RPM and WRP function like this
C++:
ReadProcessMemory(hProcHandle, (LPCVOID)ValueToRead, &VariableToStoreInfo, sizeof(VariableToStoreInfo), NULL);
you can see once we have our handle we just use it for all of our RPM and WPM functions because you can't read or write to memory without a handle to that memory region. Hope this helped
 
Last edited:
Attention! Before you post:

Read the How to Ask Questions Guide
99% of questions are answered in the Beginner's Guide, do it before asking a question.

No Hack Requests. Post in the correct section.  Search the forum first. Read the rules.

How to make a good post:

  • Fill out the form correctly
  • Tell us the game name & coding language
  • Post everything we need to know to help you
  • Ask specific questions, be descriptive
  • Post errors, line numbers & screenshots
  • Post code snippets using code tags
  • If it's a large project, zip it up and attach it

If you do not comply, your post may be deleted.  We want to help, please make a good post and we will do our best to help you.

Community Mods