Dynamic allocation of memory in computer games

29 March 2024 6 minutes Author: Lady Liberty

Today we will talk about dynamic memory allocation (DMA) in the context of game hacking. Explains how in the game “Wesnoth” the memory address of the player’s gold changes every time the game is restarted via DMA, making it difficult to create reusable hacks. The authors discuss how “random” addresses can be turned into consistent ones to facilitate the development of exploitable hacks.

Review

Previously, we changed the player’s gold in Vesnot. Every time we restarted the game, we had to repeat the process of finding the player’s golden memory address because it was different every time. This is through dynamic memory allocation or DMA. In order to write hacks that can be reused and distributed, we need to somehow convert these “random” addresses into consistent addresses. There are many methods to accomplish this task, but first we need to discuss how DMA works and why it exists.

Background

Games are large applications with many resources. There’s no way to fit all game data into RAM at once, so it has to be loaded when needed. For example, the game will not load an enemy model or image until the player encounters them. This process is known as dynamic resource loading.

These dynamically loaded resources must be placed in a specific area of memory so that the game can access them again. The game is responsible for creating and destroying these memory partitions. Creation is known as distribution and destruction is known as removal. So dynamic memory allocation is the process of creating memory partitions to store resources when the game needs them. The game can only request memory from the OS and has no control over where that memory is located.

Let’s take a look at player gold in Wesnoth and how it is created. When Wesnot starts, the player profile is loaded into the game’s player class. The player can then choose from a variety of game modes and other options in the main menu. If the player then starts the game, several items are allocated and placed in the player’s class, such as the player’s race, their available units, and their gold. When the player exits the game, these values are destroyed. This is why a player’s gold address is always different.

Programming

In order to program the hacks, we need some way to consistently find the golden address without searching the Cheat Engine. There are several ways to do this:

  • Use an automatic scanner such as Cheat Engine

  • Cave code

  • Reverse

These methods can be used to find any dynamic address. We’ll briefly discuss each of these in this lesson, but we’ll use all of the techniques in future lessons.

When using Cheat Engine or reverse, our goal will be to find something known as a base pointer. In general, a base pointer represents a memory address that is always consistent and can be used to shift to values of interest. This method works because there are some addresses that need to be constant in order for the game to find them. For example, in Wesnoth, the game needs to know where the Player class is. If we find the Player class, we can use it as a base pointer to shift to our golden address.

Cheat Engine

One of the features of Cheat Engine is the ability to scan the pointer. This can be done by searching for an address (such as a player’s gold) and then right-clicking on it to bring up a context menu. This context menu contains all pointer scanning functions.

This function returns all memory locations currently referenced by the selected address. These addresses can then be saved to a scan file. After that, you can restart the game and find the address again. After comparing new memory locations with the scan file, you can narrow down to only matching locations, similar to a normal memory search. Eventually, we will only have pointers that always point to the address we have chosen.

Code Cave

Another way to defeat DMA is to use a code cave. This approach finds the location where the desired value is accessed. In our Wesnoth example, this could be anywhere the gold changes. Immediately after this location, the code redirects to our code cave. In our code cave, we can store the current value in a piece of memory that we control. Our hack can then access this memory sequentially.

For example, the code in Wesnoth that is responsible for reducing our gold when hiring a unit looks like this:

sub dword ptr ds:[edx+4], ecx

When this instruction is executed, edx + 4 contains a reference to the golden memory address, and ecx contains a reference to the cost of the unit just fetched. By redirecting the code immediately following this address to the cave, we can store the value of the address in the cave. Below is an example of a cave where this can be done:

pushad
mov dword ptr ds:[0x12345678], edx+4
popad
...original instruction replaced...
jmp 0xredirect_location

By doing this, our hack will be able to reference 0x12345678 to get the current value of the golden address.

Reverse

A final method to deal with DMA is to change the target. This method uses a combination of the two previous methods and is the most versatile. In this approach, we first find the instruction that changes the value we are interested in, such as the subinstruction in the previous section. We then parse the function before that instruction and determine where the register of interest (in this case, edx) is assigned. Often this will be assigned the value of another offset register, such as eax+60.

We then repeat this process to find where the previous register is assigned. Later we will find the base value or pointer that is used to assign all these values. This base pointer can then be combined with all the offsets we’ve changed to get the address we’re interested in.

Other related articles
Found an error?
If you find an error, take a screenshot and send it to the bot.