This is a draft document. Expect the process to change as I get more familiar.
Things you need:
- dumped romfs & exefs
-
Ghidra with the nintendo switch loader plugin
- make sure the versions match: at time of posting the latest release of Ghidra is 10.2.3, but the latest release of SwitchLoader is only compatible with Ghidra 10.2.2 (or you can build from source)
- il2cppdumper
- switch-tools (compiled version here)
- python 3
- HxD
Setting up Ghidra:
- Copy
exefs/main
androms/managed/metadata/global-metadata.dat
into the il2cpp folder and run il2cppdumper.exe. This will create anil2cpp/output
folder.- Next run
il2cpp_header_to_ghidra.py
. This will give youil2cpp/il2cpp_ghidra.h
- Next run
- Open Ghidra
-
File > Install Extensions and install the SwitchLoader extension.
-
Create a new project, and File>Import File selecting
exefs/main
(i tend to rename the ProgramName to the title update version number e.g. main1.2 as of current writing)
-
Once imported, let it run analysis with the default options (takes a while)
-
- Window > Script Manager and create a new script (type: Python). Name it whatever. When the text input window appears, copy and paste in the contents of
il2cpp/ghidra_with_struct.py
. - Save and run the script. When prompted, select
il2cpp/output/script.json
. - File > Parse C Source and add a new source file to parse. When prompted select
il2cpp/il2cpp_ghidra.h
that we created previously. Click ‘Parse to Program’.
You can now start looking through the code for interesting functions.
Making edits:
Let’s make it so items don’t consume uses. The function we’re after is App.UnitItem$$Expend which can be found in the Symbol Tree.
The address (in v1.2) is 0x7102408f60. We want to change the code here to never expend an item. Below we can see that it does some checks and branches based on the number of uses. We can nop
the branch to ensure it always returns 0 without expending a use.
First, using the switch tools you can use decompress.cmd to turn main
into main.elf
.
Using HxD you can make edits to main.elf
. To find the address in HxD we first subtract the 0x7100000000 offset, giving us 0x2408f74. Then we add 0x908 header giving us 0x240987c. I use https://armconverter.com/ to turn assembly into hex - Switch uses ARM64:
Copy and paste the hex into HxD, using CTRL+B instead of CTRL+V so that it doesn’t alter the file size.
Then you can run compress.cmd to get main.nso
. Copy this into your mod’s exefs folder and rename it to main
(no extension). You should now be able to try it in game.
Coming soon: advanced il2cpp reverse engineering (?)