Now Reading
From Zero to 0-day — Neodyme

From Zero to 0-day — Neodyme

2023-06-11 02:36:14


We recognized three impartial distant code execution (RCE) vulnerabilities within the in style Counter-Strike: International Offensive sport. Every vulnerability could be triggered when the sport shopper connects to our malicious python CS:GO server. This publish particulars our journey via the CS:GO binary and conducts a technical deep dive into numerous recognized bugs. We conclude by presenting a proof of idea (POC) exploit that leverages 4 completely different logic bugs into distant code execution within the sport’s shopper, triggered when a shopper connects to the server.


The CS:GO patch dated 04/28/2021 fastened a number of crucial vulnerabilities, together with three crucial bugs from us. This publish describes our strategy and the way we found three crucial vulnerabilities. We current a single bug chain, consisting of 4 logic bugs, and clarify how these led to a distant code execution (RCE) on the shopper by cleverly combining them. Though the publish does clarify the 4 logic vulnerabilities, its focus is on the methodology of our analysis.

First we take a look at current analysis for the CS:GO sport and provides a basic introduction to make reverse engineering of the advanced shopper much less painful. The publish then introduces primary ideas of the CS:GO community protocol like fast_dl and Cvars and element 4 completely different logic bugs. Combining the bugs results in the proof of idea that exploits a CS:GO shopper by solely connecting to a malicous, attacker managed server.

Desk of contents

  1. CS:GO
  2. Know your target
    1. Software Development Kits
    2. Public Research
    3. Cheating Communities
    4. Debug Symbols
    5. Fuzzing
  3. The discovery of four logic bugs
    1. Bug 1: Execution of privileged commands from the server
    2. Bug 2: Arbitrary file download due to extension stripping
    3. Bug 3: Arbitrary text file write in game directory
    4. Bug 4: Fallback to disabled signature checks
  4. Full logic bug chain
    1. Gameinfo.txt
    2. CVars
    3. Exploit flow
  5. Video
  6. Closing Thoughts
  7. Timeline


The free-to-play sport Counter Strike: Global Offensive (CS:GO) continues to expertise nice recognition with 21 million gamers per 30 days, not least due to the big variety of sport modes supplied by the various community-hosted servers. The sport from 2012 relies on the even older source engine (2004), recognized for video games equivalent to Portal, Half-Life 2 and Left 4 Dead. The supply engine in flip makes use of elements from its predecessors, GoldSrc (1998) and the Quake engine (1996). This historical past already signifies that the highly effective and complicated supply engine possesses some elements, for which safety didn’t but stand within the foreground whereas programming.

The numerous sport modes, group servers and modding assist take a toll: a big assault floor. The numerous file codecs equivalent to textures, 3D fashions and AI navigation factors undergo all kinds of parsers with utterly attacker-controlled knowledge as the information is shipped instantly from the CS:GO server. As well as, the supply engine implements its personal TCP-like community stack primarily based on UDP with all of the related issues in such a posh implementation. The community implementation has already been exploited in other attacks.

Know your goal

Safety analysis isn’t about blindly poking round and searching for safety gaps. As a result of: Solely when you could have totally understood a goal, you’re able to interrupt via the technical restrictions. Step one ought to due to this fact be to acquire as a lot details about the goal as attainable. The next sections present concepts for this “recon” section:

Software program Growth Kits

Video games with modding assist usually present an official software development kit (SDK). Whereas the SDK doesn’t comprise the goal’s supply code, the constructions outlined there present worthwhile info on network packages and sophistication definitions that assist to know the engine. For Valve video games particularly, there have additionally been a number of supply code leaks of the engine or full video games (2003, 2007, and 2020). Though the supply code is usually outdated and accommodates many, now fastened, safety holes, these leaks are very useful. Principally as a result of supply code is just extra nice to learn than compiler-optimized meeting.

Public Analysis

CS:GO is well-known, thus we weren’t the primary researchers searching for bugs on this sport. Due to this fact, we searched the Web for helpful blogposts and presentations at conferences. The knowledge described on this public analysis is usually diminished to the necessities and makes it simpler to seek out one’s method round a brand new, advanced goal.

Dishonest Communities

Tremendous annoying within the sport, liked by safety researchers: Cheater communities like UnknownCheats exist. These boards present detailed reverse engineering posts and internals to the engine. On this case, Felipe had already written a Network Cheat that contributed loads to the understanding of the community protocol.

Debug Symbols

Debug symbols comprise the in any other case unrecognizable operate names and sophistication constructions that make reverse engineering rather more handy. Typically variations of the sport are additionally deliberately shipped with debug symbols to generate higher error studies. Nonetheless, typically programmers overlook to take away the debug symbols from the ultimate binaries of the sport. Programmers are people, and people make errors.

CS:GO Binary with Debug Symbols

CS:GO Binary with Debug Symbols

The CS:GO model for macOS from April 2017 (proven beneath) contained full debug symbols. Recreation information with symbols are many occasions bigger than with out and may due to this fact be recognized routinely utilizing SteamDB and previous repositories.

2017-04-26T00:15:42+00:00 [M:8167272392035836136]
csgo/bin/osx64/server.dylib (+9.30 MiB)
bin/osx64/engine.dylib (+5.17 MiB)
bin/osx64/scaleformui.dylib (+3.23 MiB)
csgo/bin/osx64/shopper.dylib (+12.13 MiB)
bin/osx64/materialsystem.dylib (+2.18 MiB)

Whereas in 2021 it was nonetheless attainable to particularly obtain previous variations utilizing SteamCMD, the function appears to have been disabled by Valve within the meantime.


Regardless of all the data, you need to make investments many hours in reverse engineering the goal. Solely after getting totally understood which buffer processes the community knowledge through which digital operate with which arguments you can begin doing thrilling issues. However the effort is value it: we discovered instantaneous shopper crashes utilizing Hongfuzz, the public protobuf network structures, and libprotobuf-mutator. These crashes instantly offered instruction pointer management and had been thus very probably exploitable! To check the total extent and develop exploit methods, we determined to implement our personal early-stage server in Python.

The invention of 4 logic bugs

For a goal like CS:GO, resulting from years of improvement and public bug bounty program, easy bugs are most definitely fastened by now. In case you are solely searching for stack overflows in random strategies of the large engine.dll, you’ll shortly quit in frustration. However it’s true: each little anomaly can show to be worthwhile together with different gaps. In the course of the weeks of staring on the CS:GO disassembly and source-code leaks, we consistently requested ourselves the next questions:

  • What primitives can we have already got?
  • What can we do by combining them?
  • What safety mechanisms are there?
  • What bizarre edge instances would possibly a developer not have thought of?

Reminiscence corruption exploitation is tough. Though two of the three full-chain exploits submitted by us to Valve had been reminiscence corruptions, that meant extraordinarily excessive overhead and at all times the danger that the shopper would crash due to an unfavorable reminiscence allocation. Beginning CS:GO and connecting to a server loading the map took a number of minutes every time, which made improvement very robust.

On this publish, somewhat then explaining bizarre heap feng shui mechanisms, deal with 4 logic bugs that collectively led to our objective of distant code execution on the shopper. The order of discovery was as follows.

Bug 1: Execution of privileged instructions from the server

This bug permits the attacker to execute “privileged” instructions on the shopper that normally solely work within the single participant mode

To confirm that our customized python CS:GO server is definitely working, we despatched the command echo Hiya World! to the shopper by way of CNETMsg_StringCmd and, as anticipated, obtained the output Hiya World! on the sport console. Randomly, we additionally tried sending the give up command. And the sport closed! We couldn’t imagine {that a} server is allowed to do this. Because it seems, it’s normally not allowed to take action: With the assistance of SourceMod, a supply engine modding framework that may additionally ship messages to the shopper, we recreated the identical setup with an official and modded server. The outcome: FCVAR_SERVER_CAN_EXECUTE prevented server working command: give up. Did we discover our entry bug? How precisely does the bug happen?

Supply engine single-player video games internally use a regionally hosted supply engine server. The only-player shopper then connects to its personal server to affix the sport. This single-player server ought to in fact have far-reaching rights, e.g., to vary the keyboard structure on the shopper or to take screenshots.

A multi-player server is acknowledged as a neighborhood, and thus privileged, single participant server if solely a most of 1 shopper can connect with the server. The vulnerability is within the willpower of the server kind: The maximal variety of purchasers that may connect with the server is managed by the variable m_nMaxClients and is obtained by the shopper when connecting to a server. By probability, our Python server had set the variable m_nMaxClients to 1. And with this we might execute privileged instructions on the shopper!

Host_IsSinglePlayerGame Check

Host_IsSinglePlayerGame Examine

Bug 2: Arbitrary file obtain resulting from extension stripping

This bug permits the attacker to obtain information with arbitrary file extensions, bypassing the extension filter

Supply engine servers can ship further sport information equivalent to maps or participant fashions to the shopper. The information switch could be accomplished both by way of the supply community protocol or HTTP fast_dl. To forestall malicious information from being despatched to the shopper, sure file extensions like *.exe, *.dll, *.ini are blocked.

If the fast_dl choice is ready, further content material is loaded from a specified HTTP server somewhat then from the CS:GO server instantly. The URL is dynamically generated from the server identify and the total file identify by the snprintf(p_cResult, 256, "%s/%s", p_cServerName, p_cFileName) operate. The snprintf operate limits the size of the ensuing string to 256 characters, thus truncating pointless characters from the file identify. However each p_cServerName and p_cFileName can have a size of 256 characters every! A file identify like ././[..]/file.AAA.BBB could be terminated particularly after the .AAA extension, because the .BBB half is truncated by the snprintf operate. The filter for probably harmful information can thus be bypassed utterly!

The next supply snipped illustrates that the extension is stripped:

#embody <stdio.h>

int foremost()
    unsigned char p_cResult[32];

    // String matches into 32 byte and contains the `.bsp` half
    snprintf(p_cResult, 32, "%s/%s", "AAAAAAAAAAAAAAAA", "evil.dll.bsp");       
    printf("%sn", p_cResult); // Output: AAAAAAAAAAAAAAAA/evil.dll.bsp

    // Lengthy sufficient string to truncate the `.bsp` half
    snprintf(p_cResult, 32, "%s/%s", "AAAAAAAAAAAAAAAAAAAAAA", "evil.dll.bsp"); 
    printf("%sn", p_cResult); // Output: AAAAAAAAAAAAAAAAAAAAAA/evil.dll
    return 0;

Vulnerable snprintf function cuts remaining data from string

Weak snprintf operate cuts remaining knowledge from string

This vulnerability was discovered via code evaluation of the fast_dl protocol, which has not modified a lot in recent times.

Bug 3: Arbitrary textual content file write in sport listing

This bug permits the attacker to (over)write arbitrary information within the sport folder

At this level, we weren’t positive the best way to mix the 2 earlier bugs. Due to this fact, we searched the CS:GO binary for useful privileged instructions. With the con_logfile command, we surprisingly found that this command might write arbitrary *.log information to arbitrary sport folders. As a consequence of an analogous extension stripping bug by snprintf it was additionally attainable to specify an arbitrary file extension and thus write textual content information with arbitrary contents and an arbitrary extension.

See Also

Particularly, this bug might be used to create a brand new configuration file cfg/leak.log with arbitrary CS:GO instructions. The leak.log “config” file might then the loaded by the exec leak.log command, studying the file from the cfg folder.

Bug 4: Fallback to disabled signature checks

This bug permits the attacker to launch the CS:GO shopper within the “insecure” mode, permitting to load non-signed sport binaries

When beginning the CS:GO shopper, the integrity of the sport DLLs is verified by way of matching hash values. Solely after this verification it’s attainable to play on official servers. If the DLL verification fails, a fallback to the insecure mode happens. This may also be achieved by the extra command line argument -insecure. Solely on this mode, further DLLs not positioned within the bin/ sport path could be loaded. If the attacker succeeds in making the DLL verification fail, they’ll create their very own DLLs, refer to those DLLs within the configuration and obtain command execution. On Home windows, an attacker can specify code that’s executed when the DLL is loaded right into a course of. Thus, the attacker can execute arbitrary code on the shopper system.

Home windows prevents the overwriting of DLLs, that are loaded in a working course of. Due to this fact, we needed to discover a DLL that’s verified at sport begin however isn’t loaded into the method. Fortuitously, we discovered that the shopper.dll had been changed by the client_panorama.dll and is due to this fact now not loaded, however continues to be verified! Overwriting shopper.dll with arbitrary textual content (bug 3) thus prompted the verification to fail.

Full logic bug chain

The total bug chain makes use of all 4 bugs to:

  1. execute privileged instructions on the shopper
  2. obtain a malicious DLL to the sport listing
  3. change the gameinfo.txt in order that the malicious DLL is loaded on sport startup
  4. corrupt the shopper.dll to realize a fallback to the insecure mode

To know the next steps, we nonetheless must introduce two components typical for supply engines: the gameinfo.txt and CVars:


All supply engine primarily based video games are literally “add-ons” to the essential Half-Life sport. Belongings and DLLs for the sport are loaded from a particular path outlined within the file gameinfo.txt:

	sport	"Counter-Strike: International Offensive"
	title2	"GO"
	kind multiplayer_only

	[ ...]

		SteamAppId				730	// This may mount all of the GCFs we'd like (240=CS:S, 220=HL2).
		ToolsAppId				211	

By setting |gameinfo_path|/exploit as first within the FileSystem array, the engine tries to load lacking DLLs from this path. Provided that the factor to be loaded isn’t discovered there, the unique sport path is used. One DLL that’s loaded at sport begin is matchmaking.dll. Which means we will place a brand new matchmaking.dll and invoke arbitrary code when the CS:GO shopper masses the DLL.


CVars are a basic idea in SourceEngine video games and seem in every single place. These variables management just about every part there may be to arrange within the sport: paths, key-binds, the looks of crosshairs, the sport mode, and many others. Additionally the legendary sv_cheats variable, which many Counter Strike gamers in all probability have already heard of, is a CVar. Relying on CVar, the settings may also be set by the server and thus override native choices.

Upon connecting, the shopper tells the server which native CVars are set on the shopper, in order that the server can react accordingly. For instance, the server can kick the shopper if sv_cheats is ready to 1 on the shopper. As an attacker, we have to know the set up listing from the CS:GO shopper in order that we will exploit bug 2 and bug 4 by taking a path that’s simply the fitting size. Sadly, by default, the shopper doesn’t ship alongside a CVar that accommodates the present sport listing. We due to this fact use a trick to set the brand new CVAR GAMEBIN and have it despatched again to the attacker-controlled server. The essential thought:

  1. Execute a “script” leak.log to set the CVar GAMEBIN
  2. Instruct the shopper to reconnect to the malicious server
  3. Upon reconnection, all CVars and set again to the malicious server

The small print contain invoking the path command from a config file to set the CVAR GAMEBIN to the set up path of the sport. We leverage the attacker-written config file leak.log, which incorporates the path command. The shopper has to execute the config file, in any other case the CVar isn’t saved persistently through the subsequent server join. The leak.log file is executed with the exec command. Afterwards the malicous server instructs the shopper to reconnect. Upon reconnection, the CVar is leaked again to the server.

Exploit stream


We offer a video of the above outlined chain of the 4 logic bugs (see beneath). Should you cease the video at 00:29 seconds you possibly can discover attention-grabbing output within the CS:GO console and within the exploit server:

  • The leaked GAMEBIN: f:spielesteamsteamappscommoncouter-strike international offensivecsgobin is retrieved from the exploit server
  • The CS:GO console reveals the very lengthy downloaded information, which succeed for the ././[..]/bin/matchmaking.dll.stf ././[..]/gameinfo.txt.stf information. As described above, the .stf extension is stripped through the obtain, ensuing within the obtain of matchmaking.dll and gameinfo.txt.

Closing Ideas

Usually individuals ask us how a lot time we spent on constructing this exploit chain. Sadly, we can’t decide the overall time spent. For weeks, we met on Discord within the night to change concepts, programm collectively and analyze our findings till late within the morning. Alain at the moment had roughly 250 hours of gameplay in CS:GO and had not performed a single on-line match. We discovered the bugs “comparatively” shortly, however for his or her bug bounty program, Valve requires a full-chain exploit demonstrating RCE influence. With out the frilly demonstration, the analysis would have been accomplished after 30% of the time. Therefore, we invested fairly a while in our RCE demonstration.

Talking of Valve: We turned conscious of Valve’s excessive payouts for CS:GO via various and simple looking HackerOne studies. The studies on the time solely wanted to reveal reminiscence corruption to get the total payout. Our preliminary euphoria shortly sank after our three completely different studies had been shortly declared legitimate, however nonetheless not fastened even after 13 months and a number of requests. After a whole lot of strain and the specter of full disclosure, the bugs had been lastly fastened. The payout was 7.5k per bug, lower than we anticipated. All in all a sobering expertise.

For us the CS:GO bug bounty journey was the primary time we invested weeks of time right into a venture collectively. The takeaways for us personally had been primarily:

  • Don’t search for cricitial bugs and fast wins solely.
  • Chain your bugs to unveal their full potential.
  • Maintain your eyes open for edge instances and issues devs didn’t take into consideration.
  • Strive more durable! If run towards a wall seek for the outlet and don’t quit early.


Date Motion
01.03.2020 We ship the preliminary Report with PoC video and exploit setup
01.03.2020 H1 has troubles to breed the difficulty
03.03.2020 We offer an exploit Docker setup for simpler reproducability
06.03.2020 H1 nonetheless has troubles to breed the difficulty
21.03.2020 We offer a full server setup with OpenVPN for even simpler reproducability
21.03.2020 H1 efficiently reproduces the difficulty(s) and marks the report as triaged
01.06.2020 We ask for an replace
03.06.2020 H1 states they’re nonetheless wanting into the report
18.09.2020 We ask for an replace, as a complete of half a yr has handed by
22.10.2020 We ask once more for an replace
27.10.2020 H1 states that Valve continues to be wanting into the studies
01.03.2021 We are saying “Completely happy Anniversary” and ask for an replace
March 2021 We contact different researchers who submitted bugs to Valve and take into consideration complaining in our studies as collective
22.04.2021 We write a press release about our dissatisfaction with the method and “reserve the fitting to reveal the findings within the upcoming weeks”
26.04.2021 H1 states that they flagged the report back to “inside managers” and attempt to pace up the method
30.04.2021 We discover that the problems have been fastened and ask for coordinated disclosure with Valve
01.05.2021 H1 says “Thanks for the report” and we obtain our bounty
29.03.2022 We request report disclosure, no response up to now

Source Link

What's Your Reaction?
In Love
Not Sure
View Comments (0)

Leave a Reply

Your email address will not be published.

2022 Blinking Robots.
WordPress by Doejo

Scroll To Top