Reverse Engineering the Anticheat on a Private MMO Server - cristianrz's websiteI play on a private Aion server. For those unfamiliar, Aion is an MMO from 2009 that NCSoft has largely abandoned in the West, but a community of private servers keeps it alive. The server I play on uses a third-party anticheat called Active Anticheat, a commercial product sold to private server operators by a developer in Warsaw.<br>I got curious about what it actually does to my machine. A few evenings with Wireshark, Procmon, Ghidra, and pefile later, here’s what I found.<br>Starting from almost nothing<br>My starting point was watching Task Manager while the game launched. A service called PRProt appeared briefly, then disappeared. A kernel driver landed in a temp folder and was gone after reboot. A DLL got injected into the game process. That was enough to go on.<br>The first useful thing was just running strings on the binaries. Most of the AC components are protected with Themida Code Virtualization — the kernel driver’s primary code section is 10.1 MB with entropy 7.62, completely opaque to static analysis. But import tables survive Themida. From those alone you can see what kernel APIs the driver registers: process creation callbacks, thread creation callbacks, image load callbacks, registry monitoring, physical memory access, and KeBugCheckEx. Standard kernel anticheat territory, but it tells you what the driver is capable of even when you can’t read a single line of its logic.<br>One string caught my attention: a reference to iqvw64e.sys — the Intel Network Adapter Diagnostic Driver, a known vulnerable signed driver that’s been abused in BYOVD attacks to kill anticheat and EDR processes from kernel level. The reference is likely a defensive check — detecting whether someone has loaded it — but its presence indicates the AC is aware of this attack vector.<br>The injected DLL (clmods64.dll) is also Themida-packed. I spent time on it statically and got nowhere useful. Dynamically it’s more interesting — it connects to the kernel driver via a named event (AAErrorPortEvent) and the game process verifies its integrity after injection before proceeding. What it actually does inside the game process remains opaque; it’s the black box at the center of the whole system.<br>The injection chain<br>The DLL doesn’t inject itself. The sequence is:<br>ActiveLauncher.exe writes clmods64.dll, the service binary, and the kernel driver to %LOCALAPPDATA%\Temp\ActiveAnticheat\[serverid]\<br>The kernel driver is registered as a service and started via services.exe, then immediately marked for deletion — it exists in the service registry only long enough to load<br>The game binary (aion.bin) sideloads version.dll from its own directory — more on this below<br>version.dll launches ij64.exe, a small injector that uses CreateRemoteThread → LoadLibrary to load clmods64.dll into the game process<br>The temp folder where all this happens is writable by the current user without elevation. aaerrport.exe (the AC service, running as SYSTEM) searches its own directory for DLLs before falling back to System32 — specifically Wtsapi32.dll and SspiCli.dll. A user-level process could drop a malicious DLL there in the window between when ActiveLauncher.exe creates the folder and when the service starts. Since the service runs as SYSTEM, the planted DLL would execute at SYSTEM privilege. The fix is straightforward: restrict the temp folder to admin-write-only since ActiveLauncher.exe itself runs elevated.<br>Network traffic<br>Capturing traffic while the game launched was more productive than static analysis. Three connections stood out: port 11000 to the AC server, port 2106 for game login, and the game world on a separate host.<br>Port 11000 is the interesting one. The handshake is RSA-1024 challenge-response — below current recommended minimums but functional. After authentication, the server pushes a blob down to the client that I initially couldn’t identify. I could see file path strings in it: localization XMLs, pak files, game binaries. It took a while to realize what I was looking at: a file integrity manifest. The server is telling the client which files to check and what their expected MD5 hashes are.<br>I confirmed this by finding the same data cached locally in the registry under a key called fastcheck — 17KB of binary data. The format is simple: 4-byte entry count, then repeated [1-byte path length + ASCII path + 16-byte MD5]. Parsing it gave me 331 files. The server controls the list entirely; the client has no say.<br>Parsing the manifest surfaced some oddities. Three files are expected to be zero bytes. All seven language ui_game_override.xml files share the same hash — identical files across language folders. The 32-bit and 64-bit dbghelp.dll share a hash, meaning a 32-bit binary was deployed to the 64-bit folder. And bin32\iovation.bin is in there — iovation is a commercial device fingerprinting service, not NCSoft code, whose presence and data...