Documentation and proof of concept code for CVE-2022-24125 and CVE-2022-24126.
A new game update, 1.15.1, has been released for Dark Souls III on 2022/08/25, along with the restoration of online services. This update fixed both CVE-2022-24125 and CVE-2022-24126, along with a wide variety of other potential security vulnerabilities present in the game's P2P networking (OOB reads/writes). Furthermore, all known exploits allowing one to corrupt the save of other players have been fixed. Many common petty cheats (e.g. "curse knife") which could be encountered often during online multiplayer have also been patched.
This repository contains proof of concept code and documentation for the most recent RCE exploit affecting FROM SOFTWARE games, CVE-2022-24126. While theoretically possible in other games, focus is on Dark Souls III as this is the game my research has been conducted on. As of now proof of concept code only exists for Dark Souls III, the vulnerability has been confirmed to be present in:
The vulnerable code is also present in Sekiro (credit: LukeYui), although there is no way to trigger it. Presence in Demon's Souls has not been confirmed but is very likely. While the closed network test was affected by this, the release version of Elden Ring is not. In fact, a huge list of network crashes, out-of-bounds reads/writes and exploits allowing players to modify the game data of peers which were present in Dark Souls III have been patched in Elden Ring. Kudos to LukeYui for compiling this list and to FROM SOFTWARE for acting swiftly! I'm happy to say that Elden Ring is undisputably the safest FROM SOFTWARE title when it comes to the extent of the damage hackers can inflict.
Contrary to popular belief, this is NOT a peer-to-peer networking exploit. It is related to the matchmaking server and thus much more severe, since you do not need to partake in any multiplayer activity to be vulnerable due to another matchmaking server vulnerability (CVE-2022-24125).
With the game having an average concurrent playerbase of about 20,000 players in the months preceding the server shutdown, it was clearly an issue that needed fixing immediately, especially with the possibility of it being in Elden Ring. Since FROM SOFTWARE had not yet acted over 40 days after my initial report with proof of concept videos and detailed exploit documentation (which a large part of this readme is based on), I decided to demonstrate the existence of the exploit puclicly in a benign manner in the hopes of raising attention to have it addressed by the developers, and it worked.
Improper bounds checking on a stack buffer and data size field during the parsing of NRSessionSearchResult matchmaking data allows an attacker to execute arbitrary code. The stack overflow allows one to overwrite the lower two bytes vftable_ptr of the DLMemoryInputStream object used internally by the stream reader, redirecting execution to carefully chosen neighboring code. Clever exploitation of the DLMemoryInputStream object's structure and data size field then allows one to achieve arbitrary code redirection, with RCX pointing to the address of our packet. From there a series of code redirections via virtual calls with different offsets (which will now jump at whatever addresses we wrote into the packet buffer) can be used to achieve arbitrary code execution.
The distribution vectors are what make this particular RCE particularly serious (beyond already being an RCE). The exploit is transmitted through matchmaking push requests containing NRSessionSearchResult information. This means that the attacker can target anyone who joins their online session. In particular, for DS3:
PushRequestSummonSign)PushRequestAllowBreakInTarget)PushRequestVisit)PushRequestAcceptQuickMatch)This is already pretty bad, but the real potential is unlocked by the RequestSendMessageToPlayers request:
message RequestSendMessageToPlayers {
repeated uint32 player_ids = 1;
required bytes push_message = 2;
}
The host uses this request to directly send the PushRequestAllowBreakInTarget push message to invaders so that they can obtain spawn coordinates and join their P2P session. That's it. That's the only way this request is used by the game.
I cannot stress how horribly unsafe this is. Any player can basically impersonnate the matchmaking server. By using this request to send the exploit through a PushRequestVisit, any online player can be remotely targeted by the attacker as long as their player ID is known. The attacker can also send the exploit to the entire online playerbase very quickly by sending multiple requests, each containing a large slice of possible player IDs.
While the RCE does not port exactly to every game, the core idea of the exploit which gives the attacker arbitrary code redirection is the same. If this can be achieved, it is very likely that a game-specific virtual call chain or ROP chain can then be found. This "first step" uses the following vulnerabilities:
Matchmaking push requests containing session join information store said information in a custom binary format which consists of a chain of length-deliminted data entries. Each entry has the following format:
struct Entry
{
uint32_t type_or_id; // not sure, but probably a type (fixed length = 2, variable length = 1 ?)
uint32_t size;
uint8_t data[size];
}
The game function responsible for copying the data of these entries blindly trusts the size field, which creates an out-of-bounds read. This can be abused by a malicious client by setting the size field to values like 0x7FFFFFFF, causing the memory allocation to fail and the victim's game to crash. Later, this size is also passed to the constructor of a DLMemoryInputSteam, which is an instrumental part of the exploit.