Utilizing the memflow memory introspection library to spy on BattlEye

Utilizing memory introspection on a qemu virtual machine to read the packets BattlEye is sending to the game server

A few years back, emulating anti-cheat was a popular bypass method. While 'emulating an anti-cheat' can take on different forms, commonly it means running the game with the anti-cheat entirely disabled and replicating the communication between the anti-cheat and the game server. But to do this, first you need to reverse engineer what the client and server are actually sending to each other, which is not an easy task.

We will be utilizing memflow, a virtual machine memory introspection library. Think of this as a form of virtual DMA. The first step here is to set up an undetected virtual machine environment to run your games in, preferably with GPU passthrough so you can maintain good performance in graphically demanding games.

Of course, these packets aren't just stored in memory somewhere. To gather them we will have to hook BattlEye's SendPacket function, thankfully ARK: Survival Evolved ships with a PDB, so finding the function in IDA is easy.

At this point you might have a few questions…

  1. BattlEye has plenty of detections for function hooks, how do we hook a function undetected?

  2. We are external through a form of DMA, how can we hook a function?

It turns out that, at least on the archaic version of BattlEye that ARK ships with, if a jmp inside a function leads to signed memory, BattlEye completely ignores it. This goes hand in hand with how we will be hooking a function externally. Using a series of code caves in .text, we can write enough shellcode into the program to move the packets out of the register, and read them from outside the virtual machine using memflow. This is quite a tedious process, and our shellcode is split up between many code caves that all chain together.

For my POC, I decided to write most of the assembly by hand, and turn it into opcodes using hexdump. After many hours of tedious work and debugging using BottlEye to simulate BattlEye's functionality, we have a working POC. The video below shows the fake packets BottlEye is sending, as I dont want to get into legal trouble, but the POC works as intended when BattlEye is running normally, and the account never got banned.

Theoretically, this data could be used to emulate BattlEye, but it seems they have more in-depth checks now that I didn't feel like figuring out, still, this project taught me a lot about assembly, and how anti-cheat software works.