12,820,108 members (23,456 online)
alternative version

#### Stats

248.2K views
155 bookmarked
Posted 23 Sep 2006

# How to write a Memory Scanner using C#

, 23 Sep 2006 CPOL
 Rate this:
Search a process' memory to find specified 16, 32 or 64 bit data values.

## Introduction

Have you ever had a problem completing a game because your health meter shows just 5% of your health available?
Have you ever used a game trainer to solve this problem?
Have you ever wondered how this trainer freezes your health meter to 100%?
These game trainers, do a simple job!
They write a little part of the Game's memory with the 100 `value`!
But how to find the exact part of memory?

## The Question and the Answer

Q: How to find the location in which a program stores a `value` in its memory?
A: Some programs named 'Memory Scanners', are written to read and search a program's memory for exact location and help freezing it! (And I have written this article to show you, how to write a 'Memory Scanner')

## Step 1: Where to begin?

Let's have a look at a program's memory.
Think that I have written a program and we can have a look at its memory.
To have a picture in mind, we can say, it looks something like this:

As you can see, the memory is made up of a huge number of small sectors, that hold a `value` in it. Our picture, just shows a small part of the memory, from sector 0 to sector 99 and a detail of sector 0 to sector 15. But as you know, a computer just knows the meaning of 0 and 1, so what do these Hexadecimal `value`s mean?

Let's take a deep look at the memory again.

As you can see, every byte is made up of 8 bits with each of them being just that 1 or 0, and in Binary mode, they can return the `value` stored in the byte((00010111)2 = (23)10 = (17)16).

As we saw, a computer's memory stores information by holding the 0 and 1s in the memory bits, and 8 bits of memory make a section of memory named byte, so a byte can hold `value`s up to (11111111)2 = (255)10 = (FF)16, but how about the bigger `value`s?
We usually work with `value`s greater than 255!
Ok, the answer is that, we have bigger units of memory to hold the bigger `value`s.

Let's look at another picture of memory that shows the bigger units and then, I will explain everything:

So we have 3 bigger memory units: 2 `Bytes` that make a 16 bit memory unit that we call 'short' in C#, 4 `Bytes` that make a 32 bit memory unit that we call it 'int' in C#, and 8 `Bytes` that make a 64 bit memory unit, and we call it 'long' in C#.

## Step 2: What to look for?

Now that we have a simple picture of the memory in our mind, let's go back to the first picture:

I know that, you are going to say: "Hey, it's just a row of `bytes`! How to find the memory units?" And then I'll tell you that, you asked the biggest question in writing a memory scanner!

Ok, let's think that it's a part of the memory of my program, and I know, where in the memory, I have stored the `value`s and I will show you that:

As you see, a memory unit, can be stored in any part of the memory and start from any memory sector. In this program for example, I have stored a 32 bit `value` in the 0 sector, and because a 32 bit `value` takes 4 `bytes` of memory, from the sector 0 to sector 3 is assigned for a 32 bit variable in the program, and after that, from the sector 4, there is a 16 bit variable that takes 2 `bytes` of memory, next is a 64 bit variable and at the end, there is again a 16 bit variable.

Now let's think that the `value`s of the sectors are the same, but the memory units start from different sectors:

Why everything changed?
Because, a variable could be stored in any memory sector number, and most of the time, even the programmer doesn't know, where the variable is stored in the memory, and just the program knows it!

## Step 3: Where to find it?

Now, let's think that we are playing a game, and the health meter shows 83%, and we don't know the location of the variable in the memory and we want to find the variable and we start from sector 0, so the memory looks like this:

So what? Is there any 83 in the memory?
First, we know that we have the hexadecimal `value`s of the memory `bytes`. Second, we should guess the variable type to look for.

Ok, let's say that the programmers of the game have used a 32 bit (int) variable, that is the most usual data type being used for storing the `value` of the health meter. So the `value` is stored in a 4 `bytes` long part of the memory. But, how to find it?
The only way to search the memory completely, is to start from the beginning, take 4 `bytes`, test them to see if the `value` equals our digit (here 83), and find the location. Like this:

Ok, now you know the main concept of memory scanning, but there are some other things that you should know to be able to write the Memory scanner:

1. Q: How long is a program's memory? (Where to begin and where to stop?)
A: As you know, Microsoft's first OS was DOS that was a 8 bit OS, after that, the Windows 3.1 became a 16 bit OS, and after that, the Windows OS became a 32 bit OS. (I'm a real fan of Apple Co. that developed the Apple Macintosh OS, a 64 bit OS, exactly when Microsoft was working on DOS (a 8 bit OS) and today, Microsoft is going to write a 64 bit Windows (and like the first Windows versions, it still looks like the Apple OSs) but, I still recommend Apple MacOS X (Ver. 10)).
So, in the DOS OS that was a 8 bit OS, programmers named 8 bits of memory, a "Byte". After that, When the Windows 3.1 OS was a 16 bit OS, they named 16 bits of memory(2 `Bytes`) a "WORD", and 32 bits of memory(4 `Bytes`) a "DWORD"(Double Word) and 64 bits of memory(8 `Bytes`) a "QWORD"(Quad Word).
As I experienced, the length of every program's memory in Windows XP, is from "0x00000000" to the maximum `value` of a "Int"("DWORD"), and equals to "0x7FFFFFFF".
I'm not sure, but I guess, it's because of that, the Windows is a 32 bit OS and the main memory unit for it, is a 32 bit memory unit, and so, the length of a program's memory, is the maximum `value` of a 32 bit memory unit!
Ok. So, we should start our search from "0x0000000" to "0x7FFFFFFF".
2. Q: Is the first found memory address, the exact answer of our search?
A: No! As you can see, there are "0x7FFFFFFF" sectors, and when you search it for a `value` like 83, you could find so many of them. So you need to hold the memory addresses and wait for the `value`s to be changed. Then search the addresses you have, for the new `value`, and do this, until you find, just one memory address that matches your `value`.
3. Q: How to read a program's memory and search it?
A: There are some functions in Windows API that make it possible for us to read and write the memory, from another program.
Thanks goes to "Arik Poznanski" for P/Invokes and methods needed to read and write the Memory, I just used his classes to do this and didn't do the P/Invokes myself.
You can search Codeproject.com, for "Minesweeper, Behind the scenes", to find his comments about these classes.
4. Q: How to convert these `bytes` to a 16, 32 or 64 bit `value`?
A: For this, we used .NET goods! There is a class with static methods that does this for us:

```byte[] bytes = new byte[] { 0x53, 0x00, 0x00, 0x00 };
int value = System.BitConverter.ToInt32(bytes, 0);
//The value is 83
```

## Step 4: Let's do the final job

Ok, now you have all the information you need to write the memory scanner.
You just need to do these in your code:

1. Select a process to scan its memory.
2. Scan the whole memory for the specified `value` and hold the addresses.
3. Wait for the `value` to be changed and search the memory address list that you got from the first scan and again wait for the `value` to be changed and scan again, and do this until you find just the address that matches the `value`.
4. At the end, you can freeze the address with a new `value`, by using a timer to write the memory in every timer's tick.

If you download my code, you will find them with comments for every command and every line of code. But there it a little thing I should explain:

`ReadProcessMemory(IntPtr MemoryAddress, uint bytesToRead, out int bytesRead)` that is the most important function, returns an empty `bytes` array if reading your request's size is too big! So I had to read the memory in parts as big as 20480 `bytes` (20KB), and because, when you are searching these memory parts, byte by byte, at the end of the `bytes` array, there will be some `bytes` left! (for example, 3 `bytes` will be left when you are searching for 32 bit `value`s)!

```if (/*scan requirement is less than 20480 bytes*/)
{
}
else
{
/*Loop through blocks(of length 20480 bytes),
until the whole memory is read;

After the first loop, move the current address to
[Data type bytes count - 1] steps back in the memory,
to fix the previously told problem;

After the loops, check to see if any other memory addresses
are left outside of the loops and if so, read them;*/
}
```

You can see it:

## That's all

Ok folks, that's all! Hope you like and enjoy it!
And now I'm working on a Enhanced Memory Scanner that could scan all types of data, including the `Bytes`, Signed Data Types and even Strings, it just takes some time!
I'll be back soon.

## Share

 CEO Sweden
MVC/SPA designer and programmer.
C# programmer on .net/mono/monomac/monotouch/monodroid frameworks.
jQuery/Knockout/Angular programmer.
And has been working since 2002.

## You may also be interested in...

 Pro Pro

 i need help mansan_mansur5-Sep-09 11:13 mansan_mansur 5-Sep-09 11:13
 Need HELP!!!!!!!!!!!!! Pavel Rumberg4-Sep-09 8:40 Pavel Rumberg 4-Sep-09 8:40
 Characters and Strings? Kasperlitheater30-Jul-09 15:35 Kasperlitheater 30-Jul-09 15:35
 Re: Characters and Strings? Jordanwb27-Oct-09 17:27 Jordanwb 27-Oct-09 17:27
 Re: Characters and Strings? dzCepheus8-Oct-10 9:22 dzCepheus 8-Oct-10 9:22
 SOJANER I NEED YOUR HELP :) Goor23-Jul-09 11:29 Goor 23-Jul-09 11:29
 Re: SOJANER I NEED YOUR HELP :) Sojaner29-Jul-09 22:45 Sojaner 29-Jul-09 22:45
 ReadProcessMemory fails when pointing at protected memory The_Mega_ZZTer16-Nov-07 18:03 The_Mega_ZZTer 16-Nov-07 18:03
 Hi, I'm trying to use your article to build my own memory scanner / hex editor / game cheat thing etc. I already have such a tool but I wanted a challenge.However I have run into a problem and after checking your code it appears your program would suffer from the same problem, although you don't even check for an error.The problem is this: large areas of a processes memory are protected. ReadProcessMemory will fail when trying to read from such a place.I will show an example of various desired and undesired results, and what both your code and my code do.Here is my relevant VB code for reference, which I think improves on yours a bit, although the calling function has to do more checks on the returned data (ie IsNot Nothing, or != null):```Public Function ReadMemory(ByVal start As UInteger, ByVal length As UInteger) As Byte() Dim read As UInteger = 0 Dim buffer(length - 1) As Byte WinAPI.ReadProcessMemory(_handle, start, buffer, length, read) If read = 0 Then Return Nothing End If If read <> length Then Array.Resize(Of Byte)(buffer, read) End If Return buffer End Function ```Let's say we have a chunk of memory that looks like this starting at 0x00000000, where the Xs are protected:01 23 45 67 89 AB CD EF XX XX XX XX XX 01 23 45 67 89 AB CD EFWe ReadProcessMemory the first three, everything is OK:Your function: 01 23 45Mine: 01 23 45We read 10 bytes, and the last two get cut off. This is ok because we still get all the data we can access:Your function: 01 23 45 67 89 AB CD EF 00 00Mine: 01 23 45 67 89 AB CD EFNow we read bytes at 0x8 for 5 bytes...Your function: 00 00 00 00 00Mine: nullStill acceptable behavior. Now this is where it gets ugly.Let's read 10 bytes from the same place:Your function: 00 00 00 00 00 00 00 00 00 00Mine: nullWhere we would really like to convey the actual contents of XX XX XX XX XX 01 23 45 67 89 somehow...To summarize, if the starting address is protected, the ENTIRE read fails, even if later parts of the specified address range are unprotected!A visual demonstration... the pictured control does one ReadProcessMemory operation on the entire pictured block of memory... here is a result with an entirely non-protected block:http://x.mzzt.net/0039.jpgNow if we scroll up one line, we have the top line as a protected block. The whole read operation is blank:http://x.mzzt.net/0040.jpgNow my problem is, how do I determine where a protected area ends? If I have a condition like 40.jpg, I can't tell unless I read every single protected byte one at a time until I find the first unprotected one... and that is SLOW.I know there must be a Windows API function to get the addresses of these protected areas, because the program I use for memory scanning can show me those ranges in a list.So my question is... what is it? I've been looking through the API docs and I can't see anything relevant.I figure it's my lack of expertise in this area that's responsible... the term "memory pages" keeps popping in my head but I don't remember enough about OS-level memory management to know if this is what I'm running into. Not that I saw any API functions relating to pages either.I'm also curious if it's possible to do this a lazy way... like, can I count on a certain boundary for these areas (ie I'd only need to check once every 0xXXXX bytes instead of checking every protected byte to find the end of the protected area). PS: I think you should consider splitting your article into two articles, one on basics of memory and another on your actual program. This way those of us who were expecting just an article on the program don't have to go past a bunch of stuff we already know... you can have it in a separate article for those of us who don't know. Also you should expand more on the actual program and how it operates... right now most of your article about that is just theory and not how you actually implemented it.BTW I assume when you are referring to *-bit OSs you mean the maximum number of bits used to access memory, and thus the limit on how much memory the OS supports. Nowadays that's what the *-bit means in modern OSs, but when you are talking about the *-bit of microprocessors there are a few different metrics that can be used... it's all very confusing but I will just say there has never been an 8-bit OS as far as memory usage. 8 bits is only enough to fit 256 bytes, you can't do ANYTHING in that. And I know for a fact DOS was 16-bit, with the exception of extenders like DOS4GW and Windows 386 Enhanced mode which enabled some 32-bit functionality in supported programs.
 Solution! The_Mega_ZZTer17-Nov-07 16:08 The_Mega_ZZTer 17-Nov-07 16:08
 Problems with finding a value mathg15-Oct-07 9:58 mathg 15-Oct-07 9:58
 Re: Brilliant thinking Sojaner6-Aug-07 11:14 Sojaner 6-Aug-07 11:14
 another memory scanner skumria30-Jul-07 2:22 skumria 30-Jul-07 2:22
 cool~ nancun30-May-07 18:33 nancun 30-May-07 18:33
 Really Nice! Coksnuss9-Feb-07 6:03 Coksnuss 9-Feb-07 6:03
 Re: Really Nice! Sojaner18-Feb-07 1:15 Sojaner 18-Feb-07 1:15
 scan game memory fail flash.lin1-Feb-07 15:18 flash.lin 1-Feb-07 15:18
 Re: scan game memory fail Sojaner18-Feb-07 1:13 Sojaner 18-Feb-07 1:13
 CloseHandle Error ic3dwabit21-Dec-06 16:25 ic3dwabit 21-Dec-06 16:25
 Re: CloseHandle Error Sojaner29-Dec-06 14:05 Sojaner 29-Dec-06 14:05
 Re: CloseHandle Error ic3dwabit8-Jan-07 23:09 ic3dwabit 8-Jan-07 23:09
 Error 299 Hall Maru28-Oct-06 4:15 Hall Maru 28-Oct-06 4:15
 Re: Error 299 Sojaner29-Dec-06 14:08 Sojaner 29-Dec-06 14:08
 Re: Error 299 [modified] The_Mega_ZZTer16-Nov-07 16:55 The_Mega_ZZTer 16-Nov-07 16:55