Domanda

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.

È stato utile?

Soluzione

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 * to int **. 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.

typedef int *** intPtr3;
typedef int ****** intPtr6;

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:

#define DEREF6( PTR ) \
  ******(PTR)

Lastly there's a nice macro I use quite often for moving a pointer an amount of bytes in memory:

#define PTR_ADD( PTR, OFFSET ) \
   (((char *)(PTR)) + (OFFSET))

Altri suggerimenti

Since you posted this we have changed our FindDMAAddy to be cleaner and now it looks like this

uintptr_t FindDMAAddy(HANDLE hProc, uintptr_t ptr, std::vector<unsigned int> offsets)
{
    for (unsigned int i = 0; i < offsets.size(); ++i)
    {
        ReadProcessMemory(hProc, (BYTE*)ptr, &ptr, sizeof(ptr), 0);
        ptr += offsets[i];
    }
    return ptr;
}

Few lines of code, no need for defining the length manually and x64 compatible as long as your build type matches the architecture of the target process.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top