In the previous blogs, I showed you how to use C++ CLI to create a .dll with a simple and easy to edit WindowsForm UI. In this blog, we will be learning how to read from memory using an “Array Of Bytes” as well as write to or change the “Array Of Bytes” to make the game do something we want that can’t normally be done.
Importance of an AOB
What is a byte array? A byte array is simply an area of memory containing a group of contiguous (side by side) bytes. The importance in our case for an “Array Of Bytes” is that even when the application we are messing with updates, although the address in memory may move around, for the most part, the byte array will stay the same meaning we won’t have to make any changes to our code and it will still work.
Example of an AOB in a Debugger
In the previous blogs, we added files such as Scanner.h, Memory.h, and Memory.cpp. Using these files like before, we will be scanning for an address in memory, but instead of searching using the address itself, we will be searching using the AOB of what we are looking for. In this example, I will be using an AOB which determines whether or not something dies when you attack it (as in if it runs out of health from your next attack).
In the screenshot above we can see that the highlighted line shows the address in the memory, the AOB, and the opcode“jng”. For a quick explanation, the opcode “jng” means “Jump if not greater” which is the same as “if a ≤ b”. The line above that says “cmp edx,ebx” which is the same as comparing these two things together, then it goes to the next line; jump to a different part of code if a ≤ b. At the very bottom of the screenshot, we can see the address “0048AC6A”. This address in memory will change when the game updates but thankfully if we search of the AOB itself, it will always find the new address.
Using our Memory and Scanner to Find an AOB
Instead of setting a variable to the value of an address like before, this time we are going to use our ‘FindPattern” function to scan for the entire AOB like so
Inside of FindPatter(), the first part refers to where the memory starts, which we defined as 0x400000 in the previous blogs. The second part is 0xFFFFFF which is where the memory should stop. The next part is the AOB itself “\x0F\x8E\x8E\x00\x00\x00\x53”. The last part is the number of bytes we are scanning for “xxxxxxx” (7).
Now that we have that defined we can add another button to our WindowsForm UI.
Now that we added our new buttons it’s time to add the functionality just like before.
Our “Change AOB” button will write memory and change the AOB from “0F 8E” to “0F 8F”. What this does is change the game's code from “if a ≤ b” to “if a > b”. For us when the game checks if your damage is greater than the enemy's remaining health, it will always instantly kill the enemy.
Checking if the button changes the AOB
Just to make sure that our button is actually doing something to the game’s memory, we are going to press the buttons and see if anything changes.
As we can see, the value is normal. After pressing the “Change AOB” button we see that the value changes.
So now that we know our buttons are doing something to the game’s memory. Let's go test this new feature in an actual game.
Testing our new feature in-game
Now that we have added new buttons and compiled the .dll again. Let’s inject the .dll into the game and attempt to use our new feature. Firstly we are going to start a new game and try to hit the boss without using our “Change AOB” button.
As we can see, the boss still has a lot of health. Now let's go ahead and press our “Change AOB” button to see what happens when we hit the boss one more time.
As we can see, after clicking our “Change AOB” button, the boss lost all of his health after one hit.
In conclusion, during this three-part blog, we’re able to create a simple and easy to edit CLI C++ .dll with WindowsForm for the UI. Our .dll can read from as well as write to memory. Our .dll can also scan or read from memory and write to memory using AOBs instead of addresses.