This is a continuation of post #135 found here. If you are unfamiliar about this script, please read the previous post before proceeding.
For version 2.0 of Inject and Restore Apps, these updates warrant a dedicated post explaining in detail the benefits, drawbacks, and mechanics behind this revamped script. The script can be downloaded here.
This script now includes:
- Safety checks to prevent injecting CIA files that are DSiWare, Updates, DLC’s, eShop demos, and too big in size
- “Stealth” injection to better hide injected titles from Nintendo’s detection
- Splash screen choice option
As usual, I’ll try to Q&A the role of the skeptical user who insists on grilling me.
Safety checks? Pfff. Who do you think I am?
Someone who deserves some peace of mind. Don’t take what I wrote next the wrong way as I’m not calling into question anyone’s intelligence. If a script (or program) allows you to do something you shouldn’t or didn’t intend to do in the first place, that makes it a bad script, and the blame solely rests on the person who coded it.
With that in mind, this script was created from the onset with as much idiot proofing as possible, but that doesn’t cover the flip side of those safety checks. There is one factor neither you (as the script user) nor I (as the programmer) can ever fully account for: nefarious CIA malware intended to corrupt your 3DS system titles. In the case of CIA files, this is as simple as renaming a file as Game A.cia to Game B.cia . Sounds harmless? Not really.
In the very unlikely but possible scenario that you unsuspectedly download/receive a fake or bad CIA file from somewhere or someone who wishes to harm your prized possession, those safety checks listed above should foil the most basic entries of causing injection mayhem.
System app injection is no joke. Just because something is named with a .cia extension and is image mountable by GodMode9 does not necessarily mean the file in question is injectable or safe to inject to begin with. It basically boils down to this: garbage in, garbage out.
This is probably going off topic from the stated question, but I feel it’s important to mention this.
GM9 scripting has its limitations. This script can’t account for every conceivable bad or harmful injection cases, like seemingly legitimately CIA homebrew re-coded to wreck havoc once installed on your 3DS and that can pass those above sniff tests. As the end user, it is your responsibility to download CIA titles from reputable and trustworthy sources.
And if you don’t believe 3DS malware is a thing, here is the tragic and cautionary tale of the once prodigious dev best known for creating Themely, Erman and his fall from grace in the UnbanMii debacle.
… Bro, you scare me. This inject app script biz sounds bad.
You have every reason to be concern with whichever homebrew you use on your 3DS/2DS. My job here is to help assuage this and answer to the best of my abilities those concerns regarding this script.
The Inject and Restore Apps script is geared towards those who are hitting their 300 titles limit and are looking to utilize homebrew titles in place of those 10 listed Nintendo sys apps. With the “stealth” injection method that’ll later be covered below this post, this type of injection may prove useful for those who favor quickly launching a select few homebrews straight from HOME Menu instead of first booting into Homebrew Launcher.
While there’s nothing technically stopping you from deleting those Nintendo titles using GodMode9 or FBI to free up title count, it has been mentioned elsewhere on this forum that Nintendo is able to detect when those sys apps are missing. Should you connect online with deleted system titles, you can get hit with a ban. The same rule applies for installing CIA homebrews straight onto HOME Menu.
This script allows you to put those “wasted” titles to good use but only if it has determined your shoe-in homebrew titles are deemed safe for injection.
Here are the reasons why certain CIA types cannot or should not be injected:
One other noteworthy safety check is that the script does not attempt injection for missing system titles deleted off the 3DS.
- Fake CIA (renamed from any file) – a real .cia file contains at minimum one .app file (your game). If that’s not present, there’s nothing injectable to begin with. It would be amazing if this could inject Switch ROM dumps, but renaming something like LoZ - BotW.iso to LoZ - BotW.cia doesn’t change the fact it’s not real and won’t work on the 3DS.
- Fake CIA (GM9 image mountable, renamed) – 3DS related files like .app, .3ds, .3dsx, etc. can be renamed with the wrong extension moniker. Again, this goes back to reason #1.
- Real but corrupted CIA (not intact) – If GM9 can’t read it, this is just as bad as reason #1.
- DSiWare – DSiWare CIAs are structured differently than typical CIA dumped from .3ds/.3dsx . Perhaps a DSiWare version of this script is in order for later development if this type of injection can be extended and is determined feasible. Maybe NTR Launcher “stealth” injected into Zelda Four Swords?
- Updates & DLCs – These are accessory or appendages to whichever titles they belong to. While some are very similar file structure wise when compared to complete CIA titles, launching them at HOME Menu will throw an exception.
- eShop demos – Officially released 3DS titles are injectable but (universally?) incompatible when launched from HOME Menu. In case this incompatibility bug is ever fixed, eShop demos were thrown in because I’m democist. I hate getting teased. Stick to the full copy versions.
- CIAs with .app larger than 16 MB – Most homebrews come nowhere near 16 MB. The largest Nintendo sys app is StreetPass Mii Plaza at 15.3 MB for 00000021.app. Your 3DS internal NAND has a capacity of 1 GB. Approximately 600 MB of that NAND is used to house your 3DS operating system. The rest goes to your DSiWare library, photos, game notes, etc. You wouldn’t want to accidentally inject a CIA that is 3.76 GB onto 400 MB, right?
You’re not the boss of me. What if I have this killer CIA homebrew I want to inject, but it’s bigger than 16 MB? What then, huh!?
There are two ways to overcome this script’s size safety limiter. The permanent method is to open the script in Notepad, and edit the values for these variables from the beginning.
CIA_SIZE_LIMIT is the byte size of the largest allowable injection written in hex number.
- 1 MB (megabyte) equals 10242 bytes.
- 10242 is equal to 1,048,576
- Add +1 byte to have the limiter triggered for anything over exactly 1 MB.
- 1,048,577 in decimal is equal to 0x100001 in hex.
- The 0x is not written in the CIA_SIZE_LIMIT input value. This notation is for denoting it’s a hex number.
- The CIA_SIZE_NUMBER variable is for error messaging purpose.
Set CIA_SIZE_LIMIT “100001”
Set CIA_SIZE_NUMBER “1 MB”
To obtain your converted hex number, you use a decimal to hex converter.
So the formula is: ( # of MB ) x 1024 x 1024 + 1 = decimal numbers
Convert the decimal numbers to hex numbers using the calculator like the one above.
Here are some other provided values for raising the limiter if you’re not comfortable calculating the hex numbers.
Set CIA_SIZE_LIMIT “2000001”
Set CIA_SIZE_NUMBER “32 MB”
Set CIA_SIZE_LIMIT “4000001”
Set CIA_SIZE_NUMBER “64 MB”
Set CIA_SIZE_LIMIT “8000001”
Set CIA_SIZE_NUMBER “128 MB”
The second method of overcoming the default 16 MB safety limiter is by user discretion. Right after selecting a CIA for injection, quickly press and hold the B button for a few seconds. This will skip the warning message that the file is too big, override the limiter, and continue injection.
Due to limitations of GM9 script, there is no way to patch out this bug without negatively affecting the user experience. The alternative would have been error nags every time you elect to inject. Although not intended this way, you may treat this is a feature in case the first method is too cumbersome. Just keep in mind of the physical 1 GB NAND when employing method two.
What is this “stealth” injection you speak of? Why the quotation marks? Is it or is it not stealth?
Before I start referring to this subject without those quotations, we need to be clear about several points.
With that said, “stealth” injection is a bit of a misnomer. Stealth(ier) is arguable a better term that describes it. “Stealth” is meant to denote the intended purpose of said injection method but does not necessarily mean it actually achieves that purpose. I don’t want to mislead you as the reader, so any pretenses that this type of injection will completely disguise your injected titles from Nintendo’s watchful eyes should be dropped. Okay? Thanks. *Quotation marks will now be removed from here on out.
- Nintendo does not differentiate the difference between homebrew and piracy. The company treats the two as one and the same.
- Nintendo can and will ban your 3DS if they detect there is non-licensed installed software on your handheld system.
- Except for Nintendo itself, no person can claim knowing the exact extent of Nintendo’s homebrew detection capabilities. We only have theories and speculations. Nothing more.
- Also, anyone claiming to have a sure proof method of avoiding said detection is either lying or needs to come spill the beans in how, ASAP. We the community would greatly appreciate that you share and demonstrate a working proof of concept.
- Homebrewers have to assume the possibility it is not a matter of if but when they’ll get banned. Any of us who has ever hacked their 3DS/2DS and went online may have already been marked for a future ban. If you’re still able to use Nintendo’s online services despite having CFW, assume that your system is living on borrowed time staying ban-free by Nintendo’s own discretion.
Get to the point already! What the hell is stealth injection?
Stealth injection is an advancement of GM9’s original method of H&S injection. Its function is to attempt passing off your homebrew title as the “real thing”. Stealth incorporates certain identifier data from the ncch.bin [NCCH0 header], extheader.bin [extended header], and icon [title meta info] files. When a homebrew title gets stealth injected, that title is given the identity of its container system title.
Whenever you launch a title from HOME Menu and stay connected to the Internet, it is believed Nintendo has the ability to search up and track what title you last played. This is speculation from my part, but I believe the biggest dead giveaway in how Nintendo knows this is due mostly in part from those identifier data in those files.
Observe by injecting FBI using GM9’s built-in H&S injector. I recommend having WiFi turned off beforehand and Cthulhu at the ready for cache clearing if you intend to verify this.
Launch your injected FBI and do a Titles lookup for where Health & Safety should be. Notice anything amiss?
Left: FBI (normal) injected in H&S as-is. Right: Health & Safety without injection in place. System titles are highlighted red. On the left, H&S is missing due to FBI’s occupation.
Let’s see another effect of FBI injected in H&S. I’m sure some of you out there are familiar with this one. Turn off the 3DS, remove the SD card, turn the 3DS on, and check where injected FBI is located on HOME Menu. Do not launch FBI.
Left: FBI (normal) injected in H&S without SD card. Right: FBI injected in H&S when shared icon cache is synced correctly between SD card and NAND.
If you ever had FBI icon stuck in place of H&S and needed Cthulhu to fix this issue, this is why. Your HOME Menu icon cache updated to FBI’s icon on both SD card and NAND.
This same phenomena appears when injecting into other system titles using prior versions of the script. Here is freeShop injected in Nintendo eShop:
As the old saying goes about looking and quacking like a duck, stealth injection might be enough to masquerade something like freeShop to its official namesake counterpart. This all depends if Nintendo does not look past this as an initial telemetric call back.
What exactly happens to my titles when injecting? I don’t want any funny business going on when using your script. No bueno if not explained in details.
This Q&A wasn’t meant to be an introductory crash course studying the structure of CIA-related title/game files, but here we are. For the general user, I suppose it helps to not only know what this script does but how it does it. Let’s peel back some layers off the onion we know as a CIA file. We will primarily focus on its .app file; there are other files within the CIA like the ticket, certificate, secondary .app (e-manual), etc., but those are not of relevance to this script. The .app of interest will be the primary or game/title one.
Take a moment to study and familiarize yourself with this diagram. When decompiled and cross compared with a hex viewer, the .app file is an archive that contains those constituents “stacked” or place in that order.
Brief Description of Each File
- ncch.bin (HeaderNCCH0.bin, Nintendo Content Container Header) – When launching a title, this file instructs the 3DS system the basic layout, locations, and sizes of the other files. Size: 512 bytes.
- extheader.bin (ExHeader.bin, Extended Header) – This instructs the 3DS what sort of system and access controls the title requires. Size: 2 KB (2048 bytes).
- logo.bin (LogoLZ.bin, logo) – This is the splash screen you see after launching a title while it loads. The file may either be located after the extended header, contained within ExeFS.bin, or sometimes in both locations. Size: 8 KB (8192 bytes).
- plain.bin (PlainRGN.bin) – I’m not entirely sure of this file’s purpose. My best guess is that this instructs the 3DS the minimum version update for the title to work. Newer CIA titles seem to lack it. Size: 512 bytes.
- ExeFS.bin (Executable File System) – An archive that contains several key files (explained more later). Size: varies by title.
- RomFS.bin (Read-only memory File System) – An archive that contains anything ranging from images, sounds, graphics, texts, etc. Size: varies by title.
Under the ExeFS umbrella
- HeaderExeFS.bin (ExeFS Header) – A header file that tells the sizes and locations of the other files within ExeFS. Size: 512 bytes.
- .code – The heart and soul of your title or game. Size: varies.
- banner – What you see in the top screen at HOME Menu when hovering over your title. In the case of FBI, that’s the spinning blue and white cube. Size: varies.
- icon – Contains information about the title’s name, publisher, and icon. Size: 13.6 KB (14,016 bytes).
- logo – Refer to logo.bin from above.
Next, look at the close-up hex view of the Nintendo eShop NCCH header and its data field. You’ll need this to follow what gets injected when making freeShop into freeShop.
Unlike the previous method, stealth injection employs carrying over anything that could, from eShop. Essential items are left only or modified at the bare minimum to keep freeShop portion working as intended.
Similar changes are made in the first 1024 bytes of extheader.bin. For Application Title (in case this is read off), eShop’s internal codename is “tiger”. The Program ID is matched to keep freeShop from throwing ARM9 crashes.
Lastly, icon and its hash gets swapped in ExeFS and HeaderExeFS.
And that’s it. That’s the secret behind stealth injection. If you wish to audit the script and verify that it does indeed do what I said it does, you’re free to examine the source code at my GitHub page here.
What is the splash screen option? How do I use it?
The splash screen option allows you to inject either the homebrew or Nintendo logo. This component is not believed to contribute to stealth. It’s a personal preference feature if you like switching to the Nintendo splash. The script’s startup default is homebrew. To change the splash screen you wish to inject, press the B button during your system title’s menu choices.
What the crap? I’ve used older versions of this script. Injection is slow as shiet now. Also, why is the script’s file size so much bigger than v1.9?
These are the sore points of this script… Stealth injection requires reading hex offsets from HeaderExeFS. Without those addresses, injection wouldn’t be possible in modifying and rebuilding the ExeFS container. GM9 script (v1.6.1) can’t directly copy hex values from a file and use them in variables. The only way to get around this hurdle is by converting a hex number into a SHA-256 hash value and then reconverting it back with a hash-to-hex lookup table. Most of the increase in file size is because of that table housing all 256 possible hex numbers from 00 to FF.
Version 1.9, file size = 16.3 KB
Version 2.0, file size = 53.2 KB
Up to 12 individual hex numbers, 4 numbers for each file, are retrieved when injecting banner, icon, and/or logo. As for .code, that’s a freebie because its offset is always 0.
You’ll notice the injection start to finish run time has sharply increased.
Version 1.9, FBI injected in H&S = 6 sec
Version 2.0, FBI injected in H&S = 58 sec
While I would like to improve this script’s speed performance and reduce the file size to something more reasonable in a version 2.1 update, we’ll have to wait first until GM9 script offers a ‘hexget’ command before that happens.
You’ve said too much. -But, anything left to add?
Practice safe injection. Word of advice, don’t pick up programming if you don’t have to. That stuff should be placed in the schedule 1 drug list. It’ll hurt your brains real good, kids.
I think that we all need to give this man a round of applause. Not only for the countless hours it must have taken him to discover and verify all of this, but because of how long it must have taken him to type and format this entire post all for the purpose of infroming us to practice safe injecting, among a lot of other things. Also, you should probably add a TL;DR.