Anticheat Update Tracking

2025-06-2921:0612467not-matthias.github.io

A few years ago when I was into reverse engineering and binary analysis (and game modding), I did a lot of research into anticheats work. I was curious about tracking their updates, since that would…

A few years ago when I was into reverse engineering and binary analysis (and game modding), I did a lot of research into anticheats work. I was curious about tracking their updates, since that would allow me to:

  • Know when a new version is released
  • Understand what changes were made
  • Use older versions for research purposes

So I ended up researching different ways on how to track updates of various anticheats. Some of them are already very well documented, while others haven't been explored much. This post will summarize my findings and outline how they work.

EasyAntiCheat

EasyAntiCheat is widely recognized as one of the most advanced anticheats, and is used in many popular games like Rust, Fortnite, Apex Legends, and more.

Prior to the acquisition by Epic Games, EAC was using their own CDN to distribute updates: https://download.eac-cdn.com/api/v1/games/{game_id}/client/{system}/download/?uuid=1239688.

  • game_id: unique identifier for each game (e.g. 154 for Apex Legends)
  • system: target platform/system (e.g. wow64_win64, mac64, linux32_64).

After the acquisition, they switched to the EpicGames CDN, which has a slightly different URL structure: https://modules-cdn.eac-prod.on.epicgames.com/modules/{product_id}/{deployment_id}/{system}. The parameters to this URL are completely different:

  • product_id: unique identifier for each game (e.g. 429c2212ad284866aee071454c2125b5 for Rust)
  • deployment_id: unique identifier for each deployment (e.g. 76796531e86443548754600511f42e9e for Rust). This doesn't change when an update is released and is used to identify different game versions.
  • system: same as in the old CDN

After downloading the module for a game, we'll have a file which contains data with a very high entropy which is the first indication that it is encrypted or compressed:

$ bat encrypted.bin | ent
Entropy = 7.989390 bits per byte.

Looking at the data, we also can't really identify any patterns or strings. However, across versions the header seems to always stay the same (a7 ed): Very interesting πŸ€”

$ hexyl encrypted.bin | head
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚00000000β”‚ a7 ed 96 0c 0f 0f 12 19 β”Š 1c 1b 1e 20 22 26 2a e5 β”‚Γ—Γ—Γ—_β€’β€’β€’β€’β”Šβ€’β€’β€’ "&*Γ—β”‚
β”‚00000010β”‚ e8 33 36 39 3c 3f 42 85 β”Š 88 4b 4e 51 54 57 5a 5d β”‚Γ—369<?BΓ—β”ŠΓ—KNQTWZ]β”‚
β”‚00000020β”‚ 60 63 66 69 6c 6f 72 75 β”Š 78 7b 7e 81 84 87 8a 8d β”‚`cfiloruβ”Šx{~Γ—Γ—Γ—Γ—Γ—β”‚
β”‚00000030β”‚ 90 93 96 99 9c 9f a2 a5 β”Š a8 ab ae 31 34 b7 ba cb β”‚Γ—Γ—Γ—Γ—Γ—Γ—Γ—Γ—β”ŠΓ—Γ—Γ—14Γ—Γ—Γ—β”‚
β”‚00000040β”‚ ed 9c 8e d7 80 8c a8 c3 β”Š b1 94 2b fa d2 5c a6 be β”‚Γ—Γ—Γ—Γ—Γ—Γ—Γ—Γ—β”ŠΓ—Γ—+Γ—Γ—\Γ—Γ—β”‚
β”‚00000050β”‚ cc 86 86 db dd d5 db d8 β”Š d6 98 91 d5 e3 f3 f7 00 β”‚Γ—Γ—Γ—Γ—Γ—Γ—Γ—Γ—β”ŠΓ—Γ—Γ—Γ—Γ—Γ—Γ—β‹„β”‚
β”‚00000060β”‚ b4 a5 ed ae be 16 15 c3 β”Š c1 12 cc a5 d7 e9 bd da β”‚Γ—Γ—Γ—Γ—Γ—β€’β€’Γ—β”ŠΓ—β€’Γ—Γ—Γ—Γ—Γ—Γ—β”‚
β”‚00000070β”‚ 2c 26 1f ec 97 79 79 93 β”Š 8c 6b 6e 71 74 77 7a cd β”‚,&β€’Γ—Γ—yyΓ—β”ŠΓ—knqtwzΓ—β”‚
β”‚00000080β”‚ 15 c8 86 d5 d9 93 95 c9 β”Š 4d 6e 58 09 a4 a7 aa ad β”‚β€’Γ—Γ—Γ—Γ—Γ—Γ—Γ—β”ŠMnX_Γ—Γ—Γ—Γ—β”‚

A few years ago, I spent a night early morning with a friend to find the decryption algorithm. We searched for anything that closely resembled such an algorithm, eventually found it, made a quick POC and got it working πŸ”₯. Here's what the code looks like:

void 

After decrypting the binary blob, we'll finally have a PE image (EasyAnticheat.packed.dll):

$ hexyl EasyAnticheat.packed.dll | head
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚00000000β”‚ 4d 5a 90 00 03 00 00 00 β”Š 04 00 00 00 ff ff 00 00 β”‚MZΓ—.β€’...β”Šβ€’...Γ—Γ—..β”‚
β”‚00000010β”‚ b8 00 00 00 00 00 00 00 β”Š 40 00 00 00 00 00 00 00 β”‚Γ—.......β”Š@.......β”‚
β”‚00000020β”‚ 00 00 00 00 00 00 00 00 β”Š 00 00 00 00 00 00 00 00 β”‚........β”Š........β”‚
β”‚00000030β”‚ 00 00 00 00 00 00 00 00 β”Š 00 00 00 00 80 00 00 00 β”‚........β”Š....Γ—...β”‚
β”‚00000040β”‚ 0e 1f ba 0e 00 b4 09 cd β”Š 21 b8 01 4c cd 21 54 68 β”‚β€’β€’Γ—β€’.Γ—_Γ—β”Š!Γ—β€’LΓ—!Thβ”‚
β”‚00000050β”‚ 69 73 20 70 72 6f 67 72 β”Š 61 6d 20 63 61 6e 6e 6f β”‚is progrβ”Šam cannoβ”‚
β”‚00000060β”‚ 74 20 62 65 20 72 75 6e β”Š 20 69 6e 20 44 4f 53 20 β”‚t be runβ”Š in DOS β”‚
β”‚00000070β”‚ 6d 6f 64 65 2e 0d 0d 0a β”Š 24 00 00 00 00 00 00 00 β”‚mode.___β”Š$.......β”‚
β”‚00000080β”‚ 50 45 00 00 4c 01 03 00 β”Š 34 81 52 68 00 00 00 00 β”‚PE..Lβ€’β€’.β”Š4Γ—Rh....β”‚

Unfortunately, we're not yet done. According to Detect it Easy, the binary is protected with VMProtect, which means we can't just read the .text or .data section. However, to further analyze the binary and extract the driver and usermode module we'll have to find a way to unpack it.

use PeView; use PathBuf;

After analyzing this unpacked library, you'll eventually figure out that the .data section has a high entropy and is quite large. You might even recognize the encrypted PE headers from earlier: a7 ed. This is exactly where the driver and their internal module are stored.

The embedded files use the same encryption algorithm, so we can search for the encrypted PE header (MZ or 0x4D5A). After looking at the data in IDA, I managed to find a pattern which we can use to extract the embedded files. The encrypted modules are always stored in the following order:

<encrypted_module> (encrypted data)
<size> (padded to 16 bytes)

This is somewhat equivalent to the following structure, where len always contains the size of the buffer:


By knowing that the encrypted module has a high entropy, which means that it's very unlikely that there will be patterns in the data, we can simply search for at least 8 bytes of zero padding which is always present after the size.

let section = pe.section_by_name;
let = section.find_padding_at;
let encrypted_driver = section;
let driver_module = decrypt;
assert_eq!;

let = section.find_padding_at;
let encrypted_internal = section;
let internal_module = decrypt;
assert_eq!;

Battleye

Battleye, another popular anticheat from Germany, is known for its bandaid fixes and lack of security. They put a lot of focus on detecting popular cheat providers, by detecting them via static signatures. It is used in games like Arma, DayZ, Escape from Tarkov, and most recently Grand Theft Auto V.

Their CDN seems to be built in-house and follows a very simple structure:

  1. Fetch the latest version (which is just a unix timestamp like 1746714230)
  2. Download the module using the version number from the actual CDN

Here are the required URLs:

  • Version URL: https://cdn.battleye.com/{game}/ver
  • Download URL: https://cdn.battleye.com/{game}/{version}
  • Possible values for the games include: eft, unturned, ark, r6s/win-x64, dayz/win-x64.

The downloaded binary contains other bytes before the actual module, which have to be filtered out. The easiest way to do it is to search for the PE header and delete everything before. In this case, the PE module is located at offset 0x200:

$ binwalk 1732793154
---------------------------------------------------------------------------------
DECIMAL HEXADECIMAL DESCRIPTION
---------------------------------------------------------------------------------
512 0x200 Windows PE binary, machine type: Intel x86-64
---------------------------------------------------------------------------------

The downloaded file is BEService.exe, which also embeds their kernel driver which is extracted when the service is started. You can use the same techniques as with EAC to extract it, so I won't go into further details.

While writing this blog post, I realized that some old download URLs of mine still worked. So it seems like the CDN is keeping not only the latest but also previous builds. Since the epoch timestamp only counts the seconds since 1970, it should only take a few days to enumerate all possible IDs. I've thrown together a quick POC, and unfortunately it seems like they are deleted old version :(

Electronic Arts Anti-Cheat (EA-AC)

EA-AC (not to confuse with EAC) is a relatively new anticheat that was launched in 2022. It is used in games like FIFA or Battlefield, which all use the same installer. The direct download link to their installer can be found on the help.ea.com page which links to the following URL: https://cdn.eaanticheat.ac.ea.com/EAAntiCheat.Installer.exe.

Instead of having to run the installer, we can simply usage 7z to extract the contents. However, they are not shipping the driver with the installer anymore, so you need to dump it while running the game or reverse engineer the download.

$ 7z l EAAntiCheat.Installer.exe
 Date Time Attr Size Compressed Name
------------------- ----- ------------ ------------ ------------------------
2025-06-14 08:03:50 ..... 44388600 26865015 ProgramFiles/EAAntiCheat.GameService.dll
2025-06-14 08:03:36 ..... 116300024 108845059 ProgramFiles/EAAntiCheat.GameService.exe
2025-06-14 08:04:12 ..... 26872 14232 ProgramFiles/preloader_s.dll
2025-06-14 08:03:50 ..... 37148408 20349480 Title/EAAntiCheat.GameServiceLauncher.dll
2025-06-14 08:03:50 ..... 15922936 13955947 Title/EAAntiCheat.GameServiceLauncher.exe
2025-06-14 08:04:12 ..... 27384 14245 Title/preloader_l.dll
------------------- ----- ------------ ------------ ------------------------
2025-06-14 08:04:12 213814224 170043978 6 files

Vanguard

Vanguard is the anticheat used in Valorant and League of Legends, developed by Riot Games.

Despite their advanced security features, is is relatively easy to track the updates. They provide a public API to fetch the latest config which includes the version and URL for the anticheats modules:

{
 "anticheat.vanguard.backgroundInstall": false,
 "anticheat.vanguard.enabled": true,
 "anticheat.vanguard.enforceExactVersionMatching": false,
 "anticheat.vanguard.steppingStones": [
 "1.16.15.9"
 ],
 "anticheat.vanguard.url": "https://riot-client.secure.dyn.riotcdn.net/channels/public/rccontent/vanguard/{version}/setup.exe",
 "anticheat.vanguard.version": "1.17.6.2",
 ...
}

After downloading the files from the CDN and extracting them (again either via 7z or by running the installer), we'll have the following files. This already includes the driver and usermode components, so we don't even have to extract anything.

$ 7z l setup.exe
Date Time Attr Size Compressed Name
------------------- ----- ------------ ------------ ------------------------
2025-05-05 20:43:53 ....A 21651 6298 vgc.ico
2025-05-05 20:54:45 ....A 4494048 55866276 installer.exe
2025-05-05 20:57:34 ....A 4285400 log-uploader.exe
2025-05-05 20:55:20 ....A 40075376 vgc.exe
2025-05-05 14:18:24 ..... 26955888 vgk.sys
2025-05-05 20:55:53 ....A 10524776 vgm.exe
2025-05-05 20:56:48 ....A 3239456 vgrl.dll
2025-05-05 20:57:10 ....A 4143376 vgtray.exe
------------------- ----- ------------ ------------ ------------------------
2025-05-05 20:57:34 93739971 55872574 8 files

Conclusion

It's surprising to see the differences in CDNs for different anticheats. You might think, why don't all anticheats have a state-of-the-art military-grade quantum-proof AI encrypted CDNβ„’: Turns out it doesn't matter if people can extract all of the anticheat modules or figure out when the anticheat updates.

At best, it makes it a little bit more inconvenient or time consuming for researchers (which is pretty much the whole purpose of an anticheat). The main purpose is to protect the games and this is done by protecting the modules that do the detections rather than the CDN.

I worked on this project a few years ago, even gave a talk at a local meetup about the architecture, but never got around to publish a blog post about the internals. I really enjoyed working on this project, trying out new tech stack and learning about devops, deployment, object storage (MinIO) and a lot more. While some of the information likely is not unknown anymore, I still hope you learned something.

Appendix

EDIT: Turns out the CDN doesn't work anymore, but I wanted to include it for the sake of completeness

EQU8 is an anticheat developed primarily for the game Splitgate. It isn't as advanced as the previously mentioned anticheats, but still provides some level of protection against cheaters.

The download URL is as follows: https://download2.equ8.com/v1/a1/{id}/updates.json, where {id} is a unique identifier for the game (e.g. 36 for Splitgate)

This response can be parsed with the following structures:










We can then search for the anticheat.x64.equ8.exe file which is the main executable and download it.

FACEIT

FACEIT is the anticheat of private leagues for games such as CSGO or League of Legends. They are one of the top anticheats in this space due to their invasive checks and little public information about their detections.

You can find the download link on their anticheat page which links to here: https://anticheat-client.faceit-cdn.net/FACEITInstaller_64.exe It only includes the frontend iirc, and I didn't spend much more time on it.

ESEA

This anticheat requires you to have an account, and last time I checked their download page had a CAPTCHA, making it a little bit more inconvenient to track updates. Anyways, here's the download link: https://play.esea.net/index.php?s=downloads&d=download&id=1


Read the original article

Comments

  • By nulld3v 2025-06-303:245 reply

    Very nice walk-through on the reverse engineering process.

    Also, they linked this post that made my jaw drop: https://www.unknowncheats.me/forum/anti-cheat-bypass/667333-...

    Apparantly BattleEye anti-cheat had an exploit where hackers could permanently ban any player they wanted. BattleEye allowed anybody to log in as a "game server" so hackers simply booted up a fake server, told BattleEye that "player X has logged in and is doing a bunch of suspicious stuff" and then player X's account was no more...

    I'm sorry, why do we trust these guys again?

    • By AHTERIX5000 2025-06-309:17

      That's scary. I have an old Steam account with tons of games and already got banned once due to a bug in anti-cheat software and for a while my whole account was marked with a cheater tag.

      The bug was so widespread that developers eventually removed bans but I'm sure something similar could happen where problem goes undetected and it would be really hard to try to convince developers to lift a ban.

    • By AnthonyMouse 2025-06-3010:072 reply

      It's crazy that people allow this stuff to effectively run as root. One of these companies is going to have a vulnerability that lets other players run code on your machine in kernel mode.

      • By pxc 2025-06-3013:564 reply

        It's kind of amusing to me how some PC gamers act superior to console gamers because PC gamers run their games on a flexible, customizable, general-purpose machine that the user controls rather than an appliance... and then immediately hand over control to half a dozen companies at a level that reduces "their" PC to a vendor-owned appliance anyway.

        If you are a PC gamer and run anti-cheat software like this, you should probably think of your gaming PC as a much more powerful and much jankier console, and avoid running or storing anything on it other than your games.

        • By MisterTea 2025-06-3016:201 reply

          > and then immediately hand over control to half a dozen companies at a level that reduces "their" PC to a vendor-owned appliance anyway.

          This was not always the case.

          Also, the publishers lie about how invasive their software is - see the Sony rootkit fiasco.

          • By pxc 2025-06-3017:24

            > This was not always the case.

            I know. :(

            (Though, unfortunately, the SecuROM fiasco shows that this has sadly been going on a long time.)

            I say it's amusing, but it's a bitter thing for me, too.

        • By ragequittah 2025-06-3018:541 reply

          You just dual boot. Windows is a joke itself even without the anticheat shenanigans so I use it like a toy. Any real work gets done in Luks encrypted Linux inaccessible to the Chinese company with a rootkit in my windows. Hopefully.

          • By endmin 2025-06-3023:461 reply

            Sony is Japanese

            • By pxc 2025-07-0220:00

              Maybe they're thinking of Riot Games' parent company, Tencent.

        • By whoisyc 2025-06-3019:551 reply

          What makes you think the PC gamers who do the PC master race things are the same people as the ones playing games with invasive anticheat? Just because they both game on PCs? Your assumption tells more about yourself than those mythical β€œPC gamers”, whoever they are.

          • By pxc 2025-06-3021:05

            Maybe you skipped over the word "some" in your reading of my comment, or there's other ambiguity in the scope of a subordinate clause that you interpreted uncharitably, but I don't actually assert (or assume) that all or only PCMR types run games that require such rootkits.

        • By hoseja 2025-07-017:551 reply

          > and then immediately hand over control to half a dozen companies at a level that reduces "their" PC to a vendor-owned appliance anyway.

          Only when you want to play mainstream anticheat slop.

          • By pxc 2025-07-0117:25

            A lot of people do! That's what makes it mainstream.

            Even though it's not been part of my life for a long time, I would still prefer a world where people can participate in trendy multiplayer games without subjecting themselves to such corporate malware.

            But I agree, many games are better and lack this, and a lot of games that rely on nasty anti-cheat software succeed more based on network effects than on intrinsic excellence.

            If you game for games' sakes, it's not too painful to avoid games so encumbered, or to cut these from your gaming diet. If you game as a ritual to stay in touch with distant friends, you will probably experience more pressure towards the rootkit-encumbered slop.

      • By monster_truck 2025-06-3013:01

        Happens about as often as games ship UI middleware that uses html and has xss, leading to an rce when the game leaves itself running as admin after an update. So basically all the time.

    • By ronsor 2025-06-303:341 reply

      Because game companies force you to in order to play.

      • By seangrogg 2025-06-3016:30

        Play dumb games, win dumb prizes.

    • By ethan_smith 2025-06-305:522 reply

      This BattleEye exploit demonstrates a classic failure of trust boundary definition - they effectively created a system where client attestation was accepted without proper authentication or verification.

      • By gen6acd60af 2025-06-309:492 reply

        >a classic failure of trust boundary definition - they effectively created a system where client attestation was accepted

        Can you elaborate? I'm unsure what a trust boundary definition means in this context and how it relates to attestation.

        • By close04 2025-06-3012:39

          It means you trust something with lower trustworthiness without (re)validating, or even trusting it at all if the validation isn't all but guaranteed. The boundary is when you switch between levels of trust.

          Trusting something outside of your control is a good example. When your trusted game server trusts the untrusted game client when it says "trust me, it was a headshot" without validating this.

        • By lightedman 2025-06-3012:39

          trust boundary basically means a spot in execution where the trust level of code changes (aka privilege level) and thus needs reverification

      • By cobbal 2025-06-3017:08

        Fortunately they have a solution for trusting untrusted clients already! They just need to run an anti-cheat for their anti-cheat.

    • By dogleash 2025-06-3016:401 reply

      > I'm sorry, why do we trust these guys again?

      Anyone who's attachment to gaming is low enough to let things like this effect their purchase decisions are already out. To the devs/pubs, those customers don't even exist in the category of potential customers. So they just worry about not pissing off the existing customerbase by changing the status quo too much or too fast.

  • By rak 2025-06-304:54

    ESEA shipped their client and anti-cheat with a free bitcoin miner back in the day: https://en.wikipedia.org/wiki/ESEA_League#Bitcoin_mining_inc...

  • By bpbp-mango 2025-06-304:391 reply

    my friends got me in to valorent for a time, but I found the idea of a kernel level anticheat far too invasive

    • By 7bit 2025-06-306:571 reply

      Most online Games require kernel Level anti Cheat.

      • By maeln 2025-06-307:374 reply

        No, very few of them actually use kernel level anti cheat. Really the only game that use them is Riot's games and Counter Strike private league FACEIT (as far as I remember).

        • By caem 2025-06-309:14

          Both EAC and BattleEye are also kernel level anticheats nowadays. Only if you're running them under Linux do they run in userspace only. Other than that it's pretty much only VAC, Overwatch's anticheat and maybe some other obscure ones that run in userspace.

        • By Goronmon 2025-06-3016:10

          No, very few of them actually use kernel level anti cheat.

          What are the biggest vendors for anti-cheat that avoids that level of access?

        • By Hikikomori 2025-06-3017:17

          Battleye and EAC are he biggest 3rd party AC and they've been in kernel for many years.

        • By nativeit 2025-06-3012:36

          There’s also this little known title, I think I have this rightβ€”β€œGrand Theft Auto”.

HackerNews