ROhan is an exploit to enable userland arbitrary code execution on Switch OS 3.0. It works due to Nintendo’s code making a number of assumptions that don’t hold when sm:h is in play:
- With OS 3.0.0, Nintendo split the ldr:ro service away from the ldr sysmodule, in an attempt to limit the attack surface of the critical ldr.
- The newly-created RO sysmodule contains a codepath meant to ease testing for use on devkits: when loading in NRR files (which validate the integrity of NRO “dlls”), the module will contact the spl: service to check the IsDebugMode flag, and contact the settings sysmodule to request the ro!ease_nro_restriction setting. If both of these are set, the signature check is skipped.
Both of these changes mark theoretical improvements to the system’s security. However, sm:h grants full access to the services API – including both registering and unregistering existing services. As such, the exploit flow looks like this:
- Set the ro!ease_nro_restriction setting to 1
- Using a compromised sysmodule (more on this later), MITM the spl: service to cause any GetConfig call of type 0xb (IsDebugMode) to return 1
- Kill and relaunch rohan
- Load any unsigned nrr
- Load any nro whose hash exists in that nrr
The reason we need a compromised sysmodule is that the ReplyAndReceive syscall, required to imitate a service, simply doesn’t exist in the browser. As such, we hijack an existing sysmodule to perform this attack.
In 3.0, the sdb sysmodule contains a number of bugs that make it a prime target. We currently have an arbitrary write and control of the execution flow; what we don’t have is an actual ROP/JOP-chain to allow arbitrary function calling. This is the sole piece missing for userland ACE on the Switch.