Tutorial Multilevel Pointers Explained (using AssaultCUBE)

Hexui Undetected CSGO Cheats Sinkicheat PUBG Cheat


Dank Tier VIP
Jul 15, 2018
Original Post Date: January 4, 2019

Multilevel Pointers Explained:

Something that comes as no surprise to me is just how much trouble new programmers have with pointers. Pointers are easy! I wrote a whole tutorial on pointers for that specific reason. However something that trips people up is Multi-level pointers, basically a pointer that points to another pointer.


For this tutorial we’ll be using our old workhorse AssaultCube. To save the trouble of opening Cheat Engine the pointer path is as follows:


ac_client.exe + 10F4F4

I’ve already modified the ammo amount in the picture to make it easier to find. The stumbling block is here: how do we convert this into code? If you code is being executed from inside the process it’s really straight forward, but what if you’re external from the game?

Simply put you need to resolve the pointers yourself. De-referencing is not possible with external code you’ll need to resolve the pointers yourself. First we grab a valid handle to the game process:

    HWND hWnd = FindWindowEx(HWND_DESKTOP, NULL, NULL, "AssaultCube");
    if (!hWnd)
        return -1;

    DWORD dwProcId = 0;
    GetWindowThreadProcessId(hWnd, &dwProcId);

    if (dwProcId <= 0)
        return -1;

    printf("AssaultCube: %d\n", dwProcId);

    HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcId);
    if (!hProc)
        return -1;
Then we need to get the base address of the module:

uintptr_t GetModuleBaseAddress(DWORD procId, const TCHAR* modName)
    uintptr_t modBaseAddr = 0;
    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, procId);
    if (hSnap != INVALID_HANDLE_VALUE)
        MODULEENTRY32 modEntry;
        modEntry.dwSize = sizeof(modEntry);
        if (Module32First(hSnap, &modEntry))
                if (!lstrcmpi(modEntry.szModule, modName))
                    modBaseAddr = (uintptr_t)modEntry.modBaseAddr;
            } while (Module32Next(hSnap, &modEntry));
    return modBaseAddr;
Then in our own code we can resolve the address of the Base pointer we want:

uintptr_t dwBaseOffset = GetModuleBaseAddress(dwProcId, "ac_client.exe") + 0x10f4f4;
Now we can start resolving our pointer chain until we reach our desired variable:

uintptr_t dwOffsets[] = { 0x374, 0x14, 0x0 };

printf("Base Address + Offset: 0x%x\n", dwBaseOffset);

uintptr_t dwNext, dwVal = 0;
SIZE_T dwOut = 0;
// Read our base pointer
ReadProcessMemory(hProc, (LPCVOID)dwBaseOffset, &dwVal, sizeof(uintptr_t), &dwOut);
printf("Base Ptr->%x\n", dwVal);

// Process our offsets in a loop reading and resolving to the next one
for (int i = 0; dwOffsets[i]; i++) {
    dwNext = dwVal + dwOffsets[i];

    ReadProcessMemory(hProc, (LPCVOID)dwNext, &dwVal, sizeof(uintptr_t), &dwOut);
    printf("Next Ptr->%x\n", dwVal);

// Once the chain is resolved we can grab our ammo value
int ammo = 0;
ReadProcessMemory(hProc, (LPCVOID)dwVal, &ammo, sizeof(int), &dwOut);

printf("Current ammo: %d\n", ammo);
And if everything worked we should have successfully resolved our ammo value:
  • Like
Reactions: Elitiok and Rake
Attention! Before you post:

Read the How to Ask Questions Guide
99% of questions are answered in the Beginner's Guide, do it before asking a question.

No Hack Requests. Post in the correct section.  Search the forum first. Read the rules.

How to make a good post:

  • Fill out the form correctly
  • Tell us the game name & coding language
  • Post everything we need to know to help you
  • Ask specific questions, be descriptive
  • Post errors, line numbers & screenshots
  • Post code snippets using code tags
  • If it's a large project, zip it up and attach it

If you do not comply, your post may be deleted.  We want to help, please make a good post and we will do our best to help you.

Community Mods