Resources

People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!

Achieving Remote Code Execution in Steam: a journey into the Remote Play protocol- 1314

ThaliumPosted 2 Years Ago
  • Steam remote play is a peer-to-peer system for playing video. The author of this video reverse engineered the protocol to understand how it worked, build a fuzzer and find fun vulnerabilities in it.
  • The remote play protocol was mostly using protobufs. Luckily for the author, many of this information was kept in a Github repo. There are various ways to perform networking, from webRTC to UDP but the author choose to use UDP because of its simplicity. For more details on how the protocol works, with headers, authentication, channels and things, read the post.
  • To interact with the project, the author built their own client and server implementation. An initial issue they ran into was that the session info for the session would have already been derived. They used a x32dbg script to automatically inject the key into the running process then use it on their client. Another issue they had was forcing the client to use the UDP connections. By changing advertising parameters to ONLY include this, the server would always choose UDP.
  • With a client and fuzzer built, the author setup a fuzzer. Since this uses protobuf, the fuzzer had to be grammer aware, which they created their own engine for. For strings, they added in weird things like paths, URLs, XML and more. For integers, they added in interesting sizes like powers of 2, negative numbers and more. They even randomly dropped random optional fields.
  • Some of the connection types were stateless while others were stateful. Because of this, they built a replay system and logging system to see what was going on. Additionally, a scenario system to test various stateful actions to interact with the system or reproduce bugs. One issue I've had with stateful fuzzing in the past is reproducing issues. It would require saving all previous inputs in order to be confident that we had the information to reproduce the issues.
  • With all of this built, they found a bunch of vulns! With fuzzing, crashes are nice and expected. However, looking for side effects is equally important for finding bugs; not all bugs are binary issues that lead to a crash. The first bug was a simple directory traversal, found by the fuzzer, that could be used to overwrite a Steam DLL to get code execution.
  • From there, they found a ton of format string issues but without %n available. Crazily enough, these were in parts of the system, like logging, that made it possible to use this as a leak. So, an attacker could steal arbitrary data from the heap and/or break ASLR on the system.
  • When calling CRemotePlayTogetherGroupUpdateMsg, there was an SSRF issue if JSON was not returned. By specifying a URL with a GET request, arbitrary data on the network could be leaked. Besides this, a few OOB reads and writes were found in player structs, audio encoding. One of the leaks allowed them to remotely read all heap data from the process, which is super cool.
  • Good read! The bugs are fun but the setup of the fuzzer and thought put into making the system testable was the most valuable thing to me. The SSRF issue which only leaked data if the data wasn't JSON was a good instance of fuzzing for bugs without memory corruption being the only goal. This requires you to be more active but will pay off in complicated systems like this one.