Prep: Speed Hack

Motivation

We really need speed hack to save time, this should the very first step in our journey. If there is no anti-cheat system on the server-side, we should be able to change character's speed by patching game client binary. For our case the game logic is implemented in GameLogic.dll.

GameLogic.dll

In game client's folder, we can find two interesting files GameLogic.dll and GameLogic.pdb at C:\PwnAdventure3\PwnAdventure3\Binaries\Win32.

Dropping GameLogic.dll into IDA, we figure out that this file is indeed what it is called: all the C++ game logic implementations are stored here. What is GameLogic.pdb?

Program database (PDB) is a file format (developed by Microsoft) for storing debugging information about a program (or, commonly, program modules such as a DLL or EXE). PDB files commonly have a .pdb extension. A PDB file is typically created from source files during compilation. It stores a list of all symbols in a module with their addresses and possibly the name of the file and the line on which the symbol was declared. This symbol information is not stored in the module itself, because it takes up a lot of space.

Loading GameLogic.pdb in IDA could give us the actual function names, which helps a lot in reverse engineering. If DLL file and PDB file are in the same folder, IDA is going to detect PDB file automatically:

Speed Hack

"Speed" should be a property of the main character object. Usually the main character is called something like "pawn", "player" or "actor". Here I used a trick: searching for Player:: in the symbols. It returns some interesting properties. Among them we find a Player::GetSprintMultiplier function:

Double click on it to view its content:

Press F5 to decompile it into pseudocode:

Currently the multiplier is 3.0. If we modify it to 30.0, our speed should be 10 times faster. Back to the flow chart and double click on __real@40400000:

Why 0x40400000 stands for float 3.0 in C++? Here is a nice video explaining how floating point numbers work:

Here is an online converter:

I am tempted to change this multiplier to max float. Write a simple C++ program to print out max float:

#include <float.h>
#include <math.h>
#include <stdio.h>

int main()
{
    printf("FLT_MAX = %e\n", FLT_MAX);
    return 0;
}

Use an online compiler such as https://www.onlinegdb.com/online_c++_compiler to run it. The output is:

FLT_MAX = 3.402823e+38

3.402823e+38 converts to 0x7f7ffffd in hex, so we want to patch the binary and change the following bytes:

00 00 40 40 -> FD FF 7F 7F

To change bytes in IDA, select .rdata:10078B34 with mouse and go to "Edit -> Patch code -> Change Byte":

After patching it, we have to "apply" the patch so that it overwrites the old binary. Go to "Edit -> Patch code -> Apply patches to input file":

Don't forget to select the "Create backup" option. Click "OK" and log into the game. Enjoy the speed of light 😄

Last updated