We are writing a bot for MMORPG with assembler and draenei. Part 4.5

  • Tutorial
Hi% username%! Let's make a short stop to dot all the “ands”, to understand what’s what and how it works. Recently, I got a lot of questions related to offsetting for different versions of World of Warcraft, a lot of suggestions on how to implement the injection of third-party instructions into the gameplay, and now it's time to discuss it all. If you have questions or suggestions, welcome to cut!
Disclaimer: The author is not responsible for your use of the knowledge gained in this article or damage resulting from their use. All information here is presented for educational purposes only. Especially for companies developing MMORPG to help them deal with bots. And, of course, the author of the article is not a bot driver, not a cheater, and he never was.


  1. Part 0 - Finding a code injection point
  2. Part 1 - Implementation and execution of third-party code
  3. Part 2 - Hide the code from prying eyes
  4. Part 3 - Under the Sight of World of Warcraft 5.4.x (Structures)
  5. Part 4 - Under the Sight of World of Warcraft 5.4.x (Moving)
  6. Part 5 - Under the Sight of World of Warcraft 5.4.x (Custom Fireball)

1. Questions and Answers
The most frequently asked question is “why assembler?”. One gets the feeling that people with the word assembler begin a panic attack, lay their ears and turn off the brain. No need to be afraid for so much, he is not so scary. After all, what could be easier than asking the program itself to perform its own function and place the result on a pointer that you know? No need to reinvent the wheel, I use what I have. See how easy it is to call an internal function DoAnythingFunction with her pointer DoAnythingFunctionPointer assembler
"call " + GetAnyGameObjectFunctionPointer,
"push " + argument3Pointer,
"push " + argument2Pointer,
"push " + argument1Pointer,
"push " + argument0Pointer,
"mov ecx, eax",
"call " + DoAnythingFunctionPointer,

GetAnyGameObjectFunctionPointer - returns an object to us, a pointer to it will be placed in eax
argument [N] Pointer - a pointer to the Nth argument for DoAnythingFunction .

Then comes the question about DLL injection. On a battle.net server, this is a potentially dangerous method, as your DLL may go to the security department for research. After all, this is the most common approach in both cheating and bototoring to implement your own DLL. And remember, the popularity of the approach is directly proportional to the probability of getting caught.

The next question is “why not c ++?”. This is a matter of taste. If you can do better and faster in c ++ - do it, but at the moment, apart from unconstructive criticism of the approach, I have not seen anything. Not a single c ++ implementation example. It's strange when everyone can and no one does.

Another interesting question is “why not x64?”. If you raise 4 virtual machines with win7 x86 and run a bot on each, while consuming resources from the host machine, they will be less than win7 x64. Well, in general, it is indifferent to what platform the bot runs on, and to him, too. This question will be relevant when writing cheats when you play it yourself.

The answer to all other questions will be as follows: “Over the past 4 years on the battle.net server, I have never received a ban or warning”

Regarding errors in the code and posts. Yes, I have typos and errors, as with all of you, and if you notice them, you should not wave them like a flag on the red square in a parade, just write me a personal message and I will fix it. This will demonstrate not only your attentiveness and knowledge, but also courtesy and good breeding. It is as if during a meal a person has a sauce on the beard or the food itself. Do you think this is right at the table to discuss how much conceptually it hung?

2. Offset search
For offset searches, I prefer mask searches. Naturally, the best way to find a pointer to a function is debugging, and only it will give a 100% guarantee that you have found exactly what you need. But this process can be very tiring and long, and how for beginners in 5 articles to explain about debugging, breakpoints and a disassembler, when almost nothing is clear, as I noticed. Therefore, I use mask search in the article. Let's look at an example. To get started, download 2 different Wow.exe files, one major version (I took 5.4.7 17898 and the WowCircle-32.exe client 5.4.7 18019). Our task is to find offset for Morfer, while offset for 17898 is known to us:
CGUnit_C__UpdateDisplayInfo = 0x42E3A8,
CGUnit_C__OnMountDisplayChanged = 0x42E193,
CGUnit_C__UpdateScale = 0x424AE3,

Open Wow.17898.exe in the IDA, wait until it loads, scroll to the very top, look at Imagebase = 400000 and remember this value.

Then press G and go to the address CGUnit_C__UpdateDisplayInfo + Imagebase = 0x82E3A8

Open it in Hex-View by pressing Alt + 3, copy the first 15 bytes - these are the first 8 instructions in the function that will not change during compilation, i.e. avoid commands like jxx xxxx, push offset xxxx, call xxxx, xxx dword_xxxx, etc.

After all, we start a new IDA instance already for the file under investigation, press Alt + B, enter the copied sequence of bytes and look for Ctrl + B, if something is found, then we need to compare it with the original.

As you can see, these functions are identical, with the exception of pointers to them. For accuracy, press Ctrl + B again and if nothing comes out, then the offset is found. Everything can be much more complicated when the first 15-20 bytes in a function change during compilation. In this case, you can look in it for a static piece that does not contain marks and transitions, or you will have to replace some bytes with questions in the search template. Here is an excerpt from the IDA search help:
CD 21 - bytes 0xCD, 0x21
21CD - bytes 0xCD, 0x21 (the order depends on the endiannes)
“Hello”, 0 - the null terminated string “Hello”
L “Hello” - 'H', 0, 'e', ​​0 , 'l', 0, 'l', 0, 'o', 0
B8 ???? 90 - byte 0xB8, 4 bytes with any value, byte 0x90

For example, to search for CGUnit_C__UpdateScale, I will take not the first 15 bytes, but from the 21st to the 35th, because there are no unwanted instructions. You can also use the MakeSig IDA plugin for these purposes.

PS If anyone has the strength and desire to write an article on how to look for function addresses by debugging, I would be grateful
PPS Errors and typos in a personal message

Also popular now: