# [3DS][StreetPass] Buffer Overflow in Super Mario Maker level decompression

Super Mario Maker's StreetPass level decompressor fails to check compressed chunk size, letting a crafted level overflow the heap and achieve userland RCE.

- Payout: hidden
- Severity: none
- Program: Nintendo
- Found by: mrnbayoh
- Disclosed: 2021-04-20
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/687887
- Library page: https://bugbountylibrary.com/r/h1%3A687887
- Tags: area:devices domain:iot impact:rce kind:bounty platform:hackerone technique:reverse-engineering vuln:memory-corruption

**Target:** StreetPass level decompression in Super Mario Maker (3DS)
**Root cause:** The decompressor does not validate the declared compressed chunk size against the 0x18000-byte received buffer, so it parses past the compressed buffer into the adjacent decompressed buffer and copies data beyond its end.
**Steps:**
1. Decrypt StreetPass communications using dumped bootroms.
2. Craft a level file whose first chunk is 0x18000 bytes long.
3. Decompressed output is copied to `compressed_buf+0x18000`, adjacent to the compressed buffer.
4. Because size is unchecked, content at `compressed_buf+0x18000` is parsed as the next compressed chunk.
5. That chunk is copied past the end of the decompressed buffer, overwriting heap objects.
6. Groom heap objects to gain userland code execution.
**How found:** Researcher noted bootrom dumps enable decrypting StreetPass traffic, then analyzed the level decompression routine and observed the chunk size is never validated against the 0x18000-byte receive limit, with the decompressed buffer placed directly after the compressed buffer.
**Exploitation:** Attacker sends a crafted StreetPass level; the unchecked chunk size causes the decompressor to treat the adjacent decompressed buffer as input and copy past its end, overwriting heap objects to hijack control flow for userland RCE.
**Insight:** When a fixed-size receive buffer sits adjacent to its own output buffer, an unchecked length field lets the parser consume its own output as input, turning a read-past-end into a controlled heap overflow.

