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

Minesweeper, Behind the scenes

By , 13 Jan 2003
 
Prize winner in Competition "C# Dec 2002"

Sample Image - minememoryreader.jpg

Introduction

Ever wanted to know what is happening in the Minesweeper game behind the scenes?
Well, I did, and I decided to investigate it. This article is the result of my research, brought here just for you.

Main Concepts

1. Using P/Invoke to invoke Win32 API's.

2. Direct reading another process memory.

NOTE: the first part of this article involves some assembly code, if there something you don't understand it's NOT important to the goal of this article. you CAN skip it. Nevertheless, if you want to ask me about it, you're more then welcome to mail me your question.

NOTE 2: The program was tested on Windows XP, so if you got some other system it might not work.. if you got some other system, and it did worked, comment this article with your system info so we all could enjoy that knowledge.

Update to NOTE 2: the code is now fixed in order to work on Windows 2000 as well. thanks goes to Ryan Schreiber for finding the addresses in Win2K.

Step 1 - Investigate winmine.exe

If you're not an assembly fan, you might want to skip to the end of this step, to the conclusions..

So, in order to know better what is happening behind the scenes of Minesweeper I've started by opening the file in a debugger. My personally favorite debugger is Olly Debugger v1.08, this is a very simple and intuitive debugger. Anyway, I've open winmine.exe in the debugger and looked a bit on the file. I've found in the Import section (a section that lists all the dll functions that are used in the program) the following entry:

010011B0  8D52C377 DD msvcrt.rand
which means that the Minesweeper uses the randomize function of the MicroSoft Visual C RunTime dll, So I thought it might help me. I've search the file to find where the rand() function is being called, I've found only one such place:

01003940  FF15 B0110001 CALL DWORD PTR DS:[<&msvcrt.rand>] 

Then I've put a breakpoint on this single call and ran the program. I've discovered that every time you click the smiley a new mines map is generated. the mines map is created as follows:

1. Allocate a block of memory for the mines map and set all the memory bytes to 0x0F, which means that there is no mine in that "cell".
2. second, loop over the number of mines and for each mine:
2.1. randomize x position (1 .. width).
2.2. randomize y position (1 .. height).
2.3. set the correct cell in the memory block to 0x8F, which represents a mine in this cell.

here is the original code, I've added some remarks, and bolded the important parts:

010036A7  MOV DWORD PTR DS:[1005334],EAX    ; [0x1005334] = Width
010036AC  MOV DWORD PTR DS:[1005338],ECX    ; [0x1005338] = Height
010036B2  CALL winmine.01002ED5  ; Generate empty block of memory and clears it
010036B7  MOV EAX,DWORD PTR DS:[10056A4]
010036BC  MOV DWORD PTR DS:[1005160],EDI
010036C2  MOV DWORD PTR DS:[1005330],EAX    ; [0x1005330] = number of mines
                    ; loop over the number of mines
010036C7  PUSH DWORD PTR DS:[1005334] ; push Max Width into the stack 
010036CD  CALL winmine.01003940       ; Mine_Width  = randomize x position (0 .. max width-1)
010036D2  PUSH DWORD PTR DS:[1005338] ; push Max Height into the stack
010036D8  MOV ESI,EAX
010036DA  INC ESI                ; Mine_Width = Mine_Width + 1
010036DB  CALL winmine.01003940  ; Mine_Height = randomize y position 
                                 ; (0 .. max height-1)
010036E0  INC EAX                ; Mine_Height = Mine_Height +1
010036E1  MOV ECX,EAX            ; calculate the address of the cell in the memory block 
                                 ; (the map)
010036E3  SHL ECX,5              ; the calculation goes:
                                 ; cell_memory_address = 0x1005340 + 32 * height + width
010036E6  TEST BYTE PTR DS:[ECX+ESI+1005340],80 ; [cell_memory_address] == is already mine?
010036EE  JNZ SHORT winmine.010036C7   ; if already mine start over this iteration
010036F0  SHL EAX,5                    ; otherwise, set this cell as mine
010036F3  LEA EAX,DWORD PTR DS:[EAX+ESI+1005340]
010036FA  OR BYTE PTR DS:[EAX],80
010036FD  DEC DWORD PTR DS:[1005330]        
01003703  JNZ SHORT winmine.010036C7   ; go to next iteration 
As you can see from the code I've discovered 4 important things:
  1. Reading the memory in address [0x1005334] gives me the Width of the map.
  2. Reading the memory in address [0x1005338] gives me the Height of the map.
  3. Reading the memory in address [0x1005330] gives me the number of mines in the map.
  4. Given x,y that represents a cell in the map, in column x, row y, the address [0x1005340 + 32 * y + x] gives me the cell value.

Which brings us to the next step..

Step 2 - Design a solution

You might wonder, what kind of solution am I talking about? Well, after discovering that all the mine information is available for me, and all I need to do is read the data from the memory I've decided to write a small app that reads this information and present it for you. It can even draw a map of its own, with a picture of a mine wherever I find one..

So, what is to design about that? all I need to do is put the address into a pointer (yes, they exist even in C#) and read the pointed data, right? well, not exactly, the reason why this is not the case is that the memory where this data is stored is not in my application. You see, each process has its own address space so it could not access "by accident" memory that belongs to another program, so in order to read this data I need to find a way to read the memory of another process, in this case, its the Minesweeper process.

I've decided to write a small class library, that will receive a process and will give me the functionality of reading a memory address from this process. the reason I've decided to make it a class library is because there is allot of cases you might want to use it so why develop it again and again? That way, you could easily take the class and use it in your own application, and you are free to do so. An example for where this class can help is if you write a debugger. All the debuggers I know have the ability to read memory of the debugged application..

So, how do we read another process memory? the answer resides in an API called ReadProcessMemory. this API actually let you read a process memory at a specific address. Only before you do it you must open the process in a special read mode and when you finish you must close the process handle, to avoid resource leaks. The following operations are performed with the help of two more API called OpenProcess and CloseHandle.

In order to use API's with C# you must use the P/Invoke, meaning you need to declare the API you're going to use, which is basically quite simple, but you need to do it in the .NET way, which is not that simple sometimes.. I've found the API declarations in the MSDN:

HANDLE OpenProcess(
    DWORD dwDesiredAccess,       // access flag
    BOOL bInheritHandle,         // handle inheritance option
    DWORD dwProcessId            // process identifier
    );

BOOL ReadProcessMemory(
    HANDLE hProcess,            // handle to the process
    LPCVOID lpBaseAddress,      // base of memory area
    LPVOID lpBuffer,            // data buffer
    SIZE_T nSize,               // number of bytes to read
    SIZE_T * lpNumberOfBytesRead  // number of bytes read
    );

BOOL CloseHandle(
    HANDLE hObject              // handle to object
    );

Well this declaration transformed to the following C# declarations:

[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(
    UInt32 dwDesiredAccess, 
    Int32 bInheritHandle, 
    UInt32 dwProcessId
    );

[DllImport("kernel32.dll")]
public static extern Int32 ReadProcessMemory(
    IntPtr hProcess, 
    IntPtr lpBaseAddress,
    [In, Out] byte[] buffer, 
    UInt32 size, 
    out IntPtr lpNumberOfBytesRead
    );

[DllImport("kernel32.dll")] public static extern Int32 CloseHandle(
    IntPtr hObject
    );
If you want to know more information on the types conversions between c++ and c#, I suggest you searched msdn.microsoft.com for the topics: "Marshaling Data with Platform Invoke". Basically, if you put there what is logically true, it will work. sometimes, a bit tuning is requested.

After I have these functions declared, all I need to do is wrap them with a simple class and use it. I've put the declarations in a separate class called ProcessMemoryReaderApi, only to be more organized. The main utility class is called ProcessMemoryReader. This class has a property named ReadProcess, this property is from the type System.Diagnostics.Process, this is where you put the process you want to read its memory.

The class has a method which opens the process in the read memory mode:

public void OpenProcess()

{
    m_hProcess = ProcessMemoryReaderApi.OpenProcess(
                         ProcessMemoryReaderApi.PROCESS_VM_READ, 1, 
                         (uint)m_ReadProcess.Id);

}
The PROCESS_VM_READ constant tell the system to open the process in read mode, and the m_ReadProcess.Id states what process do I want to open.

The most important method in the class is the one that reads the memory from the process:

public byte[] ReadProcessMemory(IntPtr MemoryAddress, uint bytesToRead, 
                                out int bytesReaded)
{
    byte[] buffer = new byte[bytesToRead];

    IntPtr ptrBytesReaded;
    ProcessMemoryReaderApi.ReadProcessMemory(m_hProcess,MemoryAddress,buffer,
                                             bytesToRead,out ptrBytesReaded);

    bytesReaded = ptrBytesReaded.ToInt32();

    return buffer;

}
This function declares a byte array in the requested size and read the memory with the API. Simple as that.

And finally, the method that close it all:

public void CloseHandle()

{
    int iRetValue;
    iRetValue = ProcessMemoryReaderApi.CloseHandle(m_hProcess);
    if (iRetValue == 0)
        throw new Exception("CloseHandle failed");

}

Step 3 - Using the class

Well, here comes the fun part. Using the class in order to read Minesweeper memory and reveal the map. In order to use the class you must first instantiate it:

ProcessMemoryReaderLib.ProcessMemoryReader pReader
                   = new ProcessMemoryReaderLib.ProcessMemoryReader();

then, you need to set the process you want to read its memory, here is an example of how to get the Minesweeper progress, once it is loaded, and set it as the ReadProcess property:

System.Diagnostics.Process[] myProcesses
                   = System.Diagnostics.Process.GetProcessesByName("winmine");
pReader.ReadProcess = myProcesses[0];
and all we need to do now is Open the process, read the memory, and close it when we finish. Again, here is an example of how its been done. Here I read the memory address that represent the Width of the map.
pReader.OpenProcess();

int iWidth;
byte[] memory;
memory = pReader.ReadProcessMemory((IntPtr)0x1005334,1,out bytesReaded);
iWidth = memory[0];

pReader.CloseHandle(); 

that simple!

In conclusion I present you the full code that reveals the map of mines. Don't forget, all the memory places I'm accessing are places found in the first section of this article..

// resource manager for the picture of the mine
System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(Form1));

ProcessMemoryReaderLib.ProcessMemoryReader pReader
                   = new ProcessMemoryReaderLib.ProcessMemoryReader();

System.Diagnostics.Process[] myProcesses
               = System.Diagnostics.Process.GetProcessesByName("winmine");

// take first instance of minesweeper you find
if (myProcesses.Length == 0)
{
    MessageBox.Show("No MineSweeper process found!");
    return;
}
pReader.ReadProcess = myProcesses[0];

// open process in read memory mode
pReader.OpenProcess();

int bytesReaded;
int iWidth, iHeight, iMines;
int iIsMine;
int iCellAddress;
byte[] memory;

memory = pReader.ReadProcessMemory((IntPtr)0x1005334,1,out bytesReaded);
iWidth = memory[0];
txtWidth.Text = iWidth.ToString();

memory = pReader.ReadProcessMemory((IntPtr)0x1005338,1,out bytesReaded);
iHeight = memory[0];
txtHeight.Text = iHeight.ToString();

memory = pReader.ReadProcessMemory((IntPtr)0x1005330,1,out bytesReaded);
iMines = memory[0];
txtMines.Text = iMines.ToString();

// delete the previous button array
this.Controls.Clear();
this.Controls.AddRange(MainControls);

// create new button array, for drawing the mine map
ButtonArray = new System.Windows.Forms.Button[iWidth,iHeight];

int x,y;
for (y=0 ; y<iHeight ; y++)
    for (x=0 ; x<iWidth ; x++)
    {
        ButtonArray[x,y] = new System.Windows.Forms.Button();
        ButtonArray[x,y].Location = new System.Drawing.Point(20 + x*16, 70 + y*16);
        ButtonArray[x,y].Name = "";
        ButtonArray[x,y].Size = new System.Drawing.Size(16,16);

        iCellAddress = (0x1005340) + (32 * (y+1)) + (x+1);
        memory = pReader.ReadProcessMemory((IntPtr)iCellAddress,1,out bytesReaded);
        iIsMine = memory[0];

        if (iIsMine == 0x8f)
            ButtonArray[x,y].Image = ((System.Drawing.Bitmap)
                                     (resources.GetObject("button1.Image")));

        this.Controls.Add(ButtonArray[x,y]);
    }

// close process handle
pReader.CloseHandle();

That's it. Hope you leaned something new.

History

  • 14 Jan 2003 - updated demo code

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

About the Author

Arik Poznanski
Software Developer (Senior) Sela Technology Center
Israel Israel
Member
Arik Poznanski is a Senior Consultant and Instructor at Sela Technology Center. He completed two B.Sc. degrees in Mathematics & Computer Science, summa cum laude, from the Technion in Israel.
 
Arik has extensive knowledge and experience in many Microsoft technologies, including .NET with C#, WPF, Silverlight, WinForms, Interop, COM/ATL programming, C++ Win32 programming and reverse engineering (assembly, IL).

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   
GeneralMy vote of 5memberSudesh Ryan9 Nov '12 - 6:45 
Cool article
GeneralMy vote of 5membergndnet14 Jul '12 - 6:37 
Awesome
QuestionFantastic program!memberEduard_Bagrov8 Jan '12 - 0:57 
Thank you very much for this program and article.
There is also one difficult part, how to find the address of space and how to understand whether
1005334 is the width of map or this is the return value from some function, maybe this is the value of some temporary object...
How to understand, how to investigate this part?
 
Fantastic program!
Regards,
Eduard
QuestionNice Articlememberzokker1316 Nov '11 - 22:35 
Thank you for sharing this.
 
I was able to built a little tool which allows me to throw you back into a game when it starts.
 

 
Awesome.
GeneralMy vote of 5memberBaesky18 Aug '10 - 19:26 
nice!
GeneralMy vote of 5mvpEddy Vluggen20 Jul '10 - 2:08 
Pleasant read, good explanation and usefull snippets Smile | :)
GeneralMy vote of 5memberTerranceSmith7 Jul '10 - 10:22 
Taught me tons!!
GeneralMy vote of 1memberadilrao27 Apr '10 - 2:38 
cant understand
GeneralRe: My vote of 1mvpEddy Vluggen20 Jul '10 - 2:07 
..since you voted the article a 1, I assume that you're blaming the article for being to complex? It says that it's intended audience would be intermediate level, and I kinda agree Smile | :)
I are Troll Suspicious | :suss:

GeneralASM!memberSVPro25 Jun '09 - 1:02 
Let's teach me how you find offset and memory in ASM! exam:[0x1005330] = number of mines, ...
010036E3 SHL ECX,5 ; the calculation goes:
 
; cell_memory_address = 0x1005340 + 32 * height + width
QuestionScanning hwnd memorymemberOlyster15 Nov '08 - 7:18 
Hi,
 
I managed to scan the memory of a process using ReadProcessMemory but what I'd like to do is to read only the memory of a certain control in a process.
 
Is there a way of doing this or I have to parse the whole output ? Is there a way of finding the memory range used by the control ?
 
I want to get text of a control (MFCGridCTRL)in another app so maybe reading video memory is another avenue ?
 
Thanks for your input
QuestionHow to access the import section in ollydbg?memberpyro strex23 Feb '08 - 21:02 
can someone or this thread starter help me?, i search, search and search but can't find the answer thank you. I hope someone will answer.
AnswerRe: How to access the import section in ollydbg?memberzokker1316 Nov '11 - 22:37 
OllyDBG can't find it.
 
Don't know why, maybe because it's a windows' game.
 

Doesn't matter anyways, just use Cheat Engine to find Values.
GeneralAddresses for Windows 2000, two places? [modified]memberDaniel Monzert12 Dec '07 - 11:45 
Ahoy,
 
I have become interested in the technique of memory accessing just recently. So I got myself your personal favourite in debuggers and started fiddling around with my Minesweeper myself.
 
Now I wonder the addresses of Windows 2000 can be obtained in another place than discovered by Ryan Schneider. That is, 0x10052C4 for the number of mines, 0x10052C8 for height and 0x10052CC for width. All close together like your Win XP addresses.
 
I'm quite okay at interpreting data and hacking through bytes and I'm familiar with datatypes. I guess Ryan Schneider found the dimensions of the array of the game field there? But I'm yet not that much into Minesweeper's memory Smile | :) I also ponder over the 0x10 bytes all over the place at the mine field.
 
Anyways, the values of the addresses always match, even after playing a few fields away or marking fields. I wonder, which set of addresses should be preferred or would you prefer?
 
/edit/
Also, what has been confusing related to Minesweeper (at least for my win2k version), it seems it gives you a loser's second chance. Because if you hit a mine with your first click, the mines are redistributed.
/snip/
 
Regards,
Daniel
 
modified on Wednesday, December 12, 2007 6:26:23 PM

GeneralThx alot =Dmembertarkster219 Nov '07 - 21:40 
Just what i've been looking for. Thanks =D
GeneralCopyrightmembersabrown10014 Nov '07 - 8:57 
I would like to have a go but are you sure this is legal?
GeneralWindows VistamemberAkshay Chandrasekhar17 Sep '07 - 21:49 
Hi Arik,
Have you any idea about minesweeper in windows vista? I find that the msvcrt.rand function is being used in about three places. Could you give me any pointers? I want to design something like this for windows vista.
 
Thanks,
Akshay
 
The game is not over until I win it.
GeneralRe: Windows VistamemberChris Kolkman10 Oct '07 - 8:49 
I'm trying to get it to run on Vista as well - I've almost got it working. I just can't seem to find the memory addresses for locating the Mines.
 
Here's what I've got so far:
Process name is no longer "winmine" its "MineSweeper"
The following are the address spaces for obtaining the Width/height/num mines.
iWidthAddress = 0x1173464;
iHeightAddress = 0x1173460;
iMinesAddress = 0x117345C;
 
Because you can have more than 255 mines (FF - the max single byte) it requires more than one byte in memory. Looking at those addresses, I'd say it was a four byte numeric value. I changed the program to get all four bytes. But this came up with another problem - those four bytes equals one number - so I created a function to fix that as well.
    memory = pReader.ReadProcessMemory(iWidthAddress, 4, out bytesReaded);
    iWidth = byt2Int(memory);
    txtWidth.Text = iWidth.ToString();
 
    memory = pReader.ReadProcessMemory(iHeightAddress, 4, out bytesReaded);
    iHeight = byt2Int(memory);
    txtHeight.Text = iHeight.ToString();
 
    memory = pReader.ReadProcessMemory(iMinesAddress, 4, out bytesReaded);
    iMines = byt2Int(memory);
    txtMines.Text = iMines.ToString();
    public int byt2Int(byte[] bytes)
    {
        string trueByte = "";
        for (int i = bytes.GetUpperBound(0); i >= 0; i--)
        {
            trueByte += ((int)bytes[i]).ToString("X");
        }
        int retVal = int.Parse(trueByte, System.Globalization.NumberStyles.AllowHexSpecifier);
        return retVal;
    }
 
I'm not sure where to find the mines - anyone know how we can locate the memory address(es) we need for the mines?
GeneralRe: Windows VistamemberAkshay Chandrasekhar9 Nov '07 - 17:45 
Thanks Chris but I am afraid your code isn't working. In windows vista, I believe that iWidthAddress, iHeightAddress and iMinesAddress are not universal. They change from machine to machine. This can be validated by debugging "Minesweeper.exe" on two different machines. The address space will be different. I am therefore trying to find another way to solve this problem. Please tell me what you think.
 
Regards,
Akshay
GeneralRe: Windows VistamemberChris Kolkman13 Nov '07 - 2:42 
Yes, I think you are right.
 
Now I remember that something about Vista's memory management automatically makes memory addresses dynamic. This would make it harder to find.
GeneralRe: Windows Vistamemberspearwall26 Jan '08 - 18:31 
thank you, I tried to use your function to read memory of another process, not minesweeper and got one propblem.

int pAddress = 0x009D1440;
int p;
memory = pReader.ReadProcessMemory((IntPtr)pAddress, 4, out bytesReaded);
p = byt2Int(memory);

I knew exactly value of the int p was 0x0D194004 (which was show in Cheat Engine) but my code wrote out p = 0x0D19404 (one zero was missed).
how to my code write out exactly p is 0x0D194004 ?
Sorry for noob question Blush | :O
GeneralRe: Windows VistamemberChris Kolkman28 Jan '08 - 7:14 
Not necessarily a noob question as there is a flaw I just noticed.
    public int byt2Int(byte[] bytes)
    {
        string trueByte = "";
        for (int i = bytes.GetUpperBound(0); i >= 0; i--)
        {
            trueByte += ((int)bytes[i]).ToString("X"); /* Error exists here */
        }
        int retVal = int.Parse(trueByte, System.Globalization.NumberStyles.AllowHexSpecifier);
        return retVal;
    }
On the error line it's truncating the leading zero of that byte - try this instead:
        public int byt2Int(byte[] bytes)
        {
            string trueByte = "";
            for (int i = bytes.GetUpperBound(0); i >= 0; i--)
                trueByte += ((int)bytes[i]).ToString("X").PadLeft(2,'0');
            int retVal = int.Parse(trueByte, System.Globalization.NumberStyles.AllowHexSpecifier);
            return retVal;
        }

GeneralRe: Windows Vistamembersk9324 Apr '08 - 12:32 
no need for the Byt2Int function...
 
BitConverter.ToInt32(bytes) will do the job nicely Wink | ;)
GeneralNice but...membersharpiesharpie15 Jul '07 - 3:09 
I still don't get it, how did you know it was 32*y+x?
GeneralNicememberDrazura18 Jun '07 - 1:29 
Very nice but how do i use it? i'm kinda noob
QuestionHelpmemberdevil.hell6 Jun '07 - 1:58 
I'm Very new in C# can you please send me the full code in one source file.
 
Thanks a lot...

 
ddd
Generalsouce filesmemberTyler Hock22 May '07 - 12:26 
what do the source files at the top do?

GeneralVirtualQueryEx in c#memberpujs15 Nov '06 - 7:40 
Im trying to use this function in c#.
Im not sure what I'm doing wrong but I always get a empty MEMORY_BASIC_INFORMATION structure back.
And I can't find ANY examples with google about this function, all i get is C# and VB.NET declaration of this api function.
 
here is the code:
 

[StructLayout(LayoutKind.Sequential)]
public struct MEMORY_BASIC_INFORMATION
{
IntPtr BaseAddress;
IntPtr AllocationBase;
uint AllocationProtect;
uint RegionSize;
uint State;
uint Protect;
uint Type;
}
[DllImport("Kernel32.dll", EntryPoint = "VirtualQueryEx")]
public static extern long VirtualQueryEx(int hProcess, IntPtr lpAddress, MEMORY_BASIC_INFORMATION x3, long dwLength);

Ok, I know how to get the first argument - handle of the process, but i stil can get this code working.
Thanks for your help.
 

GeneralRe: VirtualQueryEx in c#memberpinturic26 Mar '07 - 21:32 
I am having the same problem as you !
 
the struct is always filled with zero !
did you solve the problem ?
 
thank you very much and bye bye

GeneralRe: VirtualQueryEx in c#memberCodeNeos19 Oct '07 - 12:30 
Try this:
 
[DllImport("Kernel32.dll", EntryPoint = "VirtualQueryEx")]
public static extern long VirtualQueryEx(int hProcess, IntPtr lpAddress, ref MEMORY_BASIC_INFORMATION x3, long dwLength);
QuestionScanning a Processes Memorymemberaquateen4 Oct '06 - 14:51 
Arik,
 
I find your code simply amazing, and elegant.
 
I am currently trying to scan a processes memory and locate where it stores certain values, in this case where a poker application stores the card values for each player at the table.
 
I am looking at all of the values in Olly's right now, and see places that mark my interest, but what should I be looking for specifically to target these areas of memory. (e.g., EAX registers, PUSH commands, RETURN commands, etc.)
 
Any help is greatly appreciated, my mailing address is jon@blake.net and I will post some of the striking memory locations & their values @ http://silenceisdefeat.org/~forte/mem/
 

Thank you very kindly,
 
Jon
QuestionHow do i scan the memory of a process?memberbunnyEATINGrabbit7 Jul '06 - 5:52 
I realise this question comes after some years since this article was published. Still, i have a question which was asked before on this site, but apparently has never been answered:
 
What if i want to scan the memory of a process to find some variables ? For instance i want to create a game trainer like ArtMoney. I introduce a value, and the program finds all the locations in the process' memory which mach my value.
 
My question is simple: where do i start the search, and where do i stop. I already tried the dummest thing, which was to scan from 0x00000000 and until i find my value... Obviously it got blocked at some point, before finding my value...
 
I was thinking that most likely, every process has to have a unique address where it memorizes the variables... But i don't know and i can't seem to find anything about that on the net...
 
Please help. Or at least guide me to an article solving my problem.
 
Thanks
 
bunny EATING rabbit
AnswerRe: How do i scan the memory of a process?memberSojaner11 Sep '06 - 14:30 
Hi bunnyEATINGrabbit!
I've just started using the pointers in C# (i'm not so new in C# but not that expert that the code heros are!) and when I saw this project and got the point of reading another processes memory and then I saw your question, I tried what you asked for and became almost successful and just wanted to know if you are still intrested in solving the problem or not?
If you are, so alert me to help you!Smile | :) Rose | [Rose]
You can even contact me @ sojaner@yahoo.com Cool | :cool: Rose | [Rose]
 
Sojaner
GeneralRe: How do i scan the memory of a process?memberMember 45338261 Oct '08 - 10:27 
Hello, I am looking for a solution for a similar problem. Please let me know how you solved it.
GeneralRe: How do i scan the memory of a process?memberSojaner1 Oct '08 - 11:35 
Hi, I solved it by written a Memory Scanner.
Take a look at it buddy:
http://www.codeproject.com/KB/cs/sojaner_memory_scanner.aspx[^]
I hope that it helps you.
Generalgreat code!memberoasr29 Jun '06 - 5:31 
great code man. really, nice.
Generalfinallymemberlostmie21 Jun '06 - 22:41 
finally i know how to win!!!!!
:->
Generalcomment and questionmemberBalboos20 Jun '06 - 3:21 
Comment:
A nice piece of work. I can already imagine some useful applications for the technique (once the memory is located). I'd imagine writing applications with an absolute memory location withing the apps memory space would make this easier to use.
 
Question:
For the few who commented on using it to play minesweeper - why ??? I can never seem to understand why someone would want to play and win a single-player game by cheating. What is the point? Really. I would love an explaination so I could understand.
 
"The difference between genius and stupidity is that genius has its limits." - Albert Einstein
Generalcool code...membersnowtek30 May '06 - 10:33 
actually this answered my question about minesweeper.
You cannot hit a bomb on your first click! Smile | :)
It re create the cells again if you hit the a bomb on the first click...
 
cool program... wish to use the code someday...
 
snowtek
GeneralDetermine how wide the memory space is...memberCrossbreed25 May '06 - 8:07 
So, I'm writing something similar to this, but the variables are not always in the same location. What I plan on doing is simply scanning the entirety of the application's memory and search for the text immediately preceeding the variable i want.
 
My problem is, how can I determine how much memory exists inside an application? I've tried a few of the likely .net variables but they don't return a number which corresponds with the size Windows reports (the size of that application in memory.)
 
Any ideas?
Questionquestion???memberpq4noeh22 May '06 - 1:29 
There is something i don't understand the app has depending on the os version running
constant memory addresses
else // winXP
{
iWidthAddress = 0x1005334;
iHeightAddress = 0x1005338;
iMinesAddress = 0x1005330;
iCellBaseAddress = 0x1005340;
}
 
1.- well does it means the os has allways reserved this addresses to the winmine?
2.- what if the winmine does not ever run, it's stupid keep memory space for an app wich we don´t know if it's going to ever be run, isn`t it?, and if it is not reserved we might be looking at the wrong position?
 
3.- So i've thought about this and the only thing that came up and make sense was we are not refering to an absolute memory adress instead we referr to the "iWidthAddress = 0x1005334" within the memory space of the winmine process. is this the answer or it is not?
 
NOthing by now;)
AnswerRe: question???memberCrossbreed25 May '06 - 8:01 
Weird...I think I actually know enough to answer this.
 
1. No, the operating system does not always lock that piece of memory for that particular app.
2. Answered in 1
3. 0x anything is what's called an offset. It's the distance from memory adress zero relative to that application. Minesweeper is nice because its memory is static and you will always know where certain pieces of information are.
 
I'm not certain why the operating system matters, but I'd imagine it has to do with the way the application is compiled on each is different.
Generalnice one!memberMaxxi8624 Mar '06 - 8:16 
I did learn alot form it!
And it was very nice to read Smile | :)
 
Keep the good work goingSmile | :)
GeneralGreat article!memberAvi harush14 Dec '05 - 22:03 
I've learned a lot from this article
 
Thanks Smile | :)
GeneralMSN GamessussAnonymous23 Oct '05 - 10:16 
Is it possible to hack the MSN GAMES version of minesweeper flags?
If it is and it doesn't mean breaking any rule can you put together a program and put it here?
General2 mem locs per parametermemberscripticle23 Oct '05 - 4:42 
Very nice Tut, thanks arikp.
 
I notice through tsearch when looking at the mem locations that there are 2 places affected. The offsets above are one, but there is a second which stores the same info for each of those parameters.
 
I have noticed that if I change the info at the address above (eg I changed the number of mines at 1005330) it gets overwritten. So to make the change I have to do it in a different area (in the case of xp pro 10056A4). The same happens with width/ht.
 
I am wondering if this other loc is something to do with the input form where you can enter custom parameters.
 
My other question is say you want to reset all the mines remotely (same as clicking on the smily face) how does one do that? Can you invoke a process remotely just as you can read memory?
 
This same question refers to if you would like to "click" on a button as if you were going to play the game from the computer.
GeneralMinesweeper reversingmemberNickDigital_codedigger8 Jul '05 - 9:05 
Hello friend ...
i was jus browsing around when i had a look at this article of urs .. good effort, i must say ... even i designed something like this in assembly, a couple of years ago ...
wat i did was, use the mouseover to show where the bomb is when its pointing to a grid... it was only done when the special sneaking mode was active and it was all with dll injection in the process... Anyway this method of yours is also a good one ... all the best for ur future work ...
good day
 
Mess with the best,
Die like the rest.
Questioncongratulations! So cool, So clever! Could you help me?memberSojaner2 Jul '05 - 12:44 
You did it so nice and clear!Rose | [Rose] Smile | :)
 
Could you help me?Cry | :((
(I'm a C#.net coder!)
I need the "Context Switch" of so program's thread!OMG | :OMG:
I found that in .net framework v1.1, you can reach the target program's threat by this code:
System.Diagnostics.Process[] theProcess = System.Diagnostics.Process.GetProcessesByName("TargetProgram");
System.Diagnostics.ProcessThread theThread = theProcess[0].Threads[4];

but they didn't include any property or field or method or..., that returns the Context value!Frown | :(
So I went for it and found the "GetThreadContext" function of "kernel32.dll" and in MSND it was explaind like this:
BOOL GetThreadContext(
HANDLE hThread,
LPCONTEXT lpContext
);
//hThread
//[in] Handle to the thread whose context is to be retrieved

and I found this codes on the net for the C# version:
[DllImport("kernel32.dll", SetLastError=true)] static extern int GetThreadContext ( int hThread, ref CONTEXT lpContext)
//from the here: href="http://network.programming-in.net

and no more matches!Frown | :(
But I can not undrestand what should I do when I have to create a "CONTEXT" class(Maybe! I don't know what it is!)WTF | :WTF:
I used it this way and found error:
System.Runtime.Remoting.Contexts theContext;
int contextSwitch = GetThreadContext(theThread.Id,ref theContext);

Please help me if you can!Sigh | :sigh: Thanx alot!Rose | [Rose] Cool | :cool:
 
Sojaner
Questionwriting?memberUnruled Boy11 May '05 - 6:06 
well, reading is ok, how about writtingLaugh | :laugh:
 
Regards,
unruledboy@hotmail.com
AnswerRe: writing?membermoodytwo21 May '05 - 9:20 
the opposit of ReadProcessMemory function is WriteProcessMemory function and is used
to copy data from the specified buffer in the current process to the address range of the specified process.
 

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 14 Jan 2003
Article Copyright 2003 by Arik Poznanski
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid