Search code examples
c#cheat-engine

C# Multilevel pointers wrong last calc


I am currently trying to implement memory read in C# on base pointers found using Cheat Engine. I am 100% sure I have found the right pointers and offsets since they work just fine in Cheat-Engine, even between restarts.

I am now implementing it in C#, have not had any issues with single level points, but for some reason I can't get my last multilevel pointer to work.

It all goes well until the last value it has to add and then it returns something "random" to me, these are the pointers I have found and I can see it works in Cheat Engine.

enter image description here

This is my implementation in C#:

public static int ReadFromPointer(int address, int[] offsets)
{
    Console.WriteLine("----------");
    Console.WriteLine("Address: " + address);
    int ptr = ReadPointer(address);
    Console.WriteLine($"Pointer returned as int: {ptr}, hex: {ptr:X}");
    foreach (var offset in offsets)
    {
        Console.WriteLine($"Adding offset: {offset:X} to Pointer: {ptr:X}");
        ptr = ReadPointer(ptr + offset);
        Console.WriteLine($"Pointer returned as int: {ptr}, hex: {ptr:X}");
    }
    Console.WriteLine("----------");
    return ptr;
}

private static int ReadPointer(int adress)
{
    int ptrNext;
    int bytesRead = 0;
    byte[] _Value = new byte[4];
    ReadProcessMemory((IntPtr)ProcessHandle, (IntPtr)adress, _Value, IntPtr.Size, ref bytesRead);
    ptrNext = BitConverter.ToInt32(_Value, 0);
    return ptrNext;
}

and I call it using the following:

var valueToFind = ProcessHelper.ReadFromPointer((int)baseAddress + 0x00C45A5C, new []{ 0xEC, 0x1C, 0x178, 0x74, 0x458 });

Now here comes the "random" part, every pointer is added correctly except the last when it has to add 0x458 to pointer 1E138F80, this should return 1E1393D8, but ends up returning "41C00000" enter image description here

I am unsure if it's due to my last pointer no longer being 4 bytes or if a conversion is somehow happening that mixes it up. Any help here would be greatly appreciated!


Solution

  • Your problem is, after you add the last offset you are de-referencing it again as if this address points to the variable you are trying to get the address of. In fact, at this point the address is the address of your variable, not a pointer to it. When the last offset is added, you should stop and print that variable instead.

    I am pretty sure that changing:

    foreach (var offset in offsets)
    

    to

    for (var i = 0; i < offsets.Length; ++i)
    

    and changing

    ptr = ReadPointer(ptr + offset);
    

    to

    ptr = ReadPointer(ptr + offset[i]);
    

    will fix it.

    Print after this for loop concludes and, it should print the correct address.

    If that fails, I have prepared a replacement function for you:

    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;
    }