Cheat Engine - Memory Scan
Cheat Engine is an amazing tool to find the address of values in the game's memory. Reading a process's memory isn't difficult (we have done this on Linux all the time), but the engineering effort to make it easy and fast is non trivial.
As a first step I would like to search for the selected skill. So here you can see an initial scan for an unchanged value, which finds millions of possible addresses. This makes sense because code and resources in memory are all unchanged.
So to continue with the process, we want to change the selected skill and use a combination of changed and unchanged values to filter out possible addresses.
Eventually we are left with a single address that shows the selected skill. In this case we have skill 3 selected and see the value 2, which means the selected skill is stored as an array index. It starts at 0.
Kickstart Reverse Engineering
When reverse engineering a huge software like a game, it can be hard to decide where to start. But Cheat Engine can help us identify interesting functions with tools like "what writes this address". This will attach a debugger to the game and log every change of this selected skill value.
Here you can see an example logged entry. It is a move instruction that writes the skill ID currently stored in edx. And it writes it to esi+0x180. When we imagine this function to be called SetSelectedSkill, the offset 0x180 could be an indication for something like a player class which has the selected skill ID as a a member variable. In this case esi could be the pointer to this player class in memory.
The following screenshot shows the memory pointed to by esi. The green value is the selected skill ID. The red value is colored red because it keeps changing - it looks like a timer. And we can also see a few strings like our name LiveOverflow, the team name PwnSquad and our location LostCave. So it could make sense that this is a player class.
From Cheat Engine to Ghidra
With this knowledge we could try to kickstart reverse engineering with a disassembler/decompiler like Ghidra. To find the code we found with Cheat Engine in Ghidra, we need to account for ASLR. On the left you can see the Memory Regions of the running process and where the GameLogic.dll is loaded, and on the right you can see where Ghidra loaded it. So with a bit of math you can figure out where 0x618f3e93 is in Ghidra.
Or you could use the rebase feature (house symbol) to adjust Ghidra's addresses to match the current process memory map.
Now we can simply goto the address that we found with Cheat Engine. Here is the assembly line that changes the selected skill ID, and we can see the decompilation of it. This means we can assume that bVar1 is the itemSlot number.
And if we assume esi is a Player object, then iVar2 would be a Player object which has the selected skill ID at offset 0x180. Ghidra has a neat feature to help us reverse engineer these classes, by auto-generating a struct. Based on those offsets Ghidra assumes that those are member variables. The picture below shows how Ghidra then changes the display of it. So we can rename field_0x180 to something like itemSlot.