I'm currently memory editing a game called Assault Cube. Unfortunately, because of dynamic memory allocation, the addresses to the values that I want to edit change each time the game starts. Fortunately, there are static pointers that always point to the dynamic addresses. Using cheat engine, I can find the pointers, but they sometimes go up to 8 levels. Instead of doing ********pointer
each time, I would much rather do: *pointer
. On top of that, they have offsets, so it would be a nightmare to hard-code them.
Instead, I am using this function:
int* getLowestPointer(int** highestPointer, int levels, int offsets[])
{
for (int i = 0; i < levels; i++) {
highestPointer = (int**) (*highestPointer + offsets[i]/sizeof(int)); // I am dividing by sizeof(int) here to undo pointer arithmetic (since the offsets are the difference between the offsetted pointer and the base pointer - not in integer increments)
}
return (int*) highestPointer;
}
but it is very messy, and I am casting int* to int** and vice-versa which is considered bad practice. Is there something that I can do which doesn't result in bad practice? I also found this on the web:
DWORD FindDmaAddy(int PointerLevel, DWORD Offsets[], DWORD BaseAddress)
{
DWORD Ptr = *(DWORD*)(BaseAddress);
if(Ptr == 0) return NULL;
for(int i = 0; i < PointerLevel; i ++)
{
if(i == PointerLevel-1)
{
Ptr = (DWORD)(Ptr+Offsets[i]);
if(Ptr == 0) return NULL;
return Ptr;
}
else
{
Ptr = *(DWORD*)(Ptr+Offsets[i]);
if(Ptr == 0) return NULL;
}
}
return Ptr;
}
which I think is even uglier than what I wrote. I don't recommend you read it unless you want migraines.
I'm not sure about "cleanest way", but there's nothing you can do except to dereference those pointers. I suggest using
typedefs
just to make your code more readable.Also don't worry about casting
int *
toint **
. Sure it's considered "bad practice", but if you know what you're doing it might be exactly what is required. You just have to be careful.You can also use some macros to clean up your syntax. This would be a good example of intelligently using a macro to benefit readability and cleanliness, and reduce chance of errors:
Lastly there's a nice macro I use quite often for moving a pointer an amount of bytes in memory: