This page lists vulnerabilities / exploits for 3DS applications and applets. Exploiting these initially results in ROP, from that ROP one can then for example try exploiting system flaw(s).

Non-system applications

Application name Summary Description Fixed in app/system version Last app/system version this flaw was checked for Timeframe info related to this was added to wiki Timeframe this vuln was discovered Vuln discovered by
Cubic Ninja Map-data stack smash See here regarding Ninjhax. None App: Initial version. System: 10.4.0-29. Ninjhax release July 2014 smea
The Legend of Zelda: Ocarina of Time 3D UTF-16 name string buffer overflow via unchecked u8 length field The u8 at offset 0x2C in the savefile is the character-length of the UTF-16 string at offset 0x1C. When copying this string, it's essentially a memory-copy with lenval*2, not a string-copy. This can be used to trigger buffer overflows at various locations depending on the string length.
  • When value is >=0x6E it crashes when saving the saveslot, this causes a stack-smash however it normally crashes before it returns from the function which had the stack-frame overwritten.
  • With value >=0x9A, it crashes via stack-smash in-game once any dialogs are opened(touching buttons on the touch-screen can trigger it too).
  • Length value>=0xCD causes a crash while loading the saveslot, via a heap buffer overflow. This buf-overflow overwrites a heap memchunk following the allocated buffer. When the first 16-bits overwriting that heap memchunk is not the memchunk magic-number(0x7373), the mem-alloc code will just return a NULL ptr which later results in a crash. When the magic-number is valid, the mem-alloc code will continue to attempt to parse the memchunk, which may crash depending on the data which overwrote the memchunk. This heap code is separate from the CTRSDK heap code. Exploiting this doesn't seem to be possible: since the heap code actually verifies that the magic-number for the next/prev memchunk ptrs are correct(unlike CTRSDK), it's not possible to change those ptrs to useful arbitrary addresses outside of savedata(like with triggering a write to a c++ object ptr which later is used with a vtable func-call, this is what one would do with CTRSDK heap here).

On March 11, 2015, an exploit using this vuln was released, that one was intended for warez/etc. The following exploit wasn't released before then mainly because doing so would (presumably) result in the vuln being fixed. The following old exploit was released on March 14, 2015: [1].

None App: Initial version. System: 10.6.0-31. March 11, 2015 Around October 22, 2012 Yellows8
Super Smash Bros 3DS Buffer overflow in local-multiplayer beacon handling. See here. None See here. System: 10.3.0-28. Time of exploit release. See here. Yellows8

Useless crashes / applications which were fuzzed

  • Pushmo (3DSWare), QR codes: level name is properly limited to 16 characters, game doesn't crash with a longer name. The only possible crashes are triggered by out-of-bounds array index values, these crashes are not exploitable due to the index value being 8bit.
  • Pyramids (3DSWare), QR codes: no strings. Only crashes are from out-of-bounds values (like background ID) and are not exploitable.
  • "The Legend of Zelda: A Link Between Worlds" and "The Legend of Zelda: Tri Force Heroes": these games don't crash at all when the entire save-file(minus constant header data) is overwritten with /dev/random output / 0xFF-bytes. All of the CRC32s were updated for this of course.
  • Disney Infinity crashes when all savedata overwritten with /dev/urandom. No checksums. 0xFF bytes don't cause a crash.

System applications

Summary Description Fixed in version Last version this flaw was checked for Timeframe this was discovered Discovered by
3DS System Settings DS profile string stack-smash Too long or corrupted strings (01Ah 2 Nickname length in characters 050h 2 Message length in characters) in the NVRAM DS user settings (System Settings->Other Settings->Profile->Nintendo DS Profile) cause it to crash in 3DS-mode due to a stack-smash. The DSi is not vulnerable to this, DSi launcher(menu) and DSi System Settings will reset the NVRAM user-settings if the length field values are too long(same result as when the CRCs are invalid). TWL_FIRM also resets the NVRAM user-settings when the string-length(s) are too long. 7.0.0-13 7.0.0-13 2012 Ichfly

System applets

Summary Description Fixed in version Last version this flaw was checked for Timeframe info related to this was added to wiki Timeframe this was discovered Discovered by
Home Menu NAND-savedata Launcher.dat icons The homemenu code processing the titleid list @ launcherdat+8 copies those titleIDs to another buffer, where the offset relative to that buffer is calculated using the corresponding s8/s16 entries. Those two values are not range checked at all. Hence, one can use this to write u64(s) with arbitrary values to before/after this allocated output buffer. See here regarding Launcher.dat structure.

This can be exploited(with Launcher.dat loading at startup at least) by using a s16 for the icon entry with value 0xFFEC(-20)(and perhaps more icons with similar s16 values to write multiple u64s). The result is that the u64 value is written to outbuf-0xA0, which overwrites object+0(vtable) and object+4(doesn't matter here) for an object that gets used a bit after the vulnerable function triggers. The low 32bits of the u64 can then be set to the address of controlled memory(either outbuf in regular heap or the entire launcherdat buffer in linearmem), for use as a fake vtable in order to get control of PC. From there one can begin ROP via vtable funcptrs to do a stack-pivot(r4=objectaddr at the time the above object gets used).

Originally this vuln could only be triggered via Launcher.dat at Home Menu startup, right after Launcher.dat gets loaded + memory gets allocated, once the file-format version code is finished running. Starting with v9.6 this can be triggered when loading layouts from SD extdata as well. The vuln itself triggers before the layout data is written to Launcher.dat, but it doesn't seem to be possible to overwrite anything which actually gets used before the function which writes Launcher.dat into the layout gets called.

Home Menu has some sort of fail-safe system(or at least on v9.7) when Home Menu crashes due to Launcher.dat(this also applies for other things with Home Menu): after crashing once, Home Menu resets Launcher.dat to a state where it no longer crashes anymore. However, note that any exploits using this which hang/etc without crashing will still brick the system. Hence, attempting anything with this on physnand without hw-nand-access isn't really recommended.

None 10.3.0-X May 14, 2015 Yellows8
Home Menu theme-data decompression buffer overflow (themehax) The only func-call size parameter used by the theme decompression function is one for the compressed size, none for the decompressed size. The decompressed-size value from the LZ header is used by this function to check when to stop decompressing, but this function itself has nothing to verify the decompressed_size with. The code calling this function does not check or even use the decompressed size from the header either.

This function is separate from the rest of the Home Menu code: the function used for decompressing themes is *only* used for decompressing themes, nothing else. There's a separate decompression function in Home Menu used for decompressing everything else.

That other decompression function in Home Menu handles decompression size properly(decompressed size check for max buffer size is done by code calling the other function, not in the function itself). Unlike the other function, the theme function supports multiple LZ algorithms, but the one which actually gets used in official themes is the same one supported by the other function anyway.

See also here.

With 10.2.0-X Home Menu, the only code change was that the following was added right after theme-load and before actual decompression: "if(<get_lzheader_decompressed_size>(compressed_buf) > 0x150000)<exit>;". This fixed the vuln.

10.2.0-X 10.2.0-X December 22, 2014 Yellows8, Myria independently (~spring 2015)
Home Menu shuffle body-data buffer overflow (shufflehax) See here. 10.6.0-X 10.6.0-X January 3, 2015 Yellows8
Webkit/web-browser bugs spider has had at least three different code-execution exploits. Majority of them are use-after-free issues. See also here. 2013? A lot of people.
Old3DS/New3DS Browser-version-check bypass When the browser-version-check code runs where the savedata for it was never initialized(such as when the user used the "Initialize savedata" option), it will use base_timestamp=0 instead of the timestamp loaded from savedata. This is then used with "if(cur_timestamp - base_timestamp >= <24h timestamp>){Run browser-version-check HTTPS request code}".

Hence, if the savedata was just initialized, and if the system datetime is set to before January 2, 2000, the browser-version-check will be skipped. This includes January 1, 2000, 00:00, because that's the epoch(timestamp value 0x0) used with this timestamp.

See here for bypass usage instructions.

This was fixed with 10.7.0-32, see here for details.

10.7.0-32 February 25, 2016 November 2, 2015 (Exactly one week after the browser version pages were initially updated server-side) Yellows8

Useless crashes

Old3DS system web-browser:

  • 2^32 characters long string(finally fixed with v10.6): this is similar to the vulnerability fixed here, concat-large-strings-crash2.html triggers a crash which is about the same as the one triggered by a 2^32 string. Most of the time this vulnerability will cause a memory page permissions fault, since the WebKit code attempts to copy the string text data to the output buffer located in read-only CRO heap memory. The only difference between a crash triggered by a 2^32 string and the concat-large-strings-crash2.html crash is at the former copies the string data using the original string length(like 1 text character for "x", 4 for "xxxx") while the latter attempts to copy >12MB. In some very rare cases a thread separate from the string data-copy thread will crash, this might be exploitable. However, this is mostly useless since it rarely crashes this way.
  • Trying to directly load a page via the browser "URL" option with webkitdebug setup, causes a crash to trigger in oss.cro due to an use-after-free being caught with webkitdebug. This is presumably some sort of realloc() issue in the libcurl version used by the <={v10.2-v10.3} browser. This happens with *every* *single* *page* one tries to load via the "URL" option, but not when loading links on the current page, hence this is probably useless. A different use-after-free with realloc triggers with loading any page at all regardless of method too(libcurl probably).
  • This WebKit build has a lot of crash-trigger bugs that only happen with webkitdebug completely setup(addr accesses near 0x0), with just trying to load any page at all.