Skip to lesson
Game Hacking Academy
Preparing lesson text…
Exit reader mode
Voice and speed

Preparing read-aloud controls…

Lesson 2.8 Listening edition

How Pointer Paths Survive Restarts

Trace the player object back to a verified starting point and prove the pointer path across restarts.

About 20 minutes

Section: Start from behavior.

Use offline, 32-bit Wesnoth 1.14.9. Find the current player’s gold again and set a write breakpoint on its four bytes. Instead of recruiting, end a turn so income changes that value.

Wesnoth’s income display

When the breakpoint fires, inspect the instruction that reached the gold field. In the 32-bit Wesnoth 1.14.9 build used by this book, income reaches:

A breakpoint triggered by income

Code example. The surrounding prose explains this example; the full lesson contains the exact code.

Read that line like a sentence: “add the income in e d x to the 32-bit number four bytes after the object in e a x.” e a x points at the current side record, e a x + 4 is its gold field, and e d x contains the income.

These addresses are exact only for Wesnoth 1.14.9 32-bit. If your instruction differs, use your build’s values instead of forcing these numbers onto it.

Section: Trace the object pointer.

Set a breakpoint on the call above the income write. At entry, e a x is zero; after stepping over the call, it holds the side-record pointer. Step into that call on the next turn. The useful path begins with:

Code example. The code’s comments explain: later, follow that pointer and add hexadecimal A 9 0 the gold field is another 4 bytes into the side record

At this value, read e c x. Restart Wesnoth, recreate the same local match, and break there again. In this book’s build, e c x remains this value. The complete path is:

Code example. The surrounding prose explains this example; the full lesson contains the exact code.

Because this value + hexadecimal 6 0 is this value, later labs use the shorter form:

Code example. The surrounding prose explains this example; the full lesson contains the exact code.

Square brackets mean “read the pointer stored here.” A plus sign means “move this many bytes from that address.”

Alternative: Read the path like treasure-map directions: go to the first spot, read the note there, follow it, then take a few steps along.

Section: A pointer path is a route through an object graph.

Each dereference moves from one object to another. The observed root this value is an absolute address for the pinned course build, not an R V A, relative virtual address. Confirm that it still points into the expected module in your run. A portable profile would store the root’s R V A and first discover the module’s current base, as Lesson 2.7 explained. The heap objects reached afterward may move between runs, which is why the path reads their current addresses rather than saving yesterday’s final address.

A path is stable only under stated conditions. It may depend on:

the exact executable build;

a local match being active;

the current player or side object existing;

the same layout and pointer width;

each intermediate page being readable at the moment of use.

Validate every edge, not only the final gold. A non-null pointer can still be stale or point to the wrong object. Check module ranges, page protections, alignment, and a few field invariants before trusting the final value.

In brief: A pointer path is a route through objects. Check every step, not only the final value, and note the conditions it depends on.

Section: Build the chain manually.

In Cheat Engine, add a pointer entry by hand using the module and the offsets you observed.

Adding a pointer path manually

Be careful about order. A displayed list of offsets may be applied from the module outward or shown in reverse depending on the tool. For this exact build, enter base address shown here, first offset hexadecimal A 9 0, and final offset hexadecimal 4. The resolved value should equal the gold shown in the game.

The completed pointer entry

Section: Restart tests.

One successful run proves very little. Test:

close Wesnoth completely;

start it again;

begin a new local match;

confirm the pointer entry resolves;

repeat at least three times.

Also test a state where no match is active. A good tool should report “player object unavailable,” not crash or read address zero.

Section: Write the algorithm before the A P I, application programming interface.

The code follows this plain algorithm:

Code example. The surrounding prose explains this example; the full lesson contains the exact code.

We can model failures precisely:

Code example. The surrounding prose explains this example; the full lesson contains the exact code.

Here is the resolver without any Windows A P I noise. read_u32 can use ReadProcessMemory in an external tool or direct reads inside an injected D L L, dynamic link library:

Code example. The surrounding prose explains this example; the full lesson contains the exact code.

The Result type makes failure data we must handle, not a surprise we hope never happens.

Section: What counts as “stable”.

The path is stable only for the target version and states you tested. The absolute root in this example also depends on the module loading where it did in the verified course run; a relocated module requires base-plus-R V A resolution. Game updates can change layouts and offsets. Document:

game version and architecture;

module name;

offsets in traversal order;

the expected final type;

how many restarts passed;

known states where the chain is unavailable.

Chapter 3 turns this verified path into an external program. First, the final two lessons in this chapter ask a different question: what must be preserved when execution takes a temporary detour through new instructions?