One such issue affected the massively popular Dota 2 video game. Dota used an outdated build of
v8.dll that was compiled in December 2018. It’s no surprise that this build was vulnerable to a range of CVEs, many of them even being known exploited vulnerabilities with public proof-of-concept (PoC) exploits. We discovered that one of these vulnerabilities, CVE-2021-38003, was exploited in the wild in four custom game modes published within the game. Since V8 was not sandboxed in Dota, the exploit on its own allowed for remote code execution against other Dota players.
We disclosed our findings to the developer of Dota 2, Valve. In response, Valve pushed an update for Dota on January 12, upgrading the old and vulnerable version of V8. This update took effect immediately, since Dota has to be up to date for players to participate in online games. Valve also took additional action, by taking down the offending custom game modes, notifying the affected players, and introducing new mitigations to reduce the game’s attack surface.
Customization of Dota can take many forms: There are custom wearable in-game items, announcer packs, loading screens, chat emoticons, and more. Crucially, there are also custom community-developed game modes. These are essentially brand-new games that leverage Dota’s powerful game engine to allow anyone with a bit of programming experience to implement their ideas for a game. Custom game modes play an important role in Dota, and Valve is well aware of the benefits of letting players express their creativity by developing custom game modes. After all, Dota itself started out as a game mode for Warcraft III: The Frozen Throne. This might be why game modes can be installed with a single click from within the game. As a result, there are thousands of game modes available, some of which are extremely popular. For instance, DOTA AUTO CHESS was played by over 10 million players.
Before a game mode can be played by regular players, it must be published on the Steam store. The publishing process includes a verification performed by Valve. While this could potentially weed out some malicious game modes, no verification process is perfect. As we’ll show later, at least four malicious game modes managed to slip through. We believe the verification process exists mostly for moderation reasons to prevent inappropriate content from getting published. There are many ways to hide a backdoor within a game mode, and it would be very time-consuming to attempt to detect them all during verification.
$.AsyncWebRequest function, which, in combination with
We discovered four malicious custom game modes published on the Steam store, all developed by the same author. The first game mode (id 1556548695) is particularly interesting, as it appears that it is where the attacker only tested the exploit, judging from the lack of an actual payload attached to it. Interestingly enough, the attacker also used this game mode to test various other techniques, leaving in commented-out code or unused functions. This offered us a great opportunity to understand the attacker’s thought process.
As can be seen in the above screenshot, the attacker was very transparent about the nature of this game mode, naming it
test addon plz ignore and even going as far as using the description to urge other players not to download this game mode. While this might seem like an expression of good faith, we’ll show shortly that in the other three malicious game modes, the same attacker took the exact opposite approach and tried to make the malicious code as stealthy as possible.
There are now public PoCs and write-ups for this CVE. However, these weren’t available in March 2022, when the attacker last updated the game mode. This means they had to develop a large portion of the exploit themselves (even if there was a public PoC at that time, the attacker would still need to possess some technical skills to backport it to the outdated V8 build that Dota was using). Even so, the core of the exploit was provided in the Chromium bug tracker entry for the CVE. There is a snippet of code that can trigger the vulnerability to leak the purportedly inaccessible TheHole object and then use this leaked object to corrupt the size of a map. The attacker took this snippet and pasted it into their exploit, building up the rest of the exploit on top of this corrupted map.
Interestingly, the exploit contains a large amount of commented-out code and debug prints. This further suggests that the attacker had to put a lot of effort into weaponizing the vulnerability. The attacker-developed part of the exploit starts by using the corrupted map to corrupt the length of an array, achieving a relative read/write primitive. Then, it corrupts an
ArrayBuffer backing store pointer in order to gain an arbitrary read/write primitive. There is no
addrof function, as addresses are leaked by placing the target object at a known offset from the corrupted array and then using the relative read primitive. Finally, with the arbitrary read/write in place, the exploit uses a well-known WebAssembly trick to execute custom shellcode. We have tested the whole exploit locally against Dota and can confirm that it worked.
evil.lua. This is where the attacker tested the capabilities of the server-side Lua execution. See the Lua snippet below where the attacker tested the following in particular:
- Dynamic compilation of additional Lua code (
- Determining the exact version of the Lua interpreter
- Executing arbitrary system commands (
- Coroutine creation
- Network connectivity (HTTP GET requests)
It didn’t take long to discover three more malicious game modes, all by the same author (who also happened to be the author of the previously analyzed
test addon plz ignore game mode). These game modes were named
Overdog no annoying heroes (id 2776998052),
Custom Hero Brawl (id 2780728794), and
Overthrow RTZ Edition X10 XP (id 2780559339). Interestingly, the same author also published a fifth game mode named
Brawl in Petah Tiqwa (id 1590547173), which did not include any malicious code (to our great surprise).
The malicious code in these new three game modes is much more subtle. There is no file named
After discovering the four malicious game modes, we tried to hunt for more — unfortunately, our trail went cold. Therefore, it’s not clear what the attacker’s ultimate intentions were. However, we believe that they were not exactly pure research intentions, for two main reasons. First, the attacker did not report the vulnerability to Valve (which would generally be considered a nice thing to do). Second, the attacker tried to hide the exploit in a stealthy backdoor. Regardless, it’s also possible that the attacker didn’t have purely malicious intentions either, since such an attacker could arguably abuse this vulnerability with a much larger impact.
Before we sign off, we would like to thank Valve for quickly addressing our reports. We hope that they will continue updating V8 in the future and reduce the patch gap as much as possible. Valve also shared with us some plans about additional mitigations, and we will be most excited to see those implemented in practice. Due to the potential impact, we would also recommend very careful vetting of future updates for popular custom games.
We can also appreciate that Valve made the decision to publish custom game modes on Steam even though it might put more responsibility on their shoulders. Ultimately, this is a net positive for the overall players’ security, due to the fact that Valve can moderate the published game modes and take down malicious ones. Many other games don’t have such integrated support for custom games, so players resort to downloading mods from random third-party sites, which are often known to bundle malware.
Indicators of Compromise (IoCs)