Click here to Skip to main content
Click here to Skip to main content

How to write a Memory Scanner using C#

By , 23 Sep 2006
 

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:

A look at the Memory - FirstLook.jpg

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 values mean?

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

A look at the Memory Bits - Bits.jpg

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 values up to (11111111)2 = (255)10 = (FF)16, but how about the bigger values?
We usually work with values greater than 255!
Ok, the answer is that, we have bigger units of memory to hold the bigger values.

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

A look at the Memory Data Types - DataTypes.jpg

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:

Another look at the Memory - LookAgain.jpg

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 values and I will show you that:

Memory Units - MemoryUnits.jpg

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 values of the sectors are the same, but the memory units start from different sectors:

The other Memory Units - TheOtherMemoryUnits.jpg

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:

Game mamory - GameMemory.jpg

So what? Is there any 83 in the memory?
First, we know that we have the hexadecimal values 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:

Memory Search - Animation_1.gif

Memory Search - Animation_2.gif

Memory Search - Animation_3.gif

Memory Search - Animation_4.gif

Memory Search - Animation_5.gif

Memory Search - Animation_6.gif

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 values 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.

Comments on my classes

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 values)!

So the solution I used was this:

if (/*scan requirement is less than 20480 bytes*/)
{
    //Read the memory at once
}
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:

Memory Search solution - Fina_Animation_0.gif

Memory Search solution - Fina_Animation_1.gif

Memory Search solution - Fina_Animation_2.gif

Memory Search solution - Fina_Animation_3.gif

Memory Search solution - Fina_Animation_4.gif

Memory Search solution - Fina_Animation_5.gif

Memory Search solution - Fina_Animation_6.gif

Memory Search solution - Fina_Animation_7.gif

Memory Search solution - Fina_Animation_8.gif

Memory Search solution - Fina_Animation_9.gif

Memory Search solution - Fina_Animation_10.gif

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Sojaner
Web Developer
Iran (Islamic Republic Of) Iran (Islamic Republic Of)
Member
I'm a C# and ASP.Net Programmer and Designer.
I mostly design and write Ajax web applications.
I also write Console and Form Applications mostly for my personal projects.
I have been writing C# and ASP.Net since 2003.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Questionyaw, pitch and rollmemberLarissa Schön3 Aug '12 - 13:57 
I want to get the yaw, pitch and roll aswell it's position in the 3D-World of a character in a game. How would you go about finding them out and changing them?
BugDOS != 8Bitmembermoritz9431 May '12 - 22:51 
Hi,
 
very nice article, but there's a mistake: DOS is a 16bit operating system (or program, the BIOS contains most of the drivers ...). Maybe you should correct it Smile | :)
Anyway, good article Smile | :)
 
Greetings,
moritz94
AnswerRe: DOS != 8BitmemberSojaner1 Jun '12 - 1:34 
Thanks for your interest.
Also thanks for your information, but I think I have read somewhere that DOS has been 8-bit OS sometime in it's life time.
I have no enough time but you may help by reading this and correcting me if I'm really wrong!
Timeline of x86 DOS operating systems[^]
Thanks again.
Sojaner!

GeneralRe: DOS != 8Bitmembermoritz941 Jun '12 - 3:05 
The first DOS's (there were many different from different vendors, I've also written one [very less features^^]) were 8Bit, but MS-DOS was a 16Bit operating system.
It was designed for 80x86 processers, which started as 16Bit ones. Also DOS uses BIOS interrupts, and the BIOS contains 16Bit code on IBM PC's.
80x86 processors doesn't contain a 8Bit mode, there's only 16Bit (Real-)mode, 32Bit (Protected-)mode and 64Bit (Long-)mode.
More informations can be found at osdev.org or lowlevel.eu (german) Smile | :)
 
Greetings,
moritz94 - LittleFox on LowLevel
QuestionstringsmemberKurtis Shafer25 May '12 - 8:16 
I didnt know if you had ever worked out the string variables for the memory scanner. I tried the scanner, but I am confused as to what it is accomplishing. is it finding every instance of a certain int in the memory location that is being scanned. and if it is, what its the second scan for, is it for finding the same value after the values of other variables have most likely changed?
SuggestionRe: stringsmemberSojaner27 May '12 - 10:03 
Your question is not clear to me.What do you mean by the second scan? Do you mean the second scan in the sample memory scanner app provided? If so, how is it related to Strings scanning?
Please repeat your question in a clear way.
Thanks.
Sojaner!

QuestionRe: stringsmemberKurtis Shafer29 May '12 - 6:50 
Mainly I was wondering how to find specific strings in a memory location that is activly being written before it is saved in a log file. I saw that you were looking to write a string locator in memory, but I was wondering how it is done or if you ever did write one. I think that your article is awesome by the way. I just need some guidance on what I could do to find words(strings) in a memory location while a program is writing to it. I want to parse that data and then use it as a variable later. something like when the string "Your syntesis is successful" occurs, the memory program will find that then save it to a memory location and then perform a keyboard command later that will correspond to the string. Something like using the [Enter] button on the keyboard when the string appears. I thought that your idea of a string locator would do this as well.
AnswerRe: stringsmemberSojaner1 Jun '12 - 1:45 
Strings are not native types in most of the programming languages and so, the compiler for that language may store the Strong in the memory, in its unique way...
But most of the languages use a similar way for that...
But there are many types of string encodings and also different types of byte encodings...
For example, the String may be in UTF-8, Unicode, Windows-1256 or many other encodings and byte orders, and the compiler may store the bytes using the big-endian or little-endian byte orders in the memory...
So as you can see, there are many different combinations possible to look for, in the memory...
You have to be completely sure about these parameters or search the memory using all possible combinations that likely takes too long, maybe forever! Wink | ;)
That's the reason why I have never completed my code to find Strings, but of you like, you can use these guidelines and complete it yourself.
I hope these help you.
Sojaner!

GeneralMy vote of 5memberiliabest19 Jan '12 - 5:31 
Perfect article
AnswerRe: My vote of 5memberSojaner24 Feb '12 - 12:10 
Happy you liked it.
Sojaner!

QuestionNeed to search String please.memberAbuS3ood8 Jul '11 - 6:21 
Thanks Sojaner for your excellent sample
 
I have made several tries to make function to search for a specific string and return the addresses but failed and tried several codes from the net, please bro help me with this i still using CheatEngine to get my addresses.
 
thanks in forward,
AnswerRe: Need to search String please.memberSojaner11 Jul '11 - 17:48 
Hi,
I'm happy that you liked my article.
Because of many questions about Strings and finding them in the memory, I will write an example soon, but as I'm really busy right now, it may take some times. I'll try to do so in a week or less, but I do not make a promise.
Hope that helps.
Greetings.
Sojaner!

GeneralRe: Need to search String please.memberAbuS3ood11 Jul '11 - 20:41 
Thanks A lot man for your concern, im still trying to modify the code or create a function to do the job but still lost, waiting for your sample Smile | :)
GeneralRe: Need to search String please.memberAbuS3ood12 Jul '11 - 4:41 
Hi again,
 
I found that the codes im using are correct, but the needed value was saved outside the rage it was supposed to be, i was searching between module.BaseAddress and module.BaseAddress+ module.ModuleMemorySize,
so i got the point to search from 00000000 to 7fffffff,
but can you please help me with a hint how to make it faster, currently im increasing adress +1
,my search string always 6 digits,
thanks for your help.
AnswerRe: Need to search String please.memberSojaner24 Feb '12 - 12:13 
Small and quick hint: As other viewers mentioned you can test the first byte of the string with the current memory byte and if it is equal test the rest of the string.
That would increase the process speed.
Sojaner!

QuestionGame statistics in real-timememberhaxballfan6 Jul '11 - 8:56 
Hi Sojaner.
 
First of all, very nice tutorial ! I'm definitely going to work with it and hopefully it can help me reaching my goal.
 
I was wondering though, is it long to scan the memory of a program ? My objective would be to find some addresses of stored variables from a Flash game, to make statistics out of it. For example, by knowing the game is a multiplayers soccer game (in 2D but that's not important to know I guess), and that I want to make stats such as time possession, score, goals, assists etc.
 
I just want to know if it is even possible in your opinion,
thanks in advance !
 
Greetings,
haxballfan
AnswerRe: Game statistics in real-timememberSojaner11 Jul '11 - 17:40 
Hi,
I'm happy that you liked my article.
I have never used any memory scanner (Including mine) to scan a SWF file's memory. In fact, that's the memory for Flash Player not the SWF file and I have no idea about the memory management that Flash Player does, because a Flash Game, is not a real computer program and it's the Flash Player that deals with the variables and memory management, so there may be some difficulties to reach the variable and so in the memory.
My Memory Scanner is a demonstration to the way computer programs deal with the memory and so I suggest you to use a tool like Cheat Engine to first make sure that you can even reach the variables through the scan process and then you can use my code for your purpose and do the statistics job.
Hope this helps.
Greetings.
Sojaner!

GeneralRe: Game statistics in real-timememberhaxballfan13 Jul '11 - 6:23 
Hi Sojaner, thanks for the answer, I'll keep working on it then Smile | :)
greets
Generalhow to access a specific direction of a program memory [modified]membersjstanich9 Jun '11 - 8:54 
Thanck

modified on Friday, June 17, 2011 10:51 AM

AnswerRe: how to access a specific direction of a program memorymemberSojaner13 Jun '11 - 0:36 
Your question is not clear but if you find the exact address that you are interested in, you can change the code to only freeze that address, it is the last step that my code does, you will understand it if you read the code (it is the code being called by the last form of the window.
But keep in mind that, the addresses in OllyDbg and other debuggers are offsets of real addresses! It means that the first address that has to be 0, will be something like 10000000, and so the code is the offset of 10000000.
Good luck.
Sojaner!

GeneralMy vote of 5memberSagar (Sea)14 Dec '10 - 13:36 
The way he has gone step by step, without jumping directly to the topic is good. The diagrams also help a great deal in making the logic clear. The way he has approached and explained the whole concept has made things look much simpler. All in all, a good article
GeneralRe: My vote of 5memberSojaner13 Jun '11 - 0:30 
I really happy that you liked it. Smile | :)
Sojaner!

Questionhow to scan a float valuememberMember 456277612 Nov '10 - 0:46 
how to scan a float value ??
ex: 2.52
Confused | :confused:
AnswerRe: how to scan a float valuememberSojaner12 Nov '10 - 1:29 
For every variable type, first you need to know, how the value looks like in a byte array.
To do this, you have to use this method:
 

const float floatVariable = 2.52f;
 
byte[] floatByteArray = System.BitConverter.GetBytes(floatVariable);

 
Now you have a byte array that you can look for, in the memory. Wink | ;)
Sojaner!

GeneralMy vote of 5memberBaesky11 Sep '10 - 3:39 
When i use ReadPrcoessMemory to scan the RAM,it dons't work,lasterror=0X0000012B :(.
PS: OS->win7 64bit
GeneralRe: My vote of 5memberMember 456277612 Nov '10 - 0:47 
I used it good on WIN 7 64 bit
AnswerRe: My vote of 5memberSojaner12 Nov '10 - 1:33 
Never tried it on same OS but take care about the "User Account Control" in Windows Vista and higher, this API may be one of the Admin only APIs.
Sojaner!

GeneralPerformance of Sojaner ScannermemberCpt Balu27 Aug '10 - 21:30 
Hello Sojaner!
I'm using your scanner in C#project for many purposes Big Grin | :-D
I just wrote a nice trainer game for Settlers 4. it's workflow is the following:
- Reads resource informations
- Create a map and places resources in correct place
- Can select a resource and edit it through a simple UI
- I use a simple timer for "Freeze" option which means, that amount resources can be frozen (for eg. if a settler takes a stone for construction from a 7-stone storage slot, it remains 7 after pickup)
 
Resource read/write goes well, the only problem is gettin the list of resources.
The memory block where these informations are stored can be overflown, in this case, the program continues listing anywhere. So I have to scan wide area of memory (usually 0x07000000-0x30000000)
This takes much time even if scanning block's size is 20480. But this is the smaller problem, the greater problem is that I don't receive all the values. I tried other memory searchers, and I always get back more result than with this scanner. I think the problem is, that Settler's memory consist lots of block with RW permission of size from 0x4000 to 0x8000, separated with a 0x1000 sized block signed as "reserved". Maybe the reader can't read in such environment. The distance of identifiers I search is 128 bytes if they are in the same block (for eg. after loading a game).
I just want to know whether I can fix it with using another parameters in opening process, freezing memory before scan or etc.
Please tell me if you can advise anything.
Thanks in advance:
Cpt Balu
Hungary
GeneralRe: Performance of Sojaner Scannermembercskult26 Apr '11 - 9:12 
Love it, but could u post something in vb.net? i can search and all, but i take 1 by one and its slow as hell :(
Generalnice article!memberBaesky18 Aug '10 - 17:52 
that's really useful for me!thanks!!
GeneralRe: nice article!memberSojaner13 Jun '11 - 0:39 
I'm happy that you liked it.
Sojaner!

GeneralSojanner let seememberasskiller13 Mar '10 - 9:36 
Your Memory Scanner , is work in Games On-line ? Grand Chase and Gunbound , Scan work's ?
GeneralRe: Sojanner let seememberCpt Balu27 Aug '10 - 21:17 
The memory scanner can scan the memory of process you attach. For LAN/Online games, you can attach the client application, but remember, that some times the client application just gets informations from server. In this case, if you overwrite anything, it will be reset just after querying the server next time. If the server runs the main core for game, then your attempt to modify it will fail. The only way could help you is to attach it as remote process, but I think game server's techincal information are not published :-P
Or if you are hosting a multiplayer game, then just attach the hosting game's process.
GeneralString search example requiredmemberExtreme_man1 Mar '10 - 22:45 
I have spent 10 days looking for example source codes online that would show how to list strings contained in process's memory, but failed to do so...
Please, if someone knows how to do it, it would help me alot.. Thank you..
GeneralRe: String search example requiredmemberSojaner13 Jun '11 - 1:00 
Sorry for delay!
I have been away for a long time!
Looking for strings are so tricky as strings may contain encodings and they vary in length, so looking for a predefined pattern will be so much easier.
This is my thought on listing the Strings in the memory.
Start reading the bytes from beginning till the first null byte (0x00), store the whole array and start doing the same from the next byte after the null byte...
After searching the whole memory for the arrays, examine every array with preferred String Decoder classes to see the results.
This may not be a perfect solution but it may help.
As much as I know, there are string detection algorithms out there on the web but I have never used them.
I hope my reply helps you.
Good luck.
Sojaner!

Generalincrease speed of memory search code by over 50%memberrhboarder23 Sep '09 - 17:11 
you know, you dont need to search the whole memory space of the program in memory. the values that you are looking for, say the health, etc.. are going to be stored in the .data section, which is only a small part of all the memory space the program is using. all you need to do is read the PE headers to get the virtual address of the .data section, then search that. A PE file starts with:
_IMAGE_DOS_HEADER(not important), followed by the _IMAGE_NT_HEADERS, then the Section Table(thats what you want) which is an array of Section Headers, there is one Section Header for each section (.text,.data,idata,etc). find the one for the .data section and it contains the virtual address. As defined in winnt.h:
typedef struct _IMAGE_SECTION_HEADER {
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
    union {
            DWORD   PhysicalAddress;
            DWORD   VirtualSize;
    } Misc;
    DWORD   VirtualAddress;
    DWORD   SizeOfRawData;
    DWORD   PointerToRawData;
    DWORD   PointerToRelocations;
    DWORD   PointerToLinenumbers;
    WORD    NumberOfRelocations;
    WORD    NumberOfLinenumbers;
    DWORD   Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

Generali need helpmembermansan_mansur5 Sep '09 - 10:13 
i need recovry file source Thumbs Up | :thumbsup:
GeneralNeed HELP!!!!!!!!!!!!!memberPavel Rumberg4 Sep '09 - 7:40 
Hello Sojaner!
I'm building a GPS program for my university project.
For that task, I have to write two applications - the GPS software and the GPS emulator, which will throw "GPS String" to my software at some constant rate.
I was looking for a good way to pass variable from one application to another, and the best solution to do that working on fast rates is to create a buffer in which my emulator will write data and the gps software will read from ten times a second.
In order to make it happen, I need to create 2 "double" variables X and Y to store coordinates, and to pass their addresses to the second application.
Because I pass the adresses only once, I can use file.
The problem is to get my variables physical addresses and once passed, to set pointer to them on the other side.
I write using C#.
...hope to get some help from You, since You know thing or two about memory managing!
Thank You for Your time!..
Pavel.
QuestionCharacters and Strings?memberKasperlitheater30 Jul '09 - 14:35 
First of all, thanks a lot for this nice source code.
 
I read your code and all seems to logical to me. But I don't know how to search for string in a game, like "Charactername" and such things.
 
Can you give me a hint?
AnswerRe: Characters and Strings?memberJordanwb27 Oct '09 - 16:27 
I'd like a similar feature but for searching an array of bytes.
AnswerRe: Characters and Strings?memberdzCepheus8 Oct '10 - 8:22 
You'll need to convert the string you're searching for into a byte array using an Encoder, then search for a matching byte array:
 
string search = "CharacterName";
byte[] sBytes = Encoding.ASCII.GetBytes(search);
 
This assumes your game stores the character's name in ASCII - it might also be Unicode, in which case you'll have to change the encoder on your end to match it. The only way to know though is to try different options and see which one picks up the right values.
 
Good luck =)
PS: This is what part of the alphabet would look like if the letters Q and R were removed.

GeneralSOJANER I NEED YOUR HELP :)groupGoor23 Jul '09 - 10:29 
Sojaner... OOO biggest Sojaner x) Thos source code is the BEST Smile | :) But i need this source code in VB.NET, or VB9... Can you rewrite this code into VB(because i'am noob in C#), ooooo most powerfull Sojaner?Big Grin | :-D PleaseFrown | :( and sorry for my bad english x) 5/5
 
VB, VB.NET, C#

AnswerRe: SOJANER I NEED YOUR HELP :)memberSojaner29 Jul '09 - 21:45 
These should help you.
 
C# to VB.net Convertor Program[^]
 
C# to VB.net Convertor Web Application[^]
 
Good luck.
 
Sojaner!

GeneralReadProcessMemory fails when pointing at protected memorymemberThe_Mega_ZZTer16 Nov '07 - 17: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 EF
 
We ReadProcessMemory the first three, everything is OK:
 
Your function: 01 23 45
Mine: 01 23 45
 
We 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 00
Mine: 01 23 45 67 89 AB CD EF
 
Now we read bytes at 0x8 for 5 bytes...
 
Your function: 00 00 00 00 00
Mine: null
 
Still 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 00
Mine: null
 
Where 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.jpg
 
Now 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.jpg
 
Now 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.
GeneralSolution!memberThe_Mega_ZZTer17 Nov '07 - 15:08 
I finally found VirtualQueryEx, which can be used for this exact purpose.
 
Here is my full solution... I will use VB.NET code, but you can get C#.NET equivilants of all my Windows API function declarations at pinvoke.net.
 
STEP 1: We determine which areas of a virtual memory block an application can reside in. Going outside that block can result in VirtualQueryEx throwing errors if we query a kernel area. This is easy enough to fix.
 
Public Declare Sub GetSystemInfo Lib "kernel32.dll" (ByRef lpSystemInfo As SYSTEM_INFO)
 
We use this function to get this information, and the following one wraps it up nicely.
 

Public Shared Function GetAppMemoryRange() As MZZT.MemoryRange
If _appmem Is Nothing Then
Dim si As SYSTEM_INFO
GetSystemInfo(si)
_appmem = New MZZT.MemoryRange(si.lpMinimumApplicationAddress, _
si.lpMaximumApplicationAddress)
End If
 
Return _appmem
End Function
Private Shared _appmem As MZZT.MemoryRange = Nothing

 
You will notice an MZZT.MemoryRange class. It is simple enough that I don't think I need to explain it here, but I designed it to hold a 32-bit memory range (a start, and an end) which you can see I use to store the maximum range it is safe to use VirtualQueryEx on.
 
You can get the MemoryRange class at the end of this post if you really really want it.
 
Next we need some declarations for VirtualQueryEx and helper structures and enumerations:
 
Public Declare Function VirtualQueryEx Lib "kernel32.dll" (ByVal hProcess As IntPtr, _
ByVal lpAddress As UIntPtr, ByRef lpBuffer As MEMORY_BASIC_INFORMATION, ByVal _
dwLength As UInteger) As UInteger

<Runtime.InteropServices.StructLayout(Runtime.InteropServices.LayoutKind.Sequential)> _
Public Structure MEMORY_BASIC_INFORMATION
Public BaseAddress As UIntPtr
Public AllocationBase As UIntPtr
Public AllocationProtect As PAGE
Public RegionSize As UInteger
Public State As MEM
Public Protect As PAGE
Public Type As Integer
End Structure
 
Public Enum PAGE As Integer
EXECUTE = &H10
EXECUTE_READ = &H20
EXECUTE_READWRITE = &H40
EXECUTE_WRITECOPY = &H80
NOACCESS = &H1
[READONLY] = &H2
READWRITE = &H4
WRITECOPY = &H8
 
GUARD = &H100
NOCACHE = &H200
WRITECOMBINE = &H400
 
ANYREAD = &H66
ANYWRITE = &HCC
End Enum
 
Public Enum MEM As Integer
COMMIT = &H1000
FREE = &H10000
RESERVE = &H2000
End Enum

 
Now we will make a few small helper functions:
 

Private Function CanRead(ByVal mbi As WinAPI.MEMORY_BASIC_INFORMATION) As Boolean
If mbi.Protect And WinAPI.PAGE.GUARD Then
Return False
End If
 
If mbi.State <> WinAPI.MEM.COMMIT Then
Return False
End If
 
Return True
End Function
 
Private Function CanWrite(ByVal mbi As WinAPI.MEMORY_BASIC_INFORMATION) As Boolean
If mbi.Protect And WinAPI.PAGE.GUARD Then
Return False
End If
 
If mbi.State <> WinAPI.MEM.COMMIT Then
Return False
End If
 
Return True
End Function
 
Private Function GetMBIRange(ByVal mbi As WinAPI.MEMORY_BASIC_INFORMATION) As _
MemoryRange
 
Return New MemoryRange(mbi.BaseAddress, CDec(mbi.BaseAddress) + _
CDec(mbi.RegionSize) - 1)
End Function

 
More use of my secret class. Wink | ;)
 
CanRead determines from the information obtained through VirtualQueryEx (which is an mbi struct) whether or not we will be able to read it with ReadProcessMemory. CanWrite will do the same for WriteProcesMemory... right now I haven't made CanWrite work since I'm not concerned with writing memory at the moment. It will likely need a flag check for a WRITE attribute. GetMBIRange turns the mbi into a MemoryRange object.
 
Now the main function, which takes a MemoryRange and returns an array of MemoryRanges which are not protected. So we would pass the Range we want to read, and then iterate through the resulting array and read each MemoryRange one at a time.
 
Public Function FindUnprotectedMemory(ByVal range As MemoryRange, ByVal writable As _
Boolean) As MemoryRange()
 
range = range.Intersect(WinAPI.GetAppMemoryRange)

 
My MemoryRange class has an intersect function which works like the one on rectangle.. it returns the area the two MemoryRanges share in common. In this case, it clips of areas in range which do not belong to the application, since we already know we can't read those.
 
If range Is Nothing Then
Return Nothing
End If

 
Intersect returns null if the MemoryRanges have nothing in common.
 
Dim a As New ArrayList
Dim mbi As WinAPI.MEMORY_BASIC_INFORMATION
Dim pos As UInteger = range.RangeStart
Dim applies As MemoryRange
Dim access As Boolean
 
While pos <= range.RangeEnd

 
pos records the current memory address we are inspecting with VirtualQueryEx. Once we pass range we are done and can quit.
 
If Not WinAPI.VirtualQueryEx(_handle, pos, mbi, _
Runtime.InteropServices.Marshal.SizeOf(mbi)) Then
 
Dim ex As New System.ComponentModel.Win32Exception
If ex.NativeErrorCode <> 0 Then
Throw ex
End If
End If

 
Oddly, VirtualQueryEx returns 0 all the time, even though the MSDN docs say it should only do so on error. I put in an extra error check.
 
applies = GetMBIRange(mbi).Intersect(range)
 
It's possible for VirtualQueryEx to return an area which extends before or after our block. This clips it to the block we are interested in.
 
If writable Then
access = CanWrite(mbi)
Else
access = CanRead(mbi)
End If

 
The actual test to see if we can read/write.
 
If access Then
a.Add(applies)
End If

 
Add it to our master list of addresses that are not protected.
 
pos = applies.RangeEnd + 1
End While

 
Move on to the next memory page/block.
 
If a.Count = 0 Then
Return Nothing
End If
 
Return a.ToArray(GetType(MemoryRange))
End Function

 
Return our array, or null if the entire thing is protected.
 

 
PS: Now that ReadProcessMemory should no longer be returning protected memory errors, I altered my function accordingly:
 

Public Function ReadMemory(ByVal range As MemoryRange) As Byte()
Dim read As UInteger = 0
Dim buffer(range.RangeSize - 1) As Byte
If Not WinAPI.ReadProcessMemory(_handle, range.RangeStart, buffer, _
range.RangeSize, read) Then
 
Throw New System.ComponentModel.Win32Exception
End If
 
If read = 0 Then
Return Nothing
End If
 
If read <> range.RangeSize Then
Array.Resize(Of Byte)(buffer, read)
End If
Return buffer
End Function

 
I did not make much changes apart from the exception. I was going to integrate VirtualQueryEx right into ReadMemory, but then I realized my calling function would still need the array of unprotected addresses. So I let the calling function handle the masking out of protected addresses and kept ReadMemory simple.
 
PPS: Here is my MemoryRange class:
 
Namespace MZZT
Public Class MemoryRange
Implements ICloneable
 
Public Sub New(ByVal address As UInteger)
_start = address
_end = address
End Sub
 
Public Sub New(ByVal rangestart As UInteger, ByVal rangeend As UInteger)
_start = rangestart
_end = rangeend
End Sub
 
Public Property RangeStart() As UInteger
Get
Return _start
End Get
Set(ByVal value As UInteger)
_start = value
End Set
End Property
Private _start As UInteger
 
Public Property RangeEnd() As UInteger
Get
Return _end
End Get
Set(ByVal value As UInteger)
_end = value
End Set
End Property
Private _end As UInteger
 
Public ReadOnly Property RangeSize() As UInteger
Get
Return _end - _start + 1
End Get
End Property
 
Public Function Intersect(ByVal r As MemoryRange) As MemoryRange
If _start > r.RangeEnd OrElse r.RangeStart > _end Then
Return Nothing
End If
 
If _start >= r.RangeStart Then
If _end <= r.RangeEnd Then
Return Clone()
Else
Return New MemoryRange(_start, r.RangeEnd)
End If
Else
If r.RangeEnd <= _end Then
Return r.Clone
Else
Return New MemoryRange(r.RangeStart, _end)
End If
End If
End Function
 
Public Function Clone() As Object Implements System.ICloneable.Clone
Return New MemoryRange(_start, _end)
End Function
End Class
End Namespace

 

-- modified at 21:13 Saturday 17th November, 2007
QuestionProblems with finding a valuemembermathg15 Oct '07 - 8:58 
I seem to have problems with this code, as in 9 out of 10 trys I cant finde a specific value in a process memory. My debugger is finding the value without any problems, and I just cant find the problem with my (and your sample) code.
 
The value I try to find is 0x50, 0x00, 0x14, 0x00; => 1310800.
 
Why is your memory scanner only showing the address sometimes, and not all the time?
GeneralRe: Brilliant thinkingmemberSojaner6 Aug '07 - 10:14 
I'm so happy that you liked it.
I'm looking forwad for you program.
I hope I can help you.Smile | :)
Thank you my friend. Rose | [Rose]
 
Sojaner!

Generalanother memory scannermemberskumria30 Jul '07 - 1:22 
check this one. its free
 
http://bnf-soft.com
 
look for link to memory scanner there
GeneralReally usefulmemberMrKalinka11 Jul '07 - 7:53 
I like this article very much. Good job!
Generalcool~membernancun30 May '07 - 17:33 
:I have learned a lot from your article

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 23 Sep 2006
Article Copyright 2006 by Sojaner
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid