Tutorial  Updated

Extract and Decrypt games, NAND backups, and SD contents with ninfs

This is a tutorial that shows you how to use ninfs (formerly fuse-3ds) to extract the contents of games, NAND backups, and SD card contents. This tutorial is a work in progress; please post a reply if something is confusing or needs a correction.

This supports Windows, macOS, and Linux. This tutorial mostly focuses on the GUI on Windows. For macOS/Linux steps plus CLI/installable-module usage, see the README and latest release at the repository.

What sets ninfs apart from others like ctrtool is that it doesn't need to decrypt separately first. Instead, files are decrypted as needed. For example, if you mount a CIA, you can see all of the files in it, and you only need to copy out what you need. This makes it much faster and more efficient, especially for larger games where it can take a while (and several gigabytes of space) to decrypt!

Want to see a video demonstration? Here is one with Pokémon Ultra Moon, using fuse-3ds v1.0.
In this short video, I show that the CIA is encrypted, then I use ninfs to mount it and browse its contents in Windows/File Explorer. I can also use the decrypted.cxi file to immediately start playing it in Citra.
(Note that slowness is due to the virtual machine, speed would be faster on a normal computer!)

Getting started

Windows users simply need two things:
  • Install the latest release of WinFsp
  • Download the latest release of ninfs at GitHub or the GBAtemp Download Center
    • You should download the win64 version if you're using 64-bit Windows.
Please see the latest release notes for macOS and Linux (+ alternative steps for Windows).

You also need the ARM9 bootROM. You can use boot9strap to dump it by holding START+SELECT+X at boot, and finding it at /boot9strap/boot9.bin on the SD card. You can find boot9strap setup at 3DS Hacks Guide.

For newer digital games (2015+), you also need a SeedDB. Check out the SeedDB list.

Setting up boot9/SeedDB

You will need boot9.bin or boot9_prot.bin, and seeddb.bin. This will be placed at %APPDATA%\3ds on Windows, and `~/.3ds` on macOS/Linux.

If one of the files could not be found, an error will be displayed.
mainwindow-err-win.png

Both boot9 and SeedDB use similar steps for setup. This part shows boot9 steps, but it is the same for SeedDB.

If you click "Fix boot9", you will see a dialog allowing you to choose the boot9 file, and the searched paths.
b9-missing-win.png

Click "Select boot9 to copy..." then find the boot9.bin or boot9_prot.bin file. If it is valid, it will be copied.
b9-copied-win.png

Using the GUI

Run ninfs (either the exe, or the module if you installed it). A console window will appear, then a GUI a few seconds later.
mainwindow-win.png

First, choose the type that you want at the top:
  • CTR Cart Image (".3ds", ".cci")
  • CDN contents (directory with "cetk", "tmd", and contents)
  • CTR Importable Archive (".cia")
  • Executable Filesystem (".exefs", "exefs.bin")
  • Nintendo 3DS NAND backup ("nand.bin")
    • Using a directory instead of drive letter is highly recommended for this!
    • You need the OTP for this if the NAND backup does not have essential.exefs embedded by GodMode9. If you have essential.exefs as a separate file, you can extract it from that. If the Counter can't be automatically generated, you also need the CID.
    • You can write to the NAND. In the GUI, you need to enable this option. Otherwise, the mount will be read-only.
  • NCCH (".cxi", ".cfa", ".ncch", ".app")
  • Read-only Filesystem (".romfs", "romfs.bin")
  • SD Card Contents ("Nintendo 3DS" from an SD card)
    • You need movable.sed from the system whose SD card contents you want to browse. You can get it from essential.exefs, or by copying it from CTRNAND -> private -> movable.sed.
    • You can write to the SD contents. In the GUI, you need to enable this option. Otherwise, the mount will be read-only.
  • 3DSX Homebrew (".3dsx")
  • Titles directory ("title" from NAND or SD)
    • To browse SD card titles, the contents must be decrypted first. You can use the SD Card Contents mount first to do that, then use this one.
  • Nintendo DSi NAND backup ("nand_dsi.bin")
  • Nintendo DS ROM image (".nds", ".srl")
  • Nintendo Switch NAND backup ("rawnand.bin")
Once you choose the type, you need to choose the file (or directory) that you want to mount. This would be the game, NAND, or "Nintendo 3DS" SD card folder that you want.

Finally, click "Mount". If there are no errors, Windows Explorer/File Explorer will automatically open at the mount. Some example contents are shown below.
ciamount-win.png
ncchmount-win.png
nandmount-win.png
Now you can copy out the files you want.
  • If you mounted CCI, CDN, CIA, NCCH, or Titledir, you can see "decrypted.cxi" (or "decrypted.cfa" for non-executable contents) which acts like a decrypted version of the game. You can use it in applications that require decrypted contents like Citra.
  • For NAND, you can use a tool like OSFMount to mount partitions like CTRNAND, TWLN, and TWLP. Make sure you used directory mount, not drive letter.
    If you enabled writing, you can also write back to the partitions. They will be re-encrypted as you write.
  • For SD, you can browse the decrypted contents, and use something like the titledir mount to browse the installed games. You can also write to it, and the files you write will be re-encrypted.
    You can extract game saves and extdata with a tool like 3ds-save-tool.
Once you are done, click "Unmount". The mount will be removed.

Add to context/right-click menu

You can add "Mount with ninfs" to the context menu when you right-click on files. It will try to automatically detect the file type and show it in the GUI, so you can just click Mount.

Open ninfs, click "Help & Extras", then click "Add to menu". Read the dialog, then click "Add entry" or "Remove entry" to add or remove the context menu entry.

If you move or rename the EXE, you will need to re-add it.

Troubleshooting

  • I am using Windows 7, 8, or 8.1 and am getting "The procedure entry point ucrtbase.terminate could not be located in the dynamic link library api-ms-win-crt-runtime-l1-1-0.dll.".
  • I am on Windows 7 and am getting an error saying the driver is not signed when trying to install WinFsp.
    I am on Windows 7 and am getting "Cannot create WinFsp-FUSE file system: unspecified error."
 
Last edited by ihaveahax,

Kwyjor

Well-Known Member
Member
Joined
May 23, 2018
Messages
4,323
Trophies
1
XP
4,455
Country
Canada
I just thought that the threeSD program decrypted the .sav, then 3ds-save-tool extracted the proper files from the .sav.
If you look again, you will find that the first post in that thread says nothing about 3ds-save-tool.

While you could presumably use the "SD Decryption" function of threeSD to provide decrypted save data that you could extract with 3ds-save-tool, that would be redundant since the "Save Data Extraction" function is right there.
 

Rude_Boy_EEEE

Member
Newcomer
Joined
May 18, 2015
Messages
22
Trophies
0
Age
27
Location
NJ, USA
XP
128
Country
United States
If you look again, you will find that the first post in that thread says nothing about 3ds-save-tool.

While you could presumably use the "SD Decryption" function of threeSD to provide decrypted save data that you could extract with 3ds-save-tool, that would be redundant since the "Save Data Extraction" function is right there.
I've been looking at a lot of threads about this, man. Cut me some slack.

I try the "Save Data Extraction", but I keep getting "An error occurred while performing the operation."
 

Kwyjor

Well-Known Member
Member
Joined
May 23, 2018
Messages
4,323
Trophies
1
XP
4,455
Country
Canada
I try the "Save Data Extraction", but I keep getting "An error occurred while performing the operation."
If you read that thread again, you will find someone who just reported having the same problem and was able to easily overcome it. You only get so much slack, sir. :huh:

Plus, when I use ninfs to "Mount SD Card Content," I use my movable.sed and everything, but it gives me the files from a second id0 in my old Nintendo 3DS directory. I can't figure how it only scans that part, which doesn't have the data I'm trying to reach.
Why not just delete (or move to elsewhere) the redundant id0?
 

Rude_Boy_EEEE

Member
Newcomer
Joined
May 18, 2015
Messages
22
Trophies
0
Age
27
Location
NJ, USA
XP
128
Country
United States
If you read that thread again, you will find someone who just reported having the same problem and was able to easily overcome it. You only get so much slack, sir. :huh:

Why not just delete (or move to elsewhere) the redundant id0?
Okay, I followed what that other guy did, PLUS I was able to re-extract the movable.bin (which I renamed movable.sed) to make sure I'm using the right one (I also backed up my new device's one, so I may have mixed them up). In any event, I now have "00000001.metadata," but I'm unsure what to do with that.

EDIT: Nevermind!! I missed a folder. Thank you for your help, and I'm sorry I missed the answer the first time.
 
Last edited by Rude_Boy_EEEE,

Rude_Boy_EEEE

Member
Newcomer
Joined
May 18, 2015
Messages
22
Trophies
0
Age
27
Location
NJ, USA
XP
128
Country
United States
i found the .sav file via mounting the nintendo 3ds folder, how do i decrypt the save file?
I hope you read the other posts in this thread.

If you've done things correctly, then simply copying a file from the ninfs-mounted folder to anywhere else on your hard drive will automatically decrypt it.
It's true, listen to Kwyjor. From that point, I used 3ds-save-tool to extract the actual files from the .sav file. It took a little Python-learning, though. Then, I imported them using JKSM. And bing, bang, boom—the saves are back!

Edit: Linked the Github to 3ds-save-tool.
 

cryingmantis

New Member
Newbie
Joined
Dec 5, 2023
Messages
1
Trophies
0
Age
22
XP
20
Country
Italy
Hello, I need some help in using this tool.

I am trying to recover my saves from my former and now broken 3DS (of which I just have an SD card backup on my PC and nothing more). I last updated Luma in 2019, if I am correct. I have found the encrypted .sav file that I have to convert into .dat files to move over to my newest system.
The issue is, I have no way of generating the needed boot9 file; but I seem to have found the movable.bin file, although it has some other characters in the front - and if I got it right, I might also retrieve it from my sister's console friendlist. I might also have a nand backup somewhere but I am not completely sure. How do I proceed?

Keep in mind that I just have very basic programming knowledge.
 

Kwyjor

Well-Known Member
Member
Joined
May 23, 2018
Messages
4,323
Trophies
1
XP
4,455
Country
Canada
You should probably consider using threeSD instead of ninfs and 3ds-save-tool, although the end result is the same.
https://gbatemp.net/threads/restore-save-data-from-dead-3ds-2ds.606907/

The issue is, I have no way of generating the needed boot9 file
boot9.bin is the same for all consoles. You can dump it from any 2DS/3DS, or even download it from the Internet if you try hard enough.

ETA:
and if I got it right, I might also retrieve it from my sister's console friendlist.
You can't extract your movable.bin/sed from a different console. You can extract your "lfcs_b", aka "movable_part1", which you can use with your Friend code to brute-force your movable.sed.
 
Last edited by Kwyjor,

SylverReZ

The planet is fine. The people are crazy.
Member
GBAtemp Patron
Joined
Sep 13, 2022
Messages
7,225
Trophies
3
Location
The Wired
Website
m4x1mumrez87.neocities.org
XP
22,149
Country
United Kingdom
This is a thread about 3DS games, so what exactly do you mean by a "DS ROM image", and why do you think it can be mounted? DS ROMs have no encryption.
Its the official thread for "ninfs" (I believe), so what does it matter?

And what have you tried so far?
I've tried mounting to an empty folder on my /home/ directory and even add '*' so that it can auto-mount a virtual drive with any name. Still, I got a bunch of Python errors.
 

SylverReZ

The planet is fine. The people are crazy.
Member
GBAtemp Patron
Joined
Sep 13, 2022
Messages
7,225
Trophies
3
Location
The Wired
Website
m4x1mumrez87.neocities.org
XP
22,149
Country
United Kingdom
Please post the errors.

Code:
Command: ['/usr/bin/python3',
 '/home/emily/.local/lib/python3.10/site-packages/ninfs',
 'srl',
 '/home/emily/Fire_eng_1_45.nds',
 '-f',
 '/home/emily/mountpath']

Traceback (most recent call last):
  File "/usr/lib/python3.10/runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/lib/python3.10/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/home/emily/.local/lib/python3.10/site-packages/ninfs/__main__.py", line 23, in <module>
    exit(mount(argv.pop(1).lower()))
  File "/home/emily/.local/lib/python3.10/site-packages/ninfs/main.py", line 90, in mount
    return module.main(prog=prog)
  File "/home/emily/.local/lib/python3.10/site-packages/ninfs/mount/srl.py", line 286, in main
    mount = SRLMount(srl_fp=f, g_stat=srl_stat)
  File "/home/emily/.local/lib/python3.10/site-packages/ninfs/mount/srl.py", line 109, in __init__
    self.title = header.game_title.decode('ascii').replace('\0', '')
UnicodeDecodeError: 'ascii' codec can't decode byte 0xea in position 3: ordinal not in range(128)

Return code was 1
 

ihaveahax

Well-Known Member
OP
Member
Joined
Apr 20, 2015
Messages
6,070
Trophies
2
XP
7,836
Country
United States
Code:
Command: ['/usr/bin/python3',
 '/home/emily/.local/lib/python3.10/site-packages/ninfs',
 'srl',
 '/home/emily/Fire_eng_1_45.nds',
 '-f',
 '/home/emily/mountpath']

Traceback (most recent call last):
  File "/usr/lib/python3.10/runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/lib/python3.10/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/home/emily/.local/lib/python3.10/site-packages/ninfs/__main__.py", line 23, in <module>
    exit(mount(argv.pop(1).lower()))
  File "/home/emily/.local/lib/python3.10/site-packages/ninfs/main.py", line 90, in mount
    return module.main(prog=prog)
  File "/home/emily/.local/lib/python3.10/site-packages/ninfs/mount/srl.py", line 286, in main
    mount = SRLMount(srl_fp=f, g_stat=srl_stat)
  File "/home/emily/.local/lib/python3.10/site-packages/ninfs/mount/srl.py", line 109, in __init__
    self.title = header.game_title.decode('ascii').replace('\0', '')
UnicodeDecodeError: 'ascii' codec can't decode byte 0xea in position 3: ordinal not in range(128)

Return code was 1
This suggests the rom is corrupted because it can't decode a piece of text in the header. Or is it one that does work?
 

SylverReZ

The planet is fine. The people are crazy.
Member
GBAtemp Patron
Joined
Sep 13, 2022
Messages
7,225
Trophies
3
Location
The Wired
Website
m4x1mumrez87.neocities.org
XP
22,149
Country
United Kingdom
This suggests the rom is corrupted because it can't decode a piece of text in the header. Or is it one that does work?
Its a homebrew compiled app. So, I'm not 100% sure if its compatible or not.
 

Kwyjor

Well-Known Member
Member
Joined
May 23, 2018
Messages
4,323
Trophies
1
XP
4,455
Country
Canada
Its the official thread for "ninfs" (I believe), so what does it matter?
I suppose the first post does indicate that it can handle DS ROM images, but I've never heard of anyone using ninfs for that before. It seems to me there are other much more convenient tools for that. Tinke or The Unarchiver, perhaps.

Its a homebrew compiled app. So, I'm not 100% sure if its compatible or not.
Why not try it with an official ROM that is more likely to compatible, then? See if that works?
 

SylverReZ

The planet is fine. The people are crazy.
Member
GBAtemp Patron
Joined
Sep 13, 2022
Messages
7,225
Trophies
3
Location
The Wired
Website
m4x1mumrez87.neocities.org
XP
22,149
Country
United Kingdom

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
    K3Nv2 @ K3Nv2: https://youtube.com/shorts/9seCZUSS8zE?si=xMNkLYWrWl6kDH44