Pointer Search | ![]() |
![]() |
Pointers are what games use to keep track of the locations of chunks of memory that have been dynamically allocated. If you need a detailed explanation on what pointers are and how to work around them, see About Pointers. Pointer Searches allow you to find pointers to dynamic game objects, or objects that move in memory. This is often called dynamic memory allocation, or DMA. For the remainder of this page, for the sake of explanation, we will assume we are hacking a 3-D first-person shooter game that stores its lists of players dynamically. Typically in this type of a game, a person will have found his or her character’s health as an int from 0 to 100, but the person will notice that when he or she dies, the address for the health is no longer valid; the player’s health has moved to a new location and must be located again. What has actually happened is that the chunk of RAM that contained the player’s character data was deallocated by the game and then reallocated when the player respawned. It has not just moved the health, but the ammo, position, energy, and everything else related to the character. There is, however, one thing that did not move. No matter how complicated a game is, it still needs a way to find the data for each character, no matter when or where the data moves. All games, without exception (as guaranteed by the x86 architecture), have static (non-moving) data. Static pointers (pointers that do not move) are there specifically to tell the game where these sets of moving data are going when they move. Be careful to note that static data is often defined as data that does not move, however on the Windows® platform there is no such thing as data that does not move. All static data is stored in relation to the module that contains it, and Windows® guarantees that all modules in a process can be loaded to another address if system memory is running low. For simplification, we will assume the game is always loaded at 0x00400000. Properties of PointersPointers have several properties that allow us to locate them. The most important property is that they always point to the base of any given data set (called a structure). Consider the following example. The red rectangles outline a player structure containing our health, ammo, and some other values we don’t understand. The actual addresses of these values is irrelevant at this point; they are always referenced as an offset from the structure base, however we don’t yet know where the base is. We do, however, know that the game has a pointer to this structure somewhere, and that pointer will point to the base of it. We also know that structures are never large. That means if we have a value inside a structure (health and ammo here), then the base of the structure is never far away. In the picture above, the first value in the structure that we understand is the health. This means the base of the structure is before the address of the health, but not far before the address of the health. It is usually safe to assume that no structure in your game will be larger than 0x10000 bytes. That means if we have the health of our player, the base of the structure will never be lower than [Address of Health] - 0x10000.
Using What We KnowNow we have enough information to perform a Pointer Search. The full search options are explained below, but for now we will only discuss the options used in this example. Let’s assume the address of Health in the picture above is 0x02BE2C04. Given what we know about structures, the base of the structure must then be between 0x02BD2C04 and 0x02BE2C04. For the sake of simplicity, let’s round 0x02BD2C04 down to 0x02BD0000. In the Pointer Search dialog, we would select Range in the Search Type, then enter 2BD0000 and 2BE2C04 into the Points Between and And edit boxes. This means we are searching for all pointers that point to locations between 2BD0000 and 2BE2C04, inclusively. The base of our structure is around there somewhere and there is a pointer somewhere that points to it. We only want to find pointers that won’t move, so we select Only Find Static Pointers. The search will automatically save the offset from 2BE2C04. This will be explained later. After performing the search, we may get several returns. As stated before, the structures are usually small, so the base of our structure should be near Health. Using the Found Addresses dialog (Search/View Results), we will see a column entitled Distance from 02BE2C04. This is how we can tell how far away pointers are from our Health (address 0x02BE2C04). Negative numbers indicate that the pointer is pointing to a location lower than 2BE2C04. A distance of 0 indicates that the pointer is pointing directly at 2BE2C04. Positive numbers should never be in the list, because pointers to our structure will never point higher than the address of Health (2BE2C04). The dockable Found Addresses list shows this offset. For our example, we will assume there is a pointer at address 0x0045EFC0 whose distance is -0xC from 2BE2C04 (our Health). This happens to be very close, though the average distance can be around -0x200 to -0x500, and in some cases farther. If you find a pointer that has a distance between -0x500 and 0x0, there is a very high chance it is the correct pointer to your structure. Double-click the pointer in the Found Addresses list to add it to the main list. This is the result: The base of our player structure can always be found by following the pointer at address 0x0045EFC0. If we add 0xC to that location, we have our player health. If we add 0x1C to the base address, we have our player ammo.
The Options at Our DisposalThe following chart explains each option in the Pointer Search dialog.
Additional NotesAll fields must be entered in hexadecimal form. The Points To field must follow the rules of a valid pointer, which means it must be divisible by 4 and must be a readable address in the target process. Range searches always go from the lower number to the higher number, regardless of the order in which you enter them. The search itself always starts at the lower address and goes to the higher address, regardless of the order in which they are entered. All search data entered into the dialog is saved if you click OK and perform a search, which allows you to repeat searches without having to fill out every box again. Only if you perform a search will the previous results be lost.
Tips
|
Copyright © 2006 Shawn (L. Spiro) Wilcoxen |