[C#]Reading Memory / Pointer with multiple Offsets.

01/08/2013 03:51 iCraziE#1
I am used to coding in AutoIt. I am trying to move my project into C# but I have only about 2-3 weeks of experience.

In AutoIt, I have this code here that reads the process memory and returns a value.

Code:
$map = _MemoryRead(0x00B5CCB8, $handle) // Pointer address 0x00B5CCB8
$map = _MemoryRead($map + 0x02, $handle) // Offset 0x02
$map = _MemoryRead($map + 0xBD, $handle) // Second Offset 0xBD
I am trying desperately to convert this to C# language and I need some help. Here is what I have so far.

Code:
Process process = Process.GetProcessesByName("My Process").FirstOrDefault();
            int address = 0x00B5CCB8;
            int offset1 = 0x02;
            int offset2 = 0xBD;
            int bytesRead;

            byte[] pointer = ProcessMemoryReaderApi.ReadMemory(process, address, 4, out bytesRead);
Using this works, but I don't know how to add the necessary offsets to the address. If someone could help me out with this one. That would be greatly appreciated.

Here is the class that I am using.

Code:
class ProcessMemoryReaderApi
    {
        // constants information can be found in <winnt.h> 
        [Flags]
        public enum ProcessAccessFlags : uint
        {
            All = 0x001F0FFF,
            Terminate = 0x00000001,
            CreateThread = 0x00000002,
            VMOperation = 0x00000008,
            VMRead = 0x00000010,
            VMWrite = 0x00000020,
            DupHandle = 0x00000040,
            SetInformation = 0x00000200,
            QueryInformation = 0x00000400,
            Synchronize = 0x00100000
        }

        [DllImport("kernel32.dll")]
        private static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out int lpNumberOfBytesWritten);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, out int lpNumberOfBytesRead);

        [DllImport("kernel32.dll")]
        public static extern Int32 CloseHandle(IntPtr hProcess);

        public static byte[] ReadMemory(Process process, int address, int numOfBytes, out int bytesRead)
        {
            IntPtr hProc = OpenProcess(ProcessAccessFlags.All, false, process.Id);
            byte[] buffer = new byte[numOfBytes];

            ReadProcessMemory(hProc, new IntPtr(address), buffer, numOfBytes, out bytesRead);
            return buffer;
        }
Thanks in advance.

PS. I would also like to have a message box that will show me the value that is returned when the address is read.
01/08/2013 05:08 »jD«#2
Assuming you are using .NET 4 you can use the IntPtr Add() and Subtract() methods. For example:

Code:
IntPtr baseAddr = new IntPrt(0x00B5CCB8); 
IntPtr newAddr = IntPtr.Add(baseAddr, 0x02);
Hope that helps! Also, unless doing multiple reads on the same OpenProcess handle, you should probably call CloseHandle() after doing the Read in ReadMemory().

-jD
01/08/2013 05:44 iCraziE#3
Thanks for the reply!

I got an error but i fixed it.. Everything is working now, I think.. theres no way for me to see what the returned value is.

Is there anyway to show the value that was read at the address? in a messagebox perhaps?
01/08/2013 05:55 »jD«#4
Include this overload method in the "ProcessMemoryReaderApi" class:

Code:
public static byte[] ReadMemory(Process process, IntPtr address, int numOfBytes, out int bytesRead)
        {
            IntPtr hProc = OpenProcess(ProcessAccessFlags.All, false, process.Id);
            byte[] buffer = new byte[numOfBytes];

            ReadProcessMemory(hProc, address, buffer, numOfBytes, out bytesRead);
            return buffer;
        }
Quote:
Originally Posted by iCraziE View Post
I got an error but i fixed it.. Everything is working now, I think.. theres no way for me to see what the returned value is.

Is there anyway to show the value that was read at the address? in a messagebox perhaps?
Sure, the returned value will be a byte array, assuming it was an integer you read from the memory you can use:

Code:
byte[] valueOut = ProcessMemoryReaderApi.ReadMemory(process, address, 4, out bytesRead);
int value = BitConverter.ToInt32(valueOut, 0);
MessageBox.Show("Value of Integer: " + value.ToString());
-jD
01/08/2013 06:17 iCraziE#5
valueOfMem does not exist in current context.
should it be valueOut instead of valueOfMem?
01/08/2013 06:26 »jD«#6
Yes it should sorry -.-

-jD
01/08/2013 06:30 iCraziE#7
also this line to close the handle is saying invalid arguments,
cannot convert from system.diagnostic.process to intptr

ProcessMemoryReaderApi.CloseHandle(myProcess);
01/08/2013 06:32 »jD«#8
you should use CloseHandle() inside the ReadMemory call with the 'hProc' variable.

For example:

Code:
public static byte[] ReadMemory(Process process, IntPtr address, int numOfBytes, out int bytesRead)
        {
            IntPtr hProc = OpenProcess(ProcessAccessFlags.All, false, process.Id);
            byte[] buffer = new byte[numOfBytes];

            ReadProcessMemory(hProc, address, buffer, numOfBytes, out bytesRead);
            CloseHandle(hProc);
            return buffer;
        }
Just so I know, I'd be nice to see an output from this or letting me know if the output was what you expected ;)

-jD
01/08/2013 06:36 iCraziE#9
I hope it will be :) ill let you know, you've been a GREAT help!!

btw, my applications always say this.. whenever i execute them and then close it.

and lets say i try to rebuild it, rename the exe or delete it, if the target process is still open.

Ill get an error and it says the application is still open in the process execute.

is there anyway to stop this. Like make it so that when i close it, it will not stay attached to the target process?

would a simple application.exit() on the close form event do the trick? or is this just a helpless situation?

also it apparently attaches itself to the process, without me even opening it O_O.

and lastly not sure why, but its not returning the right value..

the value of the address changes everytime i move to a new area in the game. this function is supposed to tell me the value of the area that im in. for instance one place will have a value of 3, then if i move somewhere else it will have a new value, lets say 7. then if i go back to the first area, it will be 3 again. each area has its own value.

I know the address and offsets are correct because if i do this with autoit, it works perfectly fine. =/
01/08/2013 07:09 »jD«#10
Not quite sure whats going on... maybe a screenshot could help?

-jD
01/08/2013 08:26 iCraziE#11
Here's my entire code. If you insist on a SS i can do that too. I just figured this would be simpler.

01/08/2013 08:32 »jD«#12
I'm assuming you change "my process" to the process you are trying to access the memory from?

-jD
01/08/2013 08:41 iCraziE#13
Yes, of course :)
01/09/2013 05:57 »jD«#14
Hmmm, are you sure you called CloseHandle in ReadMemory?

-jD
01/09/2013 11:27 iCraziE#15
yes, I managed to figure it out. Thanks for your help :)

Here is my call, if anyone is also stuck with the same problems i had.

Code:
Process myProcess = Process.GetProcessesByName("My Process").FirstOrDefault();
            int bytesRead;

            int pointeraddr = 0x00BDCC32;

            byte[] valueOut = ProcessMemoryReaderApi.ReadMemory(myProcess, pointeraddr, 4, out bytesRead); ///read address 1
            int value = BitConverter.ToInt32(valueOut, 0); /// convert to Int32
            string newAddr = DecToHex(value); // convert to hex
            IntPtr mpAddr = (IntPtr)HexToDec(newAddr); // convert to decimal as IntPtr
            IntPtr mpAddr2 = IntPtr.Add(mpAddr, 0x02); // add offset
            int newmpAddr = mpAddr2.ToInt32(); // convert to int for address 2

            byte[] value2 = ProcessMemoryReaderApi.ReadMemory(myProcess, newmpAddr, 4, out bytesRead); // read address 2
            int value2Out = BitConverter.ToInt32(value2, 0); // convert to int32
            string mp = DecToHex(value2Out); //convert to hex
            IntPtr mp2 = (IntPtr)HexToDec(mp); // convert to decimal as IntPtr
            IntPtr secMpAddr = IntPtr.Add(mp2, 0xBD); //add second offset
            int fMpAddr = secMpAddr.ToInt32(); // convert to int for address 3

            byte[] value3 = ProcessMemoryReaderApi.ReadMemory(myProcess, fMpAddr, 4, out bytesRead); // read address 3
            int value3Out = BitConverter.ToInt32(value3, 0); // convert to int32
            string MpVal = value3Out.ToString(); //convert to string for output.

            MessageBox.Show(MpVal);