Skip to content

Instantly share code, notes, and snippets.

@roblabla
Last active April 3, 2019 05:58
Show Gist options
  • Save roblabla/440f3ceaa0b2d3ca530c2a43fe258420 to your computer and use it in GitHub Desktop.
Save roblabla/440f3ceaa0b2d3ca530c2a43fe258420 to your computer and use it in GitHub Desktop.
Kernel Patches

This is a small repository that aims to document some fun kernel patches I have come up with while reverse engineering the kernel. They're meant to be useful for debugging various things.

You can easily apply those patches by getting the appropriate Kernel.bin, and applying them in a hex editor. The format is: offset origvalue => newvalue offset. They are made with radiff2. (If anyone knows of a better way to create binary patches, I'd love to hear it). Another way to test those patches is to use Hekate, which recently got kernel patching support (https://github.com/nwert/hekate/blob/master/ipl/pkg1.c#L71, thanks @CTCaer ^^)

I try to document what each patch does. If something is missing or wrong, feel free to leave a comment!

Have fun!

This patch is implemented in Hekate under debugmode.

When the kernel boots, it asks the SecureMonitor if the device is in debug mode, by calling SMC #1 0xC3000004 (GetConfig) with ConfigItem 11 (IsDebugMode). It then stores the result in a global variable.

That variable will then determine access to syscalls:

  • svcBreakDebugProcess
  • svcContinueDebugEvent
  • svcReadDebugProcessMemory (on 1.0.0, 2.0.0+ don't need isDebugMode)
  • svcWriteDebugProcessMemory
  • svcSetDebugThreadContext
  • svcTerminateDebugProcess
  • svcSetHardwareBreakPoint

It also enables other features such as userland exception handling (which are kind-of-like Unix Signals).

The following kernel patches allow your retail switch to get into debug-mode, by forcing that global variable to be set to 1.

- 1.0.0         0x00044074 e80340f9 => 280080d2 0x00044074
- 2.0.0-2.3.0   0x0006086c e80340f9 => 280080d2 0x0006086c
- 3.0.0-3.0.1   0x000483fc e80340f9 => 280080d2 0x000483fc
- 3.0.2         0x00048414 e80340f9 => 280080d2 0x00048414
- 4.0.0-4.1.0   0x0004ebfc e80340f9 => 280080d2 0x0004ebfc
- 5.0.0-5.1.0   0x0005513c e80340f9 => 280080d2 0x0005513c

This patch is implemented in hekate under fullsvcperm.

When an application tries to access a certain syscall, the kernel will first check a bitmask (set at process creation time) to make sure that the process has the right to call it. Now, with nspwn and custom loaders and stuff, we can just give ourselves arbitrary svc permissions. But wouldn't it be nice if we could just disable the permission check entirely ?

Well, there we go:

- 1.0.0         0x0003764c e0020054 => 1f2003d5 0x0003764c
- 2.0.0-2.3.0   0x00054834 e0020054 => 1f2003d5 0x00054834
- 3.0.0-3.0.1   0x0003bd24 e0020054 => 1f2003d5 0x0003bd24
- 3.0.2         0x0003bd24 e0020054 => 1f2003d5 0x0003bd24
- 4.0.0-4.1.0   0x00041eb4 e0020054 => 1f2003d5 0x00041eb4
- 5.0.0-5.1.0   0x0004556c 00030054 => 1f2003d5 0x0004556c

See CTCaer/hekate#182 for an implementation of this patch in hekate.

The switch has an awesome syscall: svcOutputDebugString(char*, size_t). As the name implies, it's supposed to take a string and print it out somewhere for logging/debugging purposes. Unfortunately, on the official switch firmware, it does nothing (Nintendo isn't nice like that).

Turns out, printing debug information from the kernel is a bit of a challenge. There aren't a whole lot of peripherals we can use without interfering with the normal switch operations. USB is complicated, drawing on the screen would make it unusable for graphic apps, TCP isn't viable... Fortunately, there was some code left in the kernel that allows printing things over UART. And the switch uses the UART to communicate to JoyCons, which can easily be both soft and hard-modded... Thus a plan was born.

We're going to print the svcOutputDebugString on UART-B. Then, we'll hardmod a joycon rail with a 1.8v TTL-to-USB device, in order to transmit that data back to a computer.

TODO: It should be possible to transmit data back to a computer without hard-modding, but instead by soft-modding the joycon firmware. This would be super nice.

For the sake of simplicity, the patches will be given as radare2 commands for this one. This patch is in three parts:

  • First, let's fix up the kernel printk to print over UART-B instead of UART-A. This is because UART-B is the right joycon UART, while UART-A is just an internal debug UART that isn't connected to anything.

    - 1.0.0     wx 8c0a90f2 @ 0x00003ad4
    
  • Then, we'll want to write some glue code to wire our svc to the printk function:

    - 1.0.0     wx 252e2a73 @ 0x0004797c
                wx e20300aae0ffffd2e0ffdff280f8b7f2802f8bf2fd7bbfa986f0fe97000080d2fd7bc1a8c0035fd6 @ 0x00047984
    
  • And finally, let's call that glue code in svcOutputDebugString:

    - 1.0.0     wx 08730094 @ 0x0002ad64
    

You should now be able to listen in on the UART from a modded joycon rail and a ttl-to-usb cable (make sure you get one that supports 1.8 voltage).

@AcK77
Copy link

AcK77 commented May 27, 2018

DisableSvcVerif: - 3.0.0 0x0003bd24 e0020054 => 1f2003d5 0x0003bd24

@CTCaer
Copy link

CTCaer commented May 30, 2018

EnableDebugPatch:

- 2.0.0-2.3.0   0x0006086c e80340f9 => 280080d2 0x0006086c
- 3.0.1-3.0.2   0x000483fc e80340f9 => 280080d2 0x000483fc
- 4.0.0-4.1.0   0x0004ebfc e80340f9 => 280080d2 0x0004ebfc // It's 2800'80'd2, not 2800'08'd2.

@CTCaer
Copy link

CTCaer commented May 30, 2018

DisableSvcVerif:

- 2.0.0-2.3.0   0x00054834 e0020054 => 1f2003d5 0x00054834
- 3.0.1-3.0.2   0x0003bd24 e0020054 => 1f2003d5 0x0003bd24
- 4.0.0-4.1.0   0x00041EB4 e0020054 => 1f2003d5 0x00041EB4

In 5.0.X this changed completely.

@roblabla
Copy link
Author

roblabla commented Jun 1, 2018

Thanks a lot guys, you rock!

@pplatoon
Copy link

pplatoon commented Apr 3, 2019

incredible instead of going to the mountain that the mountain comes to me, take advantage of the console send information instead of sending it to the console because nintendo is not stupid. this would be like pegaswitch by hard =? you do an incredible research job

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment