Atmosphere-NX / Atmosphere

Atmosphère is a work-in-progress customized firmware for the Nintendo Switch.
GNU General Public License v2.0
14.34k stars 1.21k forks source link

Implement a generic patching system for Kernel/FIRM sysmodules. #3

Closed SciresM closed 5 years ago

SciresM commented 6 years ago

Decide on a standardized format, and implement in the stage 1 loader. Should be flexible enough to pattern match -- see luma-style stuff.

Is this best done via a custom "loader" system module? Needs design considerations.

Valeri0p commented 6 years ago

Sorry to bother you, probably you already know about this approach, but just in case you need some inspiration/comparison between implementations 😉 Thx for all your work!

majoni71 commented 6 years ago

Hi, how a can help to translate the Text to Portuguese BR, and Italian ? You have a list of the texts for translate?. A want help.

Resaec commented 6 years ago

For the running system with (K)ASLR the simple memsearch from luma won't work sadly. So we also have to agree on a convention for wildcard pattern scanning.

Since its confusing and slow to use "unused instructions" for wildcards 0x00, 0xFF or something along those lines I would suggest to split pattern scanning into a pattern and a mask: {0x12, 0x23, 0x34, 0x45, 0x00, 0x00, 0x00, 0x00, ...} "xxxx????..." Whith x being a character to find and ? or any other character representing a wildcard. With this distinction there won't be any accidental partial or full pattern matches due to overlapping wildcard characters and actual code.

Scanning will take much longer than it did on the 3DS regardless. This is the result of bigger files and the additional execution time introduced by the wildcards.

For static file scanning we could use memmem or memsearch (do i miss something? how is memsearch different from memmem?)

Resaec commented 6 years ago

It is also possible to make the mask binary (uint64_t or (typed) uint128_t, if the pattern gets that long) to save space (1bit <> 8bit) and use fast binary operations to check for wildcards. if(mask & 1 << loop_i)

Selver-gba commented 5 years ago

This is a difficult question to answer, without being clear on the types of patches that require support. At a first level, I second @Valeri0p's suggestion to review yifan lu's CFW framework. For any patching that can be done at the exported API layer, this seems a good starting point.

The pattern matching concept is also likely going to be needed.

The hard part (imho) is making multiple patches that affect the same area work. Even with the above framework, which hook goes "first" is a very hard problem.

A similar problem appears to have been (attempted?) solved for file system filter driver ordering in Windows. At a high level, they define multiple types of filter drivers, with a pre-defined order that they get applied.

Perhaps something similar is appropriate for a patch framework?

SciresM commented 5 years ago

So, for now we've gone with IPS. It's less flexible than pattern-matching, which is still desirable -- however, the current patch system allows for complete user control over the order in which IPS are applied, and since the patches are applied only to those kips which have matching SHA256, there shouldn't be anything doable with pattern matching not doable via IPS.

Resaec commented 5 years ago

Is pattern matching still desired? (EDIT: I didn't read it well... the answer is yes) I finished coding yesterday, but didn't push or PR it as I thought I needed to include a working patching system at the same time. I will push it to my fork in a distinct branch if anyone wants to take a look.

memSearchASLR is using a mask while memSearch is not (GNU memmem())

As kind of a benchmark: The file is generated by reading 1GB from /dev/urandom and xxd'ing at ofset 1,000,000. The pattern is 8 bytes long and alignment is 4 bytes. It looks a little too fast, so my guess is that there is some caching going on. I can not see why memmem should be slower otherwise.

Debian (gcc) (VM)

nxdev@nxdev:~/memtest$ ./test
Malloc took 0.000009s for 1048.576000 MB
File read to memory took 1.159182s to complete
memSearchASLR took 0.414878s and location is 0x3B9ACA00
memSearch took 0.672670s and location is 0x3B9ACA00

Windows (MSVC) - memmem not available

Malloc took 0.002000s for 1048.576000 MB
File read to memory took 1.600000s to complete
memSearchASLR took 0.335000s and location is 0x3B9ACA00
memSearch took 0.000000s and location is 0x0