ACE, or better known as Anti-Cheat Expert is, as the name suggests, an anti-cheat made by the tech giant Tencent. In today’s digital age, the line between ensuring fair play in online gaming and safeguarding personal privacy is becoming increasingly blurred. That’s why I took a look into ACE and, to be honest, the findings didn’t completely shock me.


Now, why did I look into said anti-cheat, and why exactly should it become a public concern? As a gaming enthusiast, I really enjoyed the extraction shooter Escape From Tarkov; however, after the recent events, I was looking out for an alternative.

Just shortly after the boycotting of Escape From Tarkov started, a game studio Morefun Studios announced the PC release of Arena Breakout: Infinite. Yet another extraction-type shooter. Luckily, I got a key for their closed beta quickly, after I had already spent time investigating their anti-cheat. That’s when I was motivated to write this blog post.


Gamers like them, security researchers find them interesting, and cheaters hate them. Recently, people started talking about anti-cheat more and more on social media, stating their concerns for privacy. This was led by a prime example called Vanguard made by Riot Games. The outcry started because Riot Games is Tencent owned, a chinese company and we all know that China loves your data. Turns out, they dumped fuel on the fire. Researchers who found out that Vanguard was taking screenshots of the game it was protecting appeared to believe it was capturing the whole screen with wreckless abandon.

NOTE: This was later debunked by daax a security researcher - View Tweet.

Now what if I told you that there actually is a Chinese-owned anti-cheat that is taking screens of your entire main screen? That’s how we come to Anti-Cheat Expert.


ACE is, as already mentioned, a Chinese-owned anti-cheat, which has several usermode and kernelmode components. 3 drivers, 9 DLLs… we’re not going to name them all. You can check the bottom of the article. It even has the facilities to be loaded at boot, this however is not used in Arena Breakout: Infinite. I heard from all sides that ACE is a privacy concern overall, and some even labeled it a RAT.

However, I wouldn’t go so far just yet. With this in mind, I set my focus on a particular usermode component called ACE-Safe.dll. This module contains a variety of things, but we only want to focus on their screenshot-taking capabilities in this post.


Anti-Cheats usually use the game’s HWND (their window handle) to take screenshots. ACE, however, wants to be the middle child in the anti-cheat family; instead of taking a screenshot of only the game, or at least of only the game’s window size, it takes a screenshot of the entire display! Noice. Now, words are just words if you can’t prove what you are saying. The following code is taken directly out of the binary.

if (GetVersion() >= 0x80000000 ||(result = check_window_station(), result <= 0))  
    hdcSrc = CreateDCW(L"DISPLAY", 0, 0, 0);  
    CompatDC = CreateCompatibleDC(hdcSrc);  
    HorizontalRes = GetDeviceCaps(hdcSrc, HORZRES);  
    VerticalRes = GetDeviceCaps(hdcSrc, VERTRES);  
    CompatibleBitmap = CreateCompatibleBitmap(hdcSrc, HorizontalRes, 16);  
    v5 = SelectObject(CompatDC, CompatibleBitmap);  
    GetObjectW(CompatibleBitmap, 32, &pv);  
    v6 = v15 * v14 * v16;  
    v7 = sub_180002D80(v6, ".\\crypto\\rand\\rand_win.c", 719, v7);  
    if ( v7 )  
        v8 = VerticalRes - 16;  
        for ( y1 = 0; y1 < v8; y1 += 16 )
            BitBlt(CompatDC, 0, 0, HorizontalRes, 16, hdcSrc, 0, y1, 0xCC0020);
            GetBitmapBits(CompatibleBitmap, v6, v7);
            v10 = sub_18000B8F0();
            sub_18000B6B0(v7, v6, v17, 0, v10, 0);
            sub_180011820(v17, 0x14);


    v11 = SelectObject(CompatDC, v5);  
    return DeleteDC(DCW);  

In the following, I will dissect the code piece by piece to hopefully make it understandable for everyone reading.

if (GetVersion() >= 0x80000000 || (result = check_window_station(), result <= 0))

The function starts off with checking if the current Windows version is NT, 2000, or XP. Most machines will fail this check, hence the second check for the Window Station. If the Window Station name does not contain the substring “Service-0x” the function proceeds.

hdcSrc = CreateDCW(L"DISPLAY", 0, 0, 0);
CompatDC = CreateCompatibleDC(hdcSrc);

After successfully passing the entry check, the function now tries to create a device context handle for the primary monitor. Once the device context handle has been acquired, it then tries to create a memory device context, that is compatible with the specified device context. Something I found quite peculiar is that this function does minimal error checking.

HorizontalRes = GetDeviceCaps(hdcSrc, HORZRES);  
VerticalRes = GetDeviceCaps(hdcSrc, VERTRES);

Now that the function has acquired the necessary contexts, it proceeds with getting the horizontal, and vertical resolutions of the display.

CompatibleBitmap = CreateCompatibleBitmap(hdcSrc, HorizontalRes, 16);

Creating a compatible bitmap is the primary building block to getting the actual bits of the screenshot taken. It does this by providing the device context, the width of the display, and the height 16. The height in this case plays a special role, as we will find out in a bit.

v8 = VerticalRes - 16;
for ( y1 = 0; y1 < v8; y1 += 16 )

v8 holds the height of your display - 16, here we start to eventually notice a pattern. In the for loop, we start at y = 0 and incrementally add 16 to y as long as y is smaller than v8. Usually, screenshots are taken with your display width and height at once, or at least the game’s window width and height. In this case, ACE took a special route; this loop is reminiscent of old CRT raster scanning patterns by screenshotting the whole width of your display at once; but only 16 pixels in height per iteration.

NOTE: I was made aware that this could also be used as a low FPS stream.

BitBlt(CompatDC, 0, 0, HorizontalRes, 16, hdcSrc, 0, y1, 0xCC0020);
GetBitmapBits(CompatibleBitmap, v6, v7);

BitBlt is the WinGDI function that actually grabs the pixels off of your screen. Here we can see it being called with the memory DC, a height of 16, x always at 0, and the current y value labeled y1. For further processing, GetBitmapBits is called to acquire the actual bits of the screenshot taken; it then stores them in v7.

Compile-Ready Implementation – View

NOTE: The sub_X functions are all related to OpenSSL and somewhat obfuscated. It’s a combination of mutation and OpenSSL being the most obscurely written piece of work I’ve ever seen.


The whole function seems dubious at best; and during my testing, it was never invoked. However, just its presence was mildly alarming.

The function could very likely be only used in certain situations, e.g., when a cheater triggered certain detections, a player was reported for cheating, etc. Worth mentioning is that the function is being referenced in other parts of the binary; hence, I wouldn’t categorize it as dead code.

It seems to be an artifact of the actual capabilities this anti-cheat has, which may not be present in the International version. In my honest opinion, such an anti-cheat feature shouldn’t be allowed in a game that is not solely available in China. ACE overall is a treasure trove of privacy violations: checking recently used files, uploading files to their servers, banning having reverse engineering tools open, or having used them recently on game files—the list goes on.

I highly recommend against running this anti-cheat on any machines that have anything personal or work-related on them.



  • ACE-ATS64.dll
  • ACE-CSI64.dll
  • ACE-DFS64.dll
  • ACE-DRV64.dll
  • ACE-IDS64.dll
  • ACE-Trace.dll
  • ACE-Safe.dll
  • ACE-SSC64.dll
  • ACE-Base64.dll


  • ACE-Base.sys
  • ACE-BOOT.sys
  • ACE-SSC-DRV64.sys


a blog about exploring reverse engineering, hypervisor development and software programming.

ACE and their screenshot shenanigans

By koyz, 2024-06-07