4

I know there are many tutorials out there showing you how to use the "ProcessMemoryReader" functions. But this problems seems to be unique or not solved yet.

For quite a while I've been digging into other people's code to find a way to use multiple offsets. And I thought that using multiple offsets was the problem for me, but I think it's a problem with the fact that my offset value is bigger than 255.

The game I'm trying to get the memory values from is called "Assault Cube". As I wasn't sure whether I got the right offset values I googled what others results where. They seem to be exactly the same: http://cheatengine.org/tables/moreinfo.php?tid=1142 (You can view the .ct file with notepad if you don't have cheat engine installed.)

Here is my code, using the ProcessMemoryReader.cs.

private void timer1_Tick(object sender, EventArgs e)
{
int bytesread;
int pointerbase;
byte[] memory;
Process[] myprocess = Process.GetProcessesByName("ac_client");
if (myprocess.Length != 0)
{
preader.ReadProcess = myprocess[0];
preader.OpenProcess();

//Ammo
memory = preader.ReadProcessMemory((IntPtr)0x4DF73C, 4, out bytesread);
pointerbase = BitConverter.ToInt32(memory, 0);
pointerbase += 0x00; //0 // 14 // 378

byte[] memory1 = preader.ReadProcessMemory((IntPtr)pointerbase, 4, out bytesread);
int pointerbase1 = BitConverter.ToInt32(memory1, 0);
pointerbase1 += 0x14; //0 // 14 // 378

byte[] memory2 = preader.ReadProcessMemory((IntPtr)pointerbase1, 4, out bytesread);
int pointerbase2 = BitConverter.ToInt32(memory2, 0);
pointerbase2 += 0x378; //00 // 14 // 378

byte[] memory3 = preader.ReadProcessMemory((IntPtr)pointerbase2, 4, out bytesread);
int valueis = BitConverter.ToInt32(memory3, 0);
label1.Text = valueis.ToString();
}

Though with a single pointer the process works fine, for example:

 //HP
 memory = preader.ReadProcessMemory((IntPtr)0x4DF73C, 4, out bytesread);
 pointerbase = BitConverter.ToInt32(memory, 0);
 pointerbase += 0xf4;

 byte[] memory1 = preader.ReadProcessMemory((IntPtr)pointerbase, 4, out bytesread);
 int valueis = BitConverter.ToInt32(memory1, 0);
 label2.Text = valueis.ToString();

So that works, it's pretty straight forward what's happening here, but I can't figure how to read the Ammo code with the multiple offsets.

Gottlieb Notschnabel
  • 9,408
  • 18
  • 74
  • 116
Arndroid
  • 314
  • 3
  • 13
  • 1
    ReadProcessMemory() doesn't have such a restriction. In the 2nd snippet you are reading a pointer to an integer. That's pretty simple. In the 1st snippet you are reading a pointer to a pointer to a pointer to an integer. That's not so simple. One small mistake and you'll read garbage. – Hans Passant Apr 17 '13 at 03:25

2 Answers2

0

I'm not familiar with CheatEngine and it's table format, but I do not get the impression it's pointing to the memory addresses that you are using.

You read 4 bytes at 0x4DF73C, which is used as the new memory address for the next read. This is repeated a few times. Basically, you're reading information from a pointer to a pointer to a pointer. Are you sure this is what is intended?

There's no reason whatsoever that an offset value greater than 255 would be a problem.

Thorarin
  • 47,289
  • 11
  • 75
  • 111
0

Use FindDMAAddy to walk the pointer chain for you, here is a working example, make sure you run as admin:

public static IntPtr FindDMAAddy(IntPtr hProc, IntPtr ptr, int[] offsets)
{
    var buffer = new byte[IntPtr.Size];

    foreach (int i in offsets)
    {
        ReadProcessMemory(hProc, ptr, buffer, buffer.Length, out
        var read);
        ptr = (IntPtr.Size == 4) ? IntPtr.Add(new IntPtr(BitConverter.ToInt32(buffer, 0)), i) : ptr = IntPtr.Add(new IntPtr(BitConverter.ToInt64(buffer, 0)), i);
    }
    return ptr;
}

var modBase = GetModuleBaseAddress(proc.Id, "ac_client.exe");

var ammoAddr = FindDMAAddy(hProc, (IntPtr)(modBase + 0x10f4f4), new int[] { 0x374, 0x14, 0 });

Console.WriteLine("Ammo address " + "0x" + ammoAddr.ToString("X"));

int newAmmo = 1337;

byte[] buffer = new byte[4];

ReadProcessMemory(proc.Handle, ammoAddr, buffer, 4, out _);

Console.WriteLine("Ammo value " + BitConverter.ToInt32(buffer, 0).ToString());

WriteProcessMemory(hProc, ammoAddr, newAmmo, 4, out _);
GuidedHacking
  • 3,628
  • 1
  • 9
  • 59