# RCE on Steam Client via buffer overflow in Server Info

Stack buffer overflow in Steam client's server browser A2S_PLAYER player-name handling allows unicode ROP chain to execute arbitrary code on Windows.

- Payout: hidden
- Severity: critical
- Program: Valve
- Found by: vinnievan
- Disclosed: 2019-03-15
- Write-up quality: 9/10
- Original: https://hackerone.com/reports/470520
- Library page: https://bugbountylibrary.com/r/h1%3A470520
- Tags: area:os domain:desktop impact:rce kind:bounty platform:hackerone sev:critical tech:windows technique:chained technique:fuzzing technique:source-review vuln:memory-corruption vuln:rce

**Target:** Steam.exe server browser (A2S_PLAYER UDP response parsing)
**Root cause:** Player name from A2S_PLAYER response is converted to wide-char unicode without bounds checking, overflowing a stack buffer in the serverbrowser library; no stack canary present on Windows.
**Steps:**
1. Implement a UDP server speaking the Server Queries protocol (A2S_INFO/A2S_PLAYER).
2. Reply to A2S_PLAYER with a player name of `A*1100` to observe crash; unicode `u"\u4141"*1100` yields `0x41414141` on stack.
3. Attach debugger, note EIP control and no canary; satisfy pre-return dereference of edi using constant values present on the Steam.exe binary.
4. Build unicode-safe ROP chain from Steam.exe gadgets to call VirtualProtect and jump to unicode shellcode spawning cmd.exe.
5. Set STEAM_BASE to leaked base for 100% reliability; serve payload and trigger via server browser 'View server info' or `steam://connect/1.2.3.4` in an iframe.
**How found:** Implemented the documented Server Queries protocol in Python, fuzzed parameters, noticed client crash on large player name in A2S_PLAYER response; debugger showed stack buffer overflow in serverbrowser library during unicode conversion with no canary.
**Exploitation:** Attacker hosts malicious UDP game server; victim views server info (manually or via steam:// protocol from a webpage/iframe). Crafted A2S_PLAYER name overflows stack, unicode ROP calls VirtualProtect to make stack executable, then shellcode runs cmd.exe. Only 9 bits are randomized, giving 0.2% (1/512) success per attempt, or chain with a memory leak for 100%.
**Escalation:** Mass distribution to all Steam users yields one victim per ~512 attempts; can chain with memory leak for reliable exploitation; shellcode can open C2 backdoor for account takeover, item theft, malware install.
**Insight:** Game server browser UDP query parsers (A2S_*) are attack surface reachable from a webpage via steam:// protocol; unicode conversion of attacker strings can bypass naive length checks and enable unicode-safe ROP when no canary exists.

## Proof of concept (copied exactly from the original report)

**Malicious A2S_PLAYER reply with overflow payload**

```
def createPLAYERReply():
    # A2S_player response
    # This query retrieves information about the players currently on the server.
    pre = "\xFF\xFF\xFF\xFF"                        # Pre (4 bytes)
    header = "\x44"                                 # Header (1 byte)
    players = "\x01"                                # Amount of players (1 byte)
    indexPlayer1 = "\x01"                           # Index of player (1 byte)

    namePlayer2 = pwn()
    scorePlayer2 = ""
    durationPlayer2  = ""
    return pre + header + players + indexPlayer1 + namePlayer2 + scorePlayer2 + durationPlayer2
```

**Payload construction with special conditions and ROP**

```
payload = "A"*1024 + u"\ub33f\ubeef"*12 + special_condition_1 + special_condition_2*31 + rop + shellcode
    return payload.encode("utf-8") + "\x00"
```

