Over the course of the last decades, video games have continuously risen in popularity. Today, hundrets of thousands of people play video games every day. Many of these games have multiplayer, where an enormous amount of people play together at the same time. When thinking about ‘hacking’ in multiplayer games, most people will think of players using wall hacks or aim bots, which allow ‘hackers’ to see other players through walls or help them with their aim in shooter games. These are usually ‘hacks’ that give players an unfair advantage in these games. Rarely, however, do people think of security threats that could lead to exposing your data or system to attackers.
One of the biggest video games of the recent times are the Dark Souls series from FromSoftware. With the first game releasing in 2011, over the years, additional games of theseries released, and by 2022 the series sold over 33 million copies[1]. Dark Souls is known for it’s dark atmosphere and it’s high difficulty.However, in early 2022, an exploit that would allow for Remote Code Execution(RCE) was discovered in the multiplayer of the Dark Souls games, potentially affecting nearly all Dark Souls players.
The RCE Exploit
On the January 22nd 2022, a Twitch Streamer with the username ‘The__Grim__Sleeper'[2] was playing Dark Souls 3 on stream. At some point during the online session, the game of The__Grim__Sleeper suddenly crashed, and Microsoft’s text-to-speech starts speaking.
A video clip of this can be found here:
https://clips.twitch.tv/GlamorousDarlingEggnogBudStar-t7dxGTY8KFWVHkL4 [3]
Later, an user called ‘tremwil'[4] (in some articles also referred to as ‘nrssr’) announced that he was the one that used the exploit against The__Grim__Sleeper. Tremwil was the one who initially discovered the exploit, and had sent a report, containing documentation of the vulnerabilities and fixes for them, as well as video demonstrations, to Bandai Namco, the publisher of the game. This report was made in early December 2021, and Bandai Namco’s support indicated that the report had been given to FromSoftware’s security teams. However, as there was no further action from FromSoftware to address the vulnerabilities, tremwil decided that they needed to bring further attention to this problem[5]. For that reason, he showcased the possible threats of the exploit on The__Grim__Sleepers live stream. While only showcased on Dark Souls 3, the exploit was also present in the Games Dark Souls 2, Dark Souls: Remastered and Dark Souls: Prepare to Die Edition[4]. At the time, FromSoftware was only a few weeks away from releasing another Game: Elden Ring. A demo Closed Network Test build of the game was investigated and also found to contain the vulnerable code. However, in the release version of Elden Ring, the exploit had been removed.
This incident garnered a lot of attention in the Dark Souls community, and on January 23rd, FromSoftware announced that the online servers for Dark Souls Prepare to Die Edition, Dark Souls: Remastered, Dark Souls 2 and Dark Souls 3 would be temporarily deactivated[6].
In the following section, the way the exploit work will be described. For this, the proof of concept provided for Dark Souls 3 by tremwil will be used as a basis[4]. While the details of the exploit may vary between the games, the general approach is the same in all the games. The basis for the exploit are two bugs. All code shown is also taken from this GitHub repository containing the proof of concept.
Bug 1: Missing Bounds Check in Entry List Parser
For Matchmaking, push requests containing session join information are used. This information is stored in a custom binary format that consists of a chain of length-delimited data entries. The format of the entries is[4]:
struct Entry<br>{<br> uint32_t type_or_id; // not sure, but probably a type (fixed length = 2, variable length = 1 ?)<br> uint32_t size;<br> uint8_t data[size];<br>}
When copying the data, the game trusts the size field without checks, which can create an out-of-bounds read. This could be used to set the size field to a extremely large or invalid value, resulting in the memory allocation to fail and the game to crash. Also, the unchecked size is passed to the constructor of a DLMemoryInputStream. This is a key component of the exploit.
Bug 2: Buffer Overrun in ‘NRSessionSearchResult’
The parser for the NRSessionSearchResult first parses a list of properties, that are either 4 byte ints, 8 byte ints or null-terminated wide strings. After that, the Steam persona name of the host as a null-terminated wide string and some for the exploit unimportant data follows. The parsing of the Steam persona name, as well as the property list parser, are using a fixed-size stack buffer to read strings. And in neither cases a bounds check is performed on the buffer. Using this, the buffer can be overrun, leading to the corruption of the stack. The code for this looks like this[4]:
size_t idx = 0;
wchar_t wchr = 0;
do {
// read_wchar() function at vftable index 17 of DLEndianStreamReader
wchr = stream_reader->read_wchar();
player_name_buff[idx] = wchr;
idx++;
} while (wchr != 0);
Virtual call / ROP chain
The DLMemoryInputStream object looks like this[4]:
struct DLMemoryInputStream {<br> uintptr_t* vftable_ptr; // Offset 0<br> size_t data_size; // Offset 4 (32bit) / 8 (64bit)<br> uint8_t* data_buffer; // Offset 8 (32bit) / 16 (64bit)<br> // Entries after the buffer are not important for the exploit <br>}
Through the use of the first Bug described above, an attacker can control the data_size field and set it to the stack memory address of the data_buffer field. The stack buffer is then placed at the top of the frame by the compiler. Using the second Bug described above, an attacker can then overwrite the lower two bytes of the vftable_ptr. The DLEndianStreamReader then calls the DLMemoryInputStream internally and the code will be redirected. The two bytes allow the attacker to jump to the 22nd function in the DLEndianStreamReader vftable, which in turn calls the 6th virtual method of the object pointed at by its first field.
In a 64-bit process, like Dark Souls 3, the following instructions are executed[4]:
MOV RCX,qword ptr [RCX + 0x8]
MOV RAX,qword ptr [RCX]
JMP qword ptr [RAX + 0x40]
RCX is a pointer to the DLMemoryInputStream object, and the first instruction writes the data_size field into RCX. As described above, using the first Bug, the data_size field has been set to the stack address pointing to the data_buffer. The two next instructions then redirect execution to the memory address the attacker has written at offset 0x40 in the data_buffer. Through this, arbitrary code redirection is achieved. Following this, a chain of code redirection can be set up, which copies its payload into a suitable memory region. Since the buffer now acts as a virtual method table, these memory regions are close to virtual calls with different offsets. In the proof of concept of tremwil, using only 3 gadgets was enough to achieve remote code execution.
Transmission trough multiplayer
What makes this exploit so dangerous is its method of transmission. The NRSessionSearchResult used for the exploit is contained in multiplayer matchmaking push requests. That means that the exploit can be used an any unsuspecting player joining the attackers online session. But through another oversight, this exploit can be used even more severely. There is a request called RequestSendMessageToPlayers and it looks like this[4]:
message RequestSendMessageToPlayers {
repeated uint32 player_ids = 1;
required bytes push_message = 2;
}
Normally, a host uses this request to send the PushRequestAllowBreakInTarget push message to invaders. It is used for the invaders to gain spawn coordinates. This is the only way the RequestSendMessageToPlayers request is used in the game. However, the RequestSendMessageToPlayers request can be used to send any push message to any player ids. This means that an attacker could send a push message containing the exploit to any known player ID. Furthermore, through sending multiple request containing large chunks of possible player Ids, the exploit can easily be spread to a large percentage of online players.
At the time the exploit became known in January 2022, six years after its initial release, Dark Souls 3 had an average of around 15.000 concurrent players. At it’s height, there were around 75.000 concurrent players[7]. Elden Ring, which in its demo Closed Network Test build contained the same vulnerable code, had a peak concurrent player count of around 522.000 players[8]. If this exploit had been discovered earlier or by a malicious attacker, most of those player could have become a victim to the exploit in a matter of minutes.
When Elden Ring finally released on February 25, 2022, the vulnerabilities had been fixed[9]. For the rest of the Dark Souls series, the fixes took a while longer. First, Dark Souls 3 restored it’s multiplayer in August 2022[10]. The multiplayer of Dark Souls 2 followed in October[11]. At last, Dark Souls: Remastered was restored in November[10]. FromSoftware also announced that Dark Souls: Prepare to Die Edition would not restore it’s multiplayer, due to an aging system[11].
Conclusion
Dark Souls multiplayer code contained huge vulnerabilities, that allowed for remote code execution. And because of unsafe code, this vulnerability could have easily been spread to nearly the entire player base. With the rise of video games, multiplayer games have more users than ever, therefore, vulnerabilities in multiplayer’s affect more and more people. What makes this extra dangerous is the absence of awareness for security in multiplayer games. Most game developers will spent more time thinking about ways to prevent cheating in the game than the security of their multiplayer system. And the chances of vulnerabilities being discovered are generally low, as aside from the developers, not many people will get a look at the games code. Dark Souls is one of the biggest series in video games and has an active modding community, meaning there are a lot more people than normal interested in the games code. And yet, it took 11 years to find this vulnerability. There were multiple other, smaller, vulnerabilities found in Dark Souls 3 before and after the one in January 2022. And there are thousands of games out there, with potentially flawed multiplayer’s. The awareness of game developers towards security needs to be raised and studios and publishers need to push for a stricter enforcement of security measures, as vulnerabilities such as found in Dark Souls 3 can have devastating effects for players and developers alike.
Sources
[1] Dark Souls-Wikipedia: https://en.wikipedia.org/wiki/Dark_Souls (last accessed 15.08.2023)
[2] The__Grim__Sleeper – Twitch: https://www.twitch.tv/the__grim__sleeper (last accessed 15.08.2023)
[3] https://clips.twitch.tv/GlamorousDarlingEggnogBudStar-t7dxGTY8KFWVHkL4 (last accessed 12.08.2023)
[4] GitHub – tremwil/ds3-nrssr-rce: Documentation and proof of concept code for CVE-2022-24125 and CVE-2022-24126.: https://github.com/tremwil/ds3-nrssr-rce (last accessed 14.08.2023)
[5] The Dark Souls RCE Exploit Was Years in the Making, Andrea Shearon: https://www.fanbyte.com/games/news/dark-souls-3-rce-vulnerability-code-present-elden-ring (last accessed 15.08.2023)
[6] Dark Souls – Twitter/X: https://twitter.com/DarkSoulsGame/status/1485210967009071108 (last accessed 15.08.2023)
[7] DARK SOULS™ III – Steam Charts: https://steamcharts.com/app/374320 (last accessed 14.08.2023)
[8] ELDEN RING – Steam Charts: https://steamcharts.com/app/1245620 (last accessed 14.08.2023)
[9] Details about the ‘Dark Souls’ hacking exploit have been published, Demi Williams: https://www.nme.com/news/gaming-news/details-about-the-dark-souls-hacking-exploit-have-been-published-3186809 (last accessed 14.08.2023)
[10] Dark Souls Remastered’s PvP servers are back online | Rock Paper Shotgun, CJ Wheeler: https://www.rockpapershotgun.com/dark-souls-remastereds-pvp-servers-are-back-online
[11] Dark Souls – Twitter/X: https://twitter.com/DarkSoulsGame/status/1584821064420716544 (last accessed 15.08.2023)
Images
Featured Image: https://wallpaperset.com/dark-souls-iii-wallpapers
Leave a Reply
You must be logged in to post a comment.