From 115d483a54685bd15db15741d7513df6600cd3c0 Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Fri, 13 Oct 2023 13:12:08 -0400 Subject: [PATCH 01/22] Rewrite most of the python script --- MSET9_installer_script/mset9.bat | 8 +- MSET9_installer_script/mset9.py | 466 ++++++++++++++++--------------- 2 files changed, 250 insertions(+), 224 deletions(-) diff --git a/MSET9_installer_script/mset9.bat b/MSET9_installer_script/mset9.bat index 96a2364..77091c5 100644 --- a/MSET9_installer_script/mset9.bat +++ b/MSET9_installer_script/mset9.bat @@ -1,2 +1,8 @@ -py -3 mset9.py +py -V >nul 2>&1 && ( + py -3 mset9.py +) || ( + echo Python 3 is not installed. + echo Please install Python 3 and try again. + echo https://www.python.org/downloads/ +) pause diff --git a/MSET9_installer_script/mset9.py b/MSET9_installer_script/mset9.py index ff181db..861f14e 100644 --- a/MSET9_installer_script/mset9.py +++ b/MSET9_installer_script/mset9.py @@ -1,17 +1,9 @@ #!/usr/bin/python3 -import os,sys,platform,time,shutil,binascii -VERSION="v1.0" - -p=platform.system() -if p == 'Windows': #0-win, 1-lin, 2-mac, x-win lol go with the market leader i guess - OPSYS=0 -elif p == 'Linux': - OPSYS=1 -elif p == 'Darwin': - OPSYS=2 -else: - OPSYS=0 -cwd = os.path.dirname(os.path.abspath(__file__)) +import os, sys, platform, time, shutil, binascii + +VERSION = "v1.1" + +cwd = os.path.dirname(os.path.abspath(__file__)) print(cwd) try: os.chdir(cwd) @@ -19,12 +11,14 @@ print("Failed to set cwd: " + cwd) exit(1) -if OPSYS == 0: #windows - _ = os.system('cls') -else: #linux or mac - _ = os.system('clear') +def clearScreen(): + if platform.system() == "Windows": + os.system("cls") + else: + os.system("clear") -print("MSET9 %s SETUP by zoogie" % VERSION) +clearScreen() +print(f"MSET9 {VERSION} SETUP by zoogie") print("What is your console model and version?") print("Old 3DS has two shoulder buttons (L and R)") print("New 3DS has four shoulder buttons (L, R, ZL, ZR)") @@ -34,241 +28,266 @@ print("3. Old 3DS, 11.4.0 to 11.7.0") print("4. New 3DS, 11.4.0 to 11.7.0") +hackedId1Encoded, consoleModel, consoleFirmware = "", "", "" while 1: try: - command = int(input('>>>')) + sysModelVerSelect = int(input(">>>")) except: - command = 42 - if command == 1: - MODE=0 + sysModelVerSelect = 42 + if sysModelVerSelect == 1: + hackedId1Encoded = "FFFFFFFA119907488546696508A10122054B984768465946C0AA171C4346034CA047B84700900A0871A0050899CE0408730064006D00630000900A0862003900" + consoleModel = "OLD3DS" + consoleFirmware = "11.8-11.17" break - elif command == 2: - MODE=1 + + if sysModelVerSelect == 2: + hackedId1Encoded = "FFFFFFFA119907488546696508A10122054B984768465946C0AA171C4346034CA047B84700900A0871A005085DCE0408730064006D00630000900A0862003900" + consoleModel = "NEW3DS" + consoleFirmware = "11.8-11.17" break - elif command == 3: - MODE=2 + + if sysModelVerSelect == 3: + hackedId1Encoded = "FFFFFFFA119907488546696508A10122054B984768465946C0AA171C4346034CA047B84700900A08499E050899CC0408730064006D00630000900A0862003900" + consoleModel = "OLD3DS" + consoleFirmware = "11.4-11.7" break - elif command == 4: - MODE=3 + + if sysModelVerSelect == 4: + hackedId1Encoded = "FFFFFFFA119907488546696508A10122054B984768465946C0AA171C4346034CA047B84700900A08459E050881CC0408730064006D00630000900A0862003900" + consoleModel = "NEW3DS" + consoleFirmware = "11.4-11.7" break + else: print("Invalid input, try again.") -trigger="002F003A.txt" #all 3ds ":/" - -#old3ds 11.8-11.17 -if MODE == 0: - id1_haxstr="FFFFFFFA119907488546696508A10122054B984768465946C0AA171C4346034CA047B84700900A0871A0050899CE0408730064006D00630000900A0862003900" - model_str="OLD3DS" - firmrange_str="11.8-11.17" -elif MODE == 1: - id1_haxstr="FFFFFFFA119907488546696508A10122054B984768465946C0AA171C4346034CA047B84700900A0871A005085DCE0408730064006D00630000900A0862003900" - model_str="NEW3DS" - firmrange_str="11.8-11.17" -elif MODE == 2: - id1_haxstr="FFFFFFFA119907488546696508A10122054B984768465946C0AA171C4346034CA047B84700900A08499E050899CC0408730064006D00630000900A0862003900" - model_str="OLD3DS" - firmrange_str="11.4-11.7" -elif MODE == 3: - id1_haxstr="FFFFFFFA119907488546696508A10122054B984768465946C0AA171C4346034CA047B84700900A08459E050881CC0408730064006D00630000900A0862003900" - model_str="NEW3DS" - firmrange_str="11.4-11.7" -else: - print("What is wrong with the elf?") - sys.exit(0) +trigger = "002F003A.txt" # all 3ds ":/" -haxid1=bytes.fromhex(id1_haxstr) #ID1 - arm injected payload in readable format -haxid1=haxid1.decode("utf-16le") -haxid1_path="" -id1="" -id1_root="" -id1_path="" +hackedId1 = bytes.fromhex(hackedId1Encoded).decode("utf-16le") # ID1 - arm injected payload in readable format +id1 = "" +id0 = "" +realId1Path = "" -ext_root="" -oldtag="_user-id1" -mode=0 #0 setup state, 1 hax state -id0_count=0 -id0_list=[] -finish_remove=0 +extdataRoot = "" +realId1BackupTag = "_user-id1" +haxState = 0 # 0 setup state, 1 hax state +id0Count = 0 +id0List = [] +shouldRemoveHax = 0 -home_menu=[0x8f,0x98,0x82,0xA1,0xA9,0xB1] #us,eu,jp,ch,kr,tw -mii_maker=[0x217,0x227,0x207,0x267,0x277,0x287] #us,eu,jp,ch,kr,tw +homeMenuExtdata = [0x8F, 0x98, 0x82, 0xA1, 0xA9, 0xB1] # us,eu,jp,ch,kr,tw +miiMakerExtdata = [0x217, 0x227, 0x207, 0x267, 0x277, 0x287] # us,eu,jp,ch,kr,tw +# Make sure we're running from the right spot if not os.path.exists("Nintendo 3DS/"): print("Are you sure you're running this script from the root of your SD card (right next to 'Nintendo 3DS')? You need to!") - print("Current dir: %s" % cwd) + print(f"Current dir: {cwd}") time.sleep(10) sys.exit(0) - + for root, dirs, files in os.walk("Nintendo 3DS/", topdown=True): - for name in files: - pass for name in dirs: + # If the name doesn't contain sdmc (Ignores MSET9 exploit folder) if "sdmc" not in name and len(name[:32]) == 32: try: - temp=int(name[:32],16) + # Check to see if the file name encodes as an int (is hex only) + hexVerify = int(name[:32], 16) except: continue - if type(temp) is int: - if os.path.exists(os.path.join(root, name)+"/extdata"): - id1=name - id1_root=root - id1_path=os.path.join(root, name) - if oldtag in name: - mode=1 + if type(hexVerify) is int: + # Check if the folder (which is either id1 or id0) has the extdata folder + # if it does, it's an id1 folder + if os.path.exists(os.path.join(root, name) + "/extdata"): + id1 = name + id0 = root + realId1Path = os.path.join(root, name) + + if realId1BackupTag in name: + haxState = 1 + + # Otherwise, add it to the id0 list because we need to make sure we only have one id0 else: - id0_count+=1 - id0_list.append(os.path.join(root, name)) + id0Count += 1 + id0List.append(os.path.join(root, name)) + + # CHeck if we have an MSET9 Hacked id1 folder if "sdmc" in name and len(name) == 32: - if haxid1 != name: - print("Yikes, don't change modes in the middle of MSET9!") + # If the MSET9 folder doesn't match the proper haxid1 for the selected console version + if hackedId1 != name: + print("Yikes, don't change console version in the middle of MSET9!") print("Make sure to run option 4, Remove MSET9 before you change modes!") time.sleep(2) - print("Removing mismatched haxid1 ...") + print("Removing mismatched haxid1...") shutil.rmtree(os.path.join(root, name)) print("done.") time.sleep(3) - finish_remove=1 - + shouldRemoveHax = 1 def setup(): - global mode, id1_path, id1_root, id1 - menu_ok=0 - mii_ok=0 - print("Setting up...", end='') - if mode: + global haxState, realId1Path, id0, id1 + menuExtdataGood = False + miiExtdataGood = False + + # Ensure we aren't already configured. + print("Setting up...") + if haxState: print("Already setup!") return - softv = softcheck(id1_path+"/dbs/title.db", 0x31e400, 0, 1) - softv +=softcheck(id1_path+"/dbs/import.db", 0x31e400, 0, 2) - if softv > 0: - if not (os.path.exists(id1_path+"/dbs/import.db") or os.path.exists(id1_path+"/dbs/title.db")): - inp = input(("Create them now? (type yes/no)")) - if inp.lower() == 'yes' or inp.lower() == 'y': - if not os.path.exists(id1_path+"/dbs"): - os.mkdir(id1_path+"/dbs") - if softv == 1: - open(id1_path+"/dbs/title.db", "x").close() - if softv == 2: - open(id1_path+"/dbs/import.db", "x").close() - if softv == 3: - open(id1_path+"/dbs/title.db", "x").close() - open(id1_path+"/dbs/import.db", "x").close() - - print("Come again after resetting the database in settings!!") - sys.exit(0) - print("Invalid database,\nplease reset it in settings -> data management -> nintendo 3ds -> software first before coming back") - sys.exit(0) - - if os.path.exists(id1_path+"/extdata/"+trigger): - os.remove(id1_path+"/extdata/"+trigger) - if not os.path.exists(id1_root+"/"+haxid1): - haxid1_path=id1_root+"/"+haxid1 - os.mkdir(haxid1_path) - os.mkdir(haxid1_path+"/extdata") - os.mkdir(haxid1_path+"/extdata/00000000") - if not os.path.exists(haxid1_path+"/dbs"): - shutil.copytree(id1_path+"/dbs",haxid1_path+"/dbs") - ext_root=id1_path+"/extdata/00000000" - - for i in home_menu: - temp=ext_root+"/%08X" % i + # Ensure data management databases exist + checkTitledb = softcheck(realId1Path + "/dbs/title.db", 0x31E400, 0, 1) + checkImportdb = softcheck(realId1Path + "/dbs/import.db", 0x31E400, 0, 1) + if checkTitledb or checkImportdb: + if not ( + os.path.exists(realId1Path + "/dbs/import.db") + or os.path.exists(realId1Path + "/dbs/title.db") + ): + dbGenInput = input(("Create empty databases now? (type yes/no)")).lower() + if dbGenInput == "yes" or "y": + if not os.path.exists(realId1Path + "/dbs"): + os.mkdir(realId1Path + "/dbs") + if checkTitledb: + open(realId1Path + "/dbs/title.db", "x").close() + if checkImportdb: + open(realId1Path + "/dbs/import.db", "x").close() + + print("Created empty databases.") + else: + print("Didn't create empty databases.") + print("\nplease reset the database files in settings -> data management -> nintendo 3ds -> software first before coming back!") + print("Visual guide: https://3ds.hacks.guide/images/screenshots/database-reset.jpg") + sys.exit(0) + + if os.path.exists(realId1Path + "/extdata/" + trigger): + os.remove(realId1Path + "/extdata/" + trigger) + + # Create the hacked id1 folder + hackedId1Path = id0 + "/" + hackedId1 + os.mkdir(hackedId1Path) + os.mkdir(hackedId1Path + "/extdata") + os.mkdir(hackedId1Path + "/extdata/00000000") + + if not os.path.exists(hackedId1Path + "/dbs"): + shutil.copytree(realId1Path + "/dbs", hackedId1Path + "/dbs") + + extdataRoot = realId1Path + "/extdata/00000000" + + for i in homeMenuExtdata: + temp = extdataRoot + f"/{i:08X}" if os.path.exists(temp): - #print(temp,haxid1_path+"/extdata/00000000/%08X" % i) - shutil.copytree(temp,haxid1_path+"/extdata/00000000/%08X" % i) - menu_ok+=1 - assert(menu_ok==1) - for i in mii_maker: - temp=ext_root+"/%08X" % i + #print(temp,hackedId1Path+f"/extdata/00000000/{i:08X}") + shutil.copytree(temp, hackedId1Path + f"/extdata/00000000/{i:08X}") + menuExtdataGood = True + if not menuExtdataGood: + print("No Home Menu Data!") + print("This shouldn't really happen, Put the sd card back in your console.") + print("Press the home settings icon in the top left, then resume from Section I step 7.") + sys.exit(1) + + for i in miiMakerExtdata: + temp = extdataRoot + f"/{i:08X}" if os.path.exists(temp): - shutil.copytree(temp,haxid1_path+"/extdata/00000000/%08X" % i) - mii_ok+=1 - assert(mii_ok==1) - - if os.path.exists(id1_path): - os.rename(id1_path, id1_path+oldtag) - id1+=oldtag - id1_path=id1_root+"/"+id1 - mode=1 - print(" done.") - + shutil.copytree(temp, hackedId1Path + f"/extdata/00000000/{i:08X}") + miiExtdataGood = True + + if not miiExtdataGood: + print("No Mii Maker Data!") + print("Please go to https://3ds.hacks.guide/troubleshooting#installing-boot9strap-mset9 for instructions.") + sys.exit(1) + + if os.path.exists(realId1Path): + os.rename(realId1Path, realId1Path + realId1BackupTag) + + id1 += realId1BackupTag + realId1Path = f"{id0}/{id1}" + haxState = 1 + print("done.") + + def inject(): - if mode==0: - print("Run setup first!") + if haxState == 0: + print("Run setup first!") return - print("Injecting...", end='') - trigger_path=id1_root+"/"+haxid1+"/extdata/"+trigger - if not os.path.exists(trigger_path): - with open(trigger_path,"w") as f: + + print("Injecting... ", end="") + triggerFilePath = id0 + "/" + hackedId1 + "/extdata/" + trigger + if not os.path.exists(triggerFilePath): + with open(triggerFilePath, "w") as f: f.write("plz be haxxed mister arm9, thx") f.close() - print(" done.") + print("done.") + def delete(): - if mode==0: - print("Run setup first!") + if haxState == 0: + print("Run setup first!") return - print("Deleting...", end='') - trigger_path=id1_root+"/"+haxid1+"/extdata/"+trigger - if os.path.exists(trigger_path): - os.remove(trigger_path) + print("Deleting...", end="") + triggerFilePath = id0 + "/" + hackedId1 + "/extdata/" + trigger + if os.path.exists(triggerFilePath): + os.remove(triggerFilePath) print(" done.") + def remove(): - global mode, id1_path, id1_root, id1 - print("Removing...", end='') - if not os.path.exists(id1_root+"/"+haxid1) and (os.path.exists(id1_path) and oldtag not in id1_path): + global haxState, realId1Path, id0, id1 + print("Removing... ", end="") + if not os.path.exists(id0 + "/" + hackedId1) and (os.path.exists(realId1Path) and realId1BackupTag not in realId1Path): print("Nothing to remove!") return - if os.path.exists(id1_path) and oldtag in id1_path: - os.rename(id1_path, id1_root+"/"+id1[:32]) - #print(id1_path, id1_root+"/"+id1[:32]) - if os.path.exists(id1_root+"/"+haxid1): - shutil.rmtree(id1_root+"/"+haxid1) - id1=id1[:32] - id1_path=id1_root+"/"+id1 - mode=0 - print(" done.") + if os.path.exists(realId1Path) and realId1BackupTag in realId1Path: + os.rename(realId1Path, id0 + "/" + id1[:32]) + # print(id1_path, id1_root+"/"+id1[:32]) + if os.path.exists(id0 + "/" + hackedId1): + shutil.rmtree(id0 + "/" + hackedId1) + id1 = id1[:32] + realId1Path = id0 + "/" + id1 + haxState = 0 + print("done.") + -def softcheck(keyfile, size, crc32, retval): +def softcheck(keyfile, expectedSize, crc32, retval): if not os.path.exists(keyfile): - print("%s \ndoes not exist on SD card!" % keyfile) + print(f"{keyfile} does not exist on SD card!") return retval - elif size: - s=os.path.getsize(keyfile) - if size != s: - print("%s \nis size %08X, not expected %08X" % (keyfile,s,size)) + elif expectedSize: + fileSize = os.path.getsize(keyfile) + if expectedSize != fileSize: + print(f"{keyfile} is size {fileSize:,} bytes, not expected {expectedSize:,} bytes") return retval elif crc32: - with open(keyfile,"rb") as f: - temp=f.read() - c=binascii.crc32(temp) - if crc32 != c: - print("%s \n was not recognized as the correct file" % keyfile) - return retval + with open(keyfile, "rb") as f: + checksum = binascii.crc32(f.read()) + if crc32 != checksum: + print(f"{keyfile} was not recognized as the correct file") + f.close() + return retval + f.close() return 0 -def check(keyfile, size, crc32): - if not os.path.exists(keyfile): - print("%s \ndoes not exist on SD card!" % keyfile) +# Checks if the file exists, and optionally checks the size and crc32 +def check(keyfile, expectedSize = None, crc32 = None): + if not os.path.exists(keyfile): + print(f"{keyfile} does not exist on SD card!") + sys.exit(0) + elif expectedSize: + fileSize = os.path.getsize(keyfile) + if expectedSize != fileSize: + print(f"{keyfile} is size {fileSize:,} bytes, not expected {expectedSize:,} bytes") sys.exit(0) - elif size: - s=os.path.getsize(keyfile) - if size != s: - print("%s \nis size %08X, not expected %08X" % (keyfile,s,size)) - sys.exit(0) - elif crc32: - with open(keyfile,"rb") as f: - temp=f.read() - c=binascii.crc32(temp) - if crc32 != c: - print("%s \n was not recognized as the correct file" % keyfile) + elif crc32: + with open(keyfile, "rb") as f: + checksum = binascii.crc32(f.read()) + if crc32 != checksum: + print(f"{keyfile} was not recognized as the correct file") + f.close() sys.exit(0) + f.close() -def reapply_cwd(): + +def reapplyWorkingDir(): try: os.chdir(cwd) return True @@ -276,61 +295,62 @@ def reapply_cwd(): print("Couldn't reapply cwd, is sdcard reinserted?") return False -if finish_remove: +if shouldRemoveHax: remove() -check("boot9strap/boot9strap.firm", 0, 0x08129c1f) -#check("Nintendo 3DS/Private/00020400/phtcache.bin", 0x7f53c, 0) -check("boot.firm", 0, 0) -check("boot.3dsx", 0, 0) -check("b9", 0, 0) -if id0_count == 0: - print("\nYou're supposed to be running this on the 3DS SD card!") - print("NOT \n%s" % cwd) + +# Ensure we have the required files (people extracted the entire zip to their sdcard) +check("boot9strap/boot9strap.firm", 0, 0x08129C1F) +# check("Nintendo 3DS/Private/00020400/phtcache.bin", 0x7f53c, 0) +check("boot.firm") +check("boot.3dsx") +check("b9") +check("SafeB9S.bin") + +if id0Count == 0: + print("You're supposed to be running this on the 3DS SD card root!") + print(f"NOT {cwd}") time.sleep(10) sys.exit(0) print("Detected ID0(s):") -for i in id0_list: +for i in id0List: print(i) print("") -if id0_count != 1: - print("You don't have 1 ID0 in your Nintendo 3DS folder, you have %d!" % id0_count) +if id0Count != 1: + print(f"You don't have 1 ID0 in your Nintendo 3DS folder, you have {id0Count}!") print("Consult:\nhttps://3ds.hacks.guide/troubleshooting#installing-boot9strap-mset9\nfor help!") sys.exit(0) -if OPSYS == 0: #windows - _ = os.system('cls') -else: #linux or mac - _ = os.system('clear') - -print("MSET9 %s SETUP by zoogie" % VERSION) -print("%s %s" % (model_str,firmrange_str)) +clearScreen() +print(f"MSET9 {VERSION} SETUP by zoogie") +print(f"Using {consoleModel} {consoleFirmware}") print("\n-- Please type in a number then hit return --\n") print("1. Setup MSET9") -print("2. Inject trigger file %s" % trigger) -print("3. Delete trigger file %s" % trigger) +print(f"2. Inject trigger file {trigger}") +print(f"3. Delete trigger file {trigger}") print("4. Remove MSET9, DO NOT FORGET to run this after you finish the exploit!") print("5. Exit") while 1: try: - command = int(input('>>>')) + sysModelVerSelect = int(input(">>>")) except: - command = 42 + sysModelVerSelect = 42 - if command >=1 and command <= 4 and not reapply_cwd(): - continue # reapply_cwd already prints error if fail - - if command == 1: + # Separated to maybe fix removable bug + if not reapplyWorkingDir(): + continue #already prints error if fail + + if sysModelVerSelect == 1: setup() - elif command == 2: + elif sysModelVerSelect == 2: inject() - elif command == 3: - delete() - elif command == 4: + elif sysModelVerSelect == 3: + delete() + elif sysModelVerSelect == 4: remove() - elif command == 5: + elif sysModelVerSelect == 5: print("Goodbye!") break else: From 53c43a28cad8be6e8bd0637d7b141e53818ecb99 Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Fri, 13 Oct 2023 18:44:05 -0400 Subject: [PATCH 02/22] Fix bugs found by Blueness and add error codes --- MSET9_installer_script/errors.txt | 14 +++++ MSET9_installer_script/mset9.bat | 10 ++-- MSET9_installer_script/mset9.py | 92 +++++++++++++++++++------------ 3 files changed, 77 insertions(+), 39 deletions(-) create mode 100644 MSET9_installer_script/errors.txt diff --git a/MSET9_installer_script/errors.txt b/MSET9_installer_script/errors.txt new file mode 100644 index 0000000..748b089 --- /dev/null +++ b/MSET9_installer_script/errors.txt @@ -0,0 +1,14 @@ +Error 1: Not running on the SD Card root. /Nintendo 3DS/ not found. +Error 2: Write protected SD Card. Ensure switch is facing up. +Error 3: Attempting to change target console version during exploit +Error 4: No Home Menu Extdata. Shouldn't happen pretty much ever. +Error 5: No Mii Maker Data, follow MSET9 Troublshooting page. +Error 6: Not running on the SD Card root. No ID0s detected. +Error 7: Multiple ID0s, follow MSET9 Troublshooting page. +Error 8: Missing expected file. Reextract MSET9 zip file. +Error 9: File size does not match expected. Reextract MSET9 zip file. +Error 10: Mismatched checksum. Redownload and Reextract MSET9 zip file. +Error 11: Failed to initially enter the directory. This shouldn't happen pretty much ever. +Error 12: Could not change back into SD directory. Ensure the SD Card has been reinserted. + +MSET9 Troublshooting Page: https://3ds.hacks.guide/troubleshooting#installing-boot9strap-mset9 \ No newline at end of file diff --git a/MSET9_installer_script/mset9.bat b/MSET9_installer_script/mset9.bat index 77091c5..d15ac8d 100644 --- a/MSET9_installer_script/mset9.bat +++ b/MSET9_installer_script/mset9.bat @@ -1,8 +1,10 @@ -py -V >nul 2>&1 && ( - py -3 mset9.py -) || ( +py -V > nul +if %errorlevel% NEQ 0 ( echo Python 3 is not installed. echo Please install Python 3 and try again. echo https://www.python.org/downloads/ + echo. + pause + exit ) -pause +py -3 mset9.py \ No newline at end of file diff --git a/MSET9_installer_script/mset9.py b/MSET9_installer_script/mset9.py index 861f14e..84a4b9b 100644 --- a/MSET9_installer_script/mset9.py +++ b/MSET9_installer_script/mset9.py @@ -8,7 +8,7 @@ try: os.chdir(cwd) except Exception: - print("Failed to set cwd: " + cwd) + print("Error 11: Failed to set cwd: " + cwd) exit(1) def clearScreen(): @@ -61,7 +61,7 @@ def clearScreen(): else: print("Invalid input, try again.") -trigger = "002F003A.txt" # all 3ds ":/" +trigger = "002F003A.txt" # all 3ds ":/" in hex hackedId1 = bytes.fromhex(hackedId1Encoded).decode("utf-16le") # ID1 - arm injected payload in readable format id1 = "" @@ -80,11 +80,18 @@ def clearScreen(): # Make sure we're running from the right spot if not os.path.exists("Nintendo 3DS/"): - print("Are you sure you're running this script from the root of your SD card (right next to 'Nintendo 3DS')? You need to!") + print("Error 1: Are you sure you're running this script from the root of your SD card (right next to 'Nintendo 3DS')? You need to!") print(f"Current dir: {cwd}") time.sleep(10) sys.exit(0) +writeable = os.access(cwd, os.W_OK) +if not writeable: + print("Error 2: Your sd is write protected! Please ensure the switch on the side of your SD card is facing upwards.") + print("Visual aid: https://nintendohomebrew.com/assets/img/nhmemes/sdlock.png") + time.sleep(10) + sys.exit(0) + for root, dirs, files in os.walk("Nintendo 3DS/", topdown=True): for name in dirs: @@ -115,7 +122,7 @@ def clearScreen(): if "sdmc" in name and len(name) == 32: # If the MSET9 folder doesn't match the proper haxid1 for the selected console version if hackedId1 != name: - print("Yikes, don't change console version in the middle of MSET9!") + print("Error 3: don't change console version in the middle of MSET9!") print("Make sure to run option 4, Remove MSET9 before you change modes!") time.sleep(2) print("Removing mismatched haxid1...") @@ -129,11 +136,14 @@ def setup(): global haxState, realId1Path, id0, id1 menuExtdataGood = False miiExtdataGood = False + homeDataPath = "" + miiDataPath = "" + # Ensure we aren't already configured. print("Setting up...") if haxState: - print("Already setup!") + print("Already setup, run option 2!") return # Ensure data management databases exist @@ -156,46 +166,58 @@ def setup(): print("Created empty databases.") else: print("Didn't create empty databases.") - print("\nplease reset the database files in settings -> data management -> nintendo 3ds -> software first before coming back!") + print("please reset the database files in settings -> data management -> nintendo 3ds -> software first before coming back!") print("Visual guide: https://3ds.hacks.guide/images/screenshots/database-reset.jpg") sys.exit(0) if os.path.exists(realId1Path + "/extdata/" + trigger): os.remove(realId1Path + "/extdata/" + trigger) - # Create the hacked id1 folder - hackedId1Path = id0 + "/" + hackedId1 - os.mkdir(hackedId1Path) - os.mkdir(hackedId1Path + "/extdata") - os.mkdir(hackedId1Path + "/extdata/00000000") - - if not os.path.exists(hackedId1Path + "/dbs"): - shutil.copytree(realId1Path + "/dbs", hackedId1Path + "/dbs") - extdataRoot = realId1Path + "/extdata/00000000" for i in homeMenuExtdata: - temp = extdataRoot + f"/{i:08X}" - if os.path.exists(temp): + extdataRegionCheck = extdataRoot + f"/{i:08X}" + if os.path.exists(extdataRegionCheck): #print(temp,hackedId1Path+f"/extdata/00000000/{i:08X}") - shutil.copytree(temp, hackedId1Path + f"/extdata/00000000/{i:08X}") + homeDataPath = extdataRegionCheck menuExtdataGood = True + break + if not menuExtdataGood: - print("No Home Menu Data!") + print("Error 4: No Home Menu Data!") print("This shouldn't really happen, Put the sd card back in your console.") print("Press the home settings icon in the top left, then resume from Section I step 7.") - sys.exit(1) + sys.exit(0) for i in miiMakerExtdata: - temp = extdataRoot + f"/{i:08X}" - if os.path.exists(temp): - shutil.copytree(temp, hackedId1Path + f"/extdata/00000000/{i:08X}") + extdataRegionCheck = extdataRoot + f"/{i:08X}" + if os.path.exists(extdataRegionCheck): + #shutil.copytree(temp, hackedId1Path + f"/extdata/00000000/{i:08X}") + miiDataPath = extdataRegionCheck miiExtdataGood = True + break if not miiExtdataGood: - print("No Mii Maker Data!") + print("Err 5: No Mii Maker Data!") print("Please go to https://3ds.hacks.guide/troubleshooting#installing-boot9strap-mset9 for instructions.") - sys.exit(1) + sys.exit(0) + + # Currently: make this error safe + # Create the hacked id1 folder + if not os.path.exists(id0 + "/" + hackedId1): + hackedId1Path = id0 + "/" + hackedId1 + os.mkdir(hackedId1Path) + os.mkdir(hackedId1Path + "/extdata") + os.mkdir(hackedId1Path + "/extdata/00000000") + + + if not os.path.exists(hackedId1Path + "/dbs"): + shutil.copytree(realId1Path + "/dbs", hackedId1Path + "/dbs") + + # *now* we can copy the extdata to the hacked path instead of failing with a half copied folder + shutil.copytree(homeDataPath, hackedId1Path + f"/extdata/00000000/{i:08X}") + shutil.copytree(miiDataPath, hackedId1Path + f"/extdata/00000000/{i:08X}") + if os.path.exists(realId1Path): os.rename(realId1Path, realId1Path + realId1BackupTag) @@ -208,7 +230,7 @@ def setup(): def inject(): if haxState == 0: - print("Run setup first!") + print("Please run option 2 first!") return print("Injecting... ", end="") @@ -222,13 +244,13 @@ def inject(): def delete(): if haxState == 0: - print("Run setup first!") + print("Run option 1 first!") return - print("Deleting...", end="") + print("Deleting... ") triggerFilePath = id0 + "/" + hackedId1 + "/extdata/" + trigger if os.path.exists(triggerFilePath): os.remove(triggerFilePath) - print(" done.") + print("done.") def remove(): @@ -270,18 +292,18 @@ def softcheck(keyfile, expectedSize, crc32, retval): # Checks if the file exists, and optionally checks the size and crc32 def check(keyfile, expectedSize = None, crc32 = None): if not os.path.exists(keyfile): - print(f"{keyfile} does not exist on SD card!") + print(f"Error 8: {keyfile} does not exist on SD card!") sys.exit(0) elif expectedSize: fileSize = os.path.getsize(keyfile) if expectedSize != fileSize: - print(f"{keyfile} is size {fileSize:,} bytes, not expected {expectedSize:,} bytes") + print(f"Error 9: {keyfile} is size {fileSize:,} bytes, not expected {expectedSize:,} bytes") sys.exit(0) elif crc32: with open(keyfile, "rb") as f: checksum = binascii.crc32(f.read()) if crc32 != checksum: - print(f"{keyfile} was not recognized as the correct file") + print(f"Error 10: {keyfile} was not recognized as the correct file") f.close() sys.exit(0) f.close() @@ -292,7 +314,7 @@ def reapplyWorkingDir(): os.chdir(cwd) return True except Exception: - print("Couldn't reapply cwd, is sdcard reinserted?") + print("Error 12: Couldn't reapply cwd, is sdcard reinserted?") return False if shouldRemoveHax: @@ -307,7 +329,7 @@ def reapplyWorkingDir(): check("SafeB9S.bin") if id0Count == 0: - print("You're supposed to be running this on the 3DS SD card root!") + print("Error 6: You're supposed to be running this on the 3DS SD card root!") print(f"NOT {cwd}") time.sleep(10) sys.exit(0) @@ -317,7 +339,7 @@ def reapplyWorkingDir(): print(i) print("") if id0Count != 1: - print(f"You don't have 1 ID0 in your Nintendo 3DS folder, you have {id0Count}!") + print(f"Error 7: You don't have 1 ID0 in your Nintendo 3DS folder, you have {id0Count}!") print("Consult:\nhttps://3ds.hacks.guide/troubleshooting#installing-boot9strap-mset9\nfor help!") sys.exit(0) From 725f65f54d2ac19be0cce52800488b5efb57e390 Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Sun, 15 Oct 2023 10:28:48 -0400 Subject: [PATCH 03/22] Rewrite script around 1 removal concept --- MSET9_installer_script/errors.txt | 1 + MSET9_installer_script/mset9.py | 275 ++++++++++++++++-------------- 2 files changed, 147 insertions(+), 129 deletions(-) diff --git a/MSET9_installer_script/errors.txt b/MSET9_installer_script/errors.txt index 748b089..ccd723e 100644 --- a/MSET9_installer_script/errors.txt +++ b/MSET9_installer_script/errors.txt @@ -10,5 +10,6 @@ Error 9: File size does not match expected. Reextract MSET9 zip file. Error 10: Mismatched checksum. Redownload and Reextract MSET9 zip file. Error 11: Failed to initially enter the directory. This shouldn't happen pretty much ever. Error 12: Could not change back into SD directory. Ensure the SD Card has been reinserted. +Error 13: Database problem. Follow the troubleshooting to reset the DBs. MSET9 Troublshooting Page: https://3ds.hacks.guide/troubleshooting#installing-boot9strap-mset9 \ No newline at end of file diff --git a/MSET9_installer_script/mset9.py b/MSET9_installer_script/mset9.py index 84a4b9b..587057d 100644 --- a/MSET9_installer_script/mset9.py +++ b/MSET9_installer_script/mset9.py @@ -3,20 +3,29 @@ VERSION = "v1.1" +def clearScreen(): + if platform.system() == "Windows": + os.system("cls") + else: + os.system("clear") + +def prgood(content): + print(f"[\033[0;32m✓\033[0m] {content}") + +def prbad(content): + print(f"[\033[0;91mX\033[0m] {content}") + +def prinfo(content): + print(f"[*] {content}") + cwd = os.path.dirname(os.path.abspath(__file__)) print(cwd) try: os.chdir(cwd) except Exception: - print("Error 11: Failed to set cwd: " + cwd) + prbad("Error 11: Failed to set cwd: " + cwd) exit(1) -def clearScreen(): - if platform.system() == "Windows": - os.system("cls") - else: - os.system("clear") - clearScreen() print(f"MSET9 {VERSION} SETUP by zoogie") print("What is your console model and version?") @@ -31,7 +40,11 @@ def clearScreen(): hackedId1Encoded, consoleModel, consoleFirmware = "", "", "" while 1: try: - sysModelVerSelect = int(input(">>>")) + sysModelVerSelect = int(input(">>> ")) + except KeyboardInterrupt: + print() + prgood("Goodbye!") + exit() except: sysModelVerSelect = 42 if sysModelVerSelect == 1: @@ -62,7 +75,6 @@ def clearScreen(): print("Invalid input, try again.") trigger = "002F003A.txt" # all 3ds ":/" in hex - hackedId1 = bytes.fromhex(hackedId1Encoded).decode("utf-16le") # ID1 - arm injected payload in readable format id1 = "" id0 = "" @@ -78,22 +90,34 @@ def clearScreen(): homeMenuExtdata = [0x8F, 0x98, 0x82, 0xA1, 0xA9, 0xB1] # us,eu,jp,ch,kr,tw miiMakerExtdata = [0x217, 0x227, 0x207, 0x267, 0x277, 0x287] # us,eu,jp,ch,kr,tw -# Make sure we're running from the right spot +# make a table so we can print regions based on what hex code from the above is found +regionTable = { + 0x8F: "USA Region", + 0x98: "EUR Region", + 0x82: "JPN Region", + 0xA1: "CHN Region", + 0xA9: "KOR Region", + 0xB1: "TWN Region" +} + +# Section: insureRoot if not os.path.exists("Nintendo 3DS/"): - print("Error 1: Are you sure you're running this script from the root of your SD card (right next to 'Nintendo 3DS')? You need to!") - print(f"Current dir: {cwd}") + prbad("Error 1: Are you sure you're running this script from the root of your SD card (right next to 'Nintendo 3DS')? You need to!") + prinfo(f"Current dir: {cwd}") time.sleep(10) sys.exit(0) +# Section: sdWritable writeable = os.access(cwd, os.W_OK) if not writeable: - print("Error 2: Your sd is write protected! Please ensure the switch on the side of your SD card is facing upwards.") - print("Visual aid: https://nintendohomebrew.com/assets/img/nhmemes/sdlock.png") + prbad("Error 2: Your sd is write protected! Please ensure the switch on the side of your SD card is facing upwards.") + prinfo("Visual aid: https://nintendohomebrew.com/assets/img/nhmemes/sdlock.png") time.sleep(10) sys.exit(0) - +# Section: sdwalk for root, dirs, files in os.walk("Nintendo 3DS/", topdown=True): + for name in dirs: # If the name doesn't contain sdmc (Ignores MSET9 exploit folder) if "sdmc" not in name and len(name[:32]) == 32: @@ -122,241 +146,232 @@ def clearScreen(): if "sdmc" in name and len(name) == 32: # If the MSET9 folder doesn't match the proper haxid1 for the selected console version if hackedId1 != name: - print("Error 3: don't change console version in the middle of MSET9!") - print("Make sure to run option 4, Remove MSET9 before you change modes!") + prbad("Error 3: don't change console version in the middle of MSET9!") + prbad("Make sure to run option 4, Remove MSET9 before you change modes!") time.sleep(2) - print("Removing mismatched haxid1...") + prinfo("Removing mismatched haxid1...") shutil.rmtree(os.path.join(root, name)) - print("done.") + prgood("done.") time.sleep(3) shouldRemoveHax = 1 - -def setup(): - global haxState, realId1Path, id0, id1 +homeDataPath, miiDataPath, homeHex, miiHex = "", "", 0x0, 0x0 +def sanity(): + global haxState, realId1Path, id0, id1, homeDataPath, miiDataPath, homeHex, miiHex menuExtdataGood = False miiExtdataGood = False - homeDataPath = "" - miiDataPath = "" + print() + prinfo("Performing sanity checks...") - # Ensure we aren't already configured. - print("Setting up...") - if haxState: - print("Already setup, run option 2!") - return - - # Ensure data management databases exist + prinfo("Ensuring extracted files exist...") + check("boot9strap/boot9strap.firm", 0, 0x08129C1F) + check("boot.firm") + check("boot.3dsx") + check("b9") + check("SafeB9S.bin") + prgood("All files look good!") + + prinfo("Checking databases...") checkTitledb = softcheck(realId1Path + "/dbs/title.db", 0x31E400, 0, 1) checkImportdb = softcheck(realId1Path + "/dbs/import.db", 0x31E400, 0, 1) if checkTitledb or checkImportdb: + prbad("Error 13: Database(s) malformed or missing!") if not ( os.path.exists(realId1Path + "/dbs/import.db") or os.path.exists(realId1Path + "/dbs/title.db") ): - dbGenInput = input(("Create empty databases now? (type yes/no)")).lower() - if dbGenInput == "yes" or "y": - if not os.path.exists(realId1Path + "/dbs"): - os.mkdir(realId1Path + "/dbs") - if checkTitledb: - open(realId1Path + "/dbs/title.db", "x").close() - if checkImportdb: - open(realId1Path + "/dbs/import.db", "x").close() - - print("Created empty databases.") - else: - print("Didn't create empty databases.") - print("please reset the database files in settings -> data management -> nintendo 3ds -> software first before coming back!") - print("Visual guide: https://3ds.hacks.guide/images/screenshots/database-reset.jpg") + if not os.path.exists(realId1Path + "/dbs"): + os.mkdir(realId1Path + "/dbs") + if checkTitledb: + open(realId1Path + "/dbs/title.db", "x").close() + if checkImportdb: + open(realId1Path + "/dbs/import.db", "x").close() + + prinfo("Created empty databases.") + prinfo("please reset the database files in settings -> data management -> nintendo 3ds -> software first before coming back!") + prinfo("Visual guide: https://3ds.hacks.guide/images/screenshots/database-reset.jpg") sys.exit(0) - + else: + prgood("Databases look good!") + if os.path.exists(realId1Path + "/extdata/" + trigger): + prinfo("Removing stale trigger...") os.remove(realId1Path + "/extdata/" + trigger) - + extdataRoot = realId1Path + "/extdata/00000000" + prinfo("Checking for home menu extdata...") for i in homeMenuExtdata: extdataRegionCheck = extdataRoot + f"/{i:08X}" if os.path.exists(extdataRegionCheck): - #print(temp,hackedId1Path+f"/extdata/00000000/{i:08X}") + prgood(f"Detected {regionTable[i]} home data!") + homeHex = i homeDataPath = extdataRegionCheck menuExtdataGood = True break if not menuExtdataGood: - print("Error 4: No Home Menu Data!") - print("This shouldn't really happen, Put the sd card back in your console.") - print("Press the home settings icon in the top left, then resume from Section I step 7.") + prbad("Error 4: No Home Menu Data!") + prinfo("This shouldn't really happen, Put the sd card back in your console.") + prinfo("Turn it on and off again, then restart the script.") sys.exit(0) - + + prinfo("Checking for mii maker extdata...") for i in miiMakerExtdata: extdataRegionCheck = extdataRoot + f"/{i:08X}" if os.path.exists(extdataRegionCheck): - #shutil.copytree(temp, hackedId1Path + f"/extdata/00000000/{i:08X}") + prgood("Found mii maker data!") + miiHex = i miiDataPath = extdataRegionCheck miiExtdataGood = True break - + if not miiExtdataGood: - print("Err 5: No Mii Maker Data!") - print("Please go to https://3ds.hacks.guide/troubleshooting#installing-boot9strap-mset9 for instructions.") + prbad("Err 5: No Mii Maker Data!") + prinfo("Please go to https://3ds.hacks.guide/troubleshooting#installing-boot9strap-mset9 for instructions.") sys.exit(0) - # Currently: make this error safe - # Create the hacked id1 folder +def injection(): + global realId1Path, id1 + if not os.path.exists(id0 + "/" + hackedId1): + prinfo("Creating hacked Id1...") hackedId1Path = id0 + "/" + hackedId1 os.mkdir(hackedId1Path) os.mkdir(hackedId1Path + "/extdata") os.mkdir(hackedId1Path + "/extdata/00000000") - + else: + prinfo("Reusing existing hacked Id1...") + hackedId1Path = id0 + "/" + hackedId1 if not os.path.exists(hackedId1Path + "/dbs"): + prinfo("Copying databases to hacked Id1...") shutil.copytree(realId1Path + "/dbs", hackedId1Path + "/dbs") - # *now* we can copy the extdata to the hacked path instead of failing with a half copied folder - shutil.copytree(homeDataPath, hackedId1Path + f"/extdata/00000000/{i:08X}") - shutil.copytree(miiDataPath, hackedId1Path + f"/extdata/00000000/{i:08X}") - + prinfo("Copying extdata to hacked Id1...") + shutil.copytree(homeDataPath, hackedId1Path + f"/extdata/00000000/{homeHex:08X}") + shutil.copytree(miiDataPath, hackedId1Path + f"/extdata/00000000/{miiHex:08X}") if os.path.exists(realId1Path): + prinfo("Backing up real Id1...") os.rename(realId1Path, realId1Path + realId1BackupTag) - + id1 += realId1BackupTag realId1Path = f"{id0}/{id1}" - haxState = 1 - print("done.") - - -def inject(): - if haxState == 0: - print("Please run option 2 first!") - return - print("Injecting... ", end="") + prinfo("Injecting trigger file...") triggerFilePath = id0 + "/" + hackedId1 + "/extdata/" + trigger if not os.path.exists(triggerFilePath): with open(triggerFilePath, "w") as f: f.write("plz be haxxed mister arm9, thx") f.close() - print("done.") - + prgood("Done.") def delete(): - if haxState == 0: - print("Run option 1 first!") - return - print("Deleting... ") + prinfo("Deleting trigger file...") triggerFilePath = id0 + "/" + hackedId1 + "/extdata/" + trigger if os.path.exists(triggerFilePath): os.remove(triggerFilePath) - print("done.") - + prgood("done.") + prinfo("Nothing to remove!") def remove(): global haxState, realId1Path, id0, id1 - print("Removing... ", end="") + prinfo("Removing MSET9...") if not os.path.exists(id0 + "/" + hackedId1) and (os.path.exists(realId1Path) and realId1BackupTag not in realId1Path): - print("Nothing to remove!") + prinfo("Nothing to remove!") return + if os.path.exists(realId1Path) and realId1BackupTag in realId1Path: + prinfo("Renaming original Id1...") os.rename(realId1Path, id0 + "/" + id1[:32]) # print(id1_path, id1_root+"/"+id1[:32]) if os.path.exists(id0 + "/" + hackedId1): + prinfo("Deleting hacked Id1...") shutil.rmtree(id0 + "/" + hackedId1) id1 = id1[:32] realId1Path = id0 + "/" + id1 haxState = 0 - print("done.") - + prgood("done.") def softcheck(keyfile, expectedSize, crc32, retval): + shortname = keyfile.rsplit("/")[-1] if not os.path.exists(keyfile): - print(f"{keyfile} does not exist on SD card!") + prbad(f"{shortname} does not exist on SD card!") return retval elif expectedSize: fileSize = os.path.getsize(keyfile) if expectedSize != fileSize: - print(f"{keyfile} is size {fileSize:,} bytes, not expected {expectedSize:,} bytes") + prbad(f"{shortname} is size {fileSize:,} bytes, not expected {expectedSize:,} bytes") return retval elif crc32: with open(keyfile, "rb") as f: checksum = binascii.crc32(f.read()) if crc32 != checksum: - print(f"{keyfile} was not recognized as the correct file") + prbad(f"{shortname} was not recognized as the correct file") f.close() return retval f.close() + prgood(f"{shortname} looks good!") return 0 -# Checks if the file exists, and optionally checks the size and crc32 def check(keyfile, expectedSize = None, crc32 = None): + shortname = keyfile.rsplit("/")[-1] if not os.path.exists(keyfile): - print(f"Error 8: {keyfile} does not exist on SD card!") + prbad(f"Error 8: {shortname} does not exist on SD card!") + prinfo("Please extract the MSET9 zip file again, being sure to Overwrite any files.") sys.exit(0) elif expectedSize: fileSize = os.path.getsize(keyfile) if expectedSize != fileSize: - print(f"Error 9: {keyfile} is size {fileSize:,} bytes, not expected {expectedSize:,} bytes") + prbad(f"Error 9: {shortname} is size {fileSize:,} bytes, not expected {expectedSize:,} bytes") + prinfo("Please extract the MSET9 zip file again, being sure to Overwrite any files.") sys.exit(0) elif crc32: with open(keyfile, "rb") as f: checksum = binascii.crc32(f.read()) if crc32 != checksum: - print(f"Error 10: {keyfile} was not recognized as the correct file") + prbad(f"Error 10: {shortname} was not recognized as the correct file") + prinfo("Please extract the MSET9 zip file again, being sure to Overwrite any files.") f.close() sys.exit(0) f.close() +prinfo("Detected ID0(s):") +for i in id0List: + prinfo(i) +print() +if id0Count != 1: + prbad(f"Error 7: You don't have 1 ID0 in your Nintendo 3DS folder, you have {id0Count}!") + prinfo("Consult:\nhttps://3ds.hacks.guide/troubleshooting#installing-boot9strap-mset9\nfor help!") + sys.exit(0) def reapplyWorkingDir(): try: os.chdir(cwd) return True except Exception: - print("Error 12: Couldn't reapply cwd, is sdcard reinserted?") + prbad("Error 12: Couldn't reapply cwd, is sdcard reinserted?") return False -if shouldRemoveHax: - remove() - -# Ensure we have the required files (people extracted the entire zip to their sdcard) -check("boot9strap/boot9strap.firm", 0, 0x08129C1F) -# check("Nintendo 3DS/Private/00020400/phtcache.bin", 0x7f53c, 0) -check("boot.firm") -check("boot.3dsx") -check("b9") -check("SafeB9S.bin") - -if id0Count == 0: - print("Error 6: You're supposed to be running this on the 3DS SD card root!") - print(f"NOT {cwd}") - time.sleep(10) - sys.exit(0) - -print("Detected ID0(s):") -for i in id0List: - print(i) -print("") -if id0Count != 1: - print(f"Error 7: You don't have 1 ID0 in your Nintendo 3DS folder, you have {id0Count}!") - print("Consult:\nhttps://3ds.hacks.guide/troubleshooting#installing-boot9strap-mset9\nfor help!") - sys.exit(0) - clearScreen() print(f"MSET9 {VERSION} SETUP by zoogie") print(f"Using {consoleModel} {consoleFirmware}") print("\n-- Please type in a number then hit return --\n") -print("1. Setup MSET9") -print(f"2. Inject trigger file {trigger}") +print("1. Perform sanity checks") +print("2. Inject MSET9 exploit") print(f"3. Delete trigger file {trigger}") -print("4. Remove MSET9, DO NOT FORGET to run this after you finish the exploit!") +print("4. Manually Remove MSET9") print("5. Exit") while 1: try: - sysModelVerSelect = int(input(">>>")) + sysModelVerSelect = int(input(">>> ")) + except KeyboardInterrupt: + sysModelVerSelect = 5 # exit on Ctrl+C + print() except: sysModelVerSelect = 42 @@ -365,17 +380,19 @@ def reapplyWorkingDir(): continue #already prints error if fail if sysModelVerSelect == 1: - setup() + sanity() + prgood("Looking good!\n") elif sysModelVerSelect == 2: - inject() + sanity() + injection() elif sysModelVerSelect == 3: delete() elif sysModelVerSelect == 4: remove() - elif sysModelVerSelect == 5: - print("Goodbye!") + elif sysModelVerSelect == 5 or "exit": + prgood("Goodbye!") break else: - print("Invalid input, try again.") + prinfo("Invalid input, try again.") -time.sleep(2) +time.sleep(2) \ No newline at end of file From fedd4004ff83c04fa751c1aaf868474f7533666c Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Sun, 15 Oct 2023 11:51:59 -0400 Subject: [PATCH 04/22] Ignore Id0s that aren't 32 chars long --- MSET9_installer_script/errors.txt | 1 + MSET9_installer_script/mset9.py | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MSET9_installer_script/errors.txt b/MSET9_installer_script/errors.txt index ccd723e..e881dd6 100644 --- a/MSET9_installer_script/errors.txt +++ b/MSET9_installer_script/errors.txt @@ -11,5 +11,6 @@ Error 10: Mismatched checksum. Redownload and Reextract MSET9 zip file. Error 11: Failed to initially enter the directory. This shouldn't happen pretty much ever. Error 12: Could not change back into SD directory. Ensure the SD Card has been reinserted. Error 13: Database problem. Follow the troubleshooting to reset the DBs. +Error 14: Invalid Id0. Ensure the length is 32 characters long. This shouldn't really happen. MSET9 Troublshooting Page: https://3ds.hacks.guide/troubleshooting#installing-boot9strap-mset9 \ No newline at end of file diff --git a/MSET9_installer_script/mset9.py b/MSET9_installer_script/mset9.py index 587057d..9066aee 100644 --- a/MSET9_installer_script/mset9.py +++ b/MSET9_installer_script/mset9.py @@ -85,7 +85,6 @@ def prinfo(content): haxState = 0 # 0 setup state, 1 hax state id0Count = 0 id0List = [] -shouldRemoveHax = 0 homeMenuExtdata = [0x8F, 0x98, 0x82, 0xA1, 0xA9, 0xB1] # us,eu,jp,ch,kr,tw miiMakerExtdata = [0x217, 0x227, 0x207, 0x267, 0x277, 0x287] # us,eu,jp,ch,kr,tw @@ -139,8 +138,9 @@ def prinfo(content): # Otherwise, add it to the id0 list because we need to make sure we only have one id0 else: - id0Count += 1 - id0List.append(os.path.join(root, name)) + if len(name) == 32: + id0Count += 1 + id0List.append(os.path.join(root, name)) # CHeck if we have an MSET9 Hacked id1 folder if "sdmc" in name and len(name) == 32: @@ -153,7 +153,6 @@ def prinfo(content): shutil.rmtree(os.path.join(root, name)) prgood("done.") time.sleep(3) - shouldRemoveHax = 1 homeDataPath, miiDataPath, homeHex, miiHex = "", "", 0x0, 0x0 def sanity(): From 6fce6dd967712a72e0afe2d2ac24722f773afb0a Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Sun, 15 Oct 2023 11:52:34 -0400 Subject: [PATCH 05/22] Remove unused error --- MSET9_installer_script/errors.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/MSET9_installer_script/errors.txt b/MSET9_installer_script/errors.txt index e881dd6..ccd723e 100644 --- a/MSET9_installer_script/errors.txt +++ b/MSET9_installer_script/errors.txt @@ -11,6 +11,5 @@ Error 10: Mismatched checksum. Redownload and Reextract MSET9 zip file. Error 11: Failed to initially enter the directory. This shouldn't happen pretty much ever. Error 12: Could not change back into SD directory. Ensure the SD Card has been reinserted. Error 13: Database problem. Follow the troubleshooting to reset the DBs. -Error 14: Invalid Id0. Ensure the length is 32 characters long. This shouldn't really happen. MSET9 Troublshooting Page: https://3ds.hacks.guide/troubleshooting#installing-boot9strap-mset9 \ No newline at end of file From f721ab727768d62fe331a4f9444961c2d1b4acf1 Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Sun, 15 Oct 2023 11:58:45 -0400 Subject: [PATCH 06/22] Move Sd card checks to before mode selection --- MSET9_installer_script/mset9.py | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/MSET9_installer_script/mset9.py b/MSET9_installer_script/mset9.py index 9066aee..3703a2a 100644 --- a/MSET9_installer_script/mset9.py +++ b/MSET9_installer_script/mset9.py @@ -19,13 +19,27 @@ def prinfo(content): print(f"[*] {content}") cwd = os.path.dirname(os.path.abspath(__file__)) -print(cwd) try: os.chdir(cwd) except Exception: prbad("Error 11: Failed to set cwd: " + cwd) exit(1) +# Section: insureRoot +if not os.path.exists("Nintendo 3DS/"): + prbad("Error 1: Are you sure you're running this script from the root of your SD card (right next to 'Nintendo 3DS')? You need to!") + prinfo(f"Current dir: {cwd}") + time.sleep(10) + sys.exit(0) + +# Section: sdWritable +writeable = os.access(cwd, os.W_OK) +if not writeable: + prbad("Error 2: Your sd is write protected! Please ensure the switch on the side of your SD card is facing upwards.") + prinfo("Visual aid: https://nintendohomebrew.com/assets/img/nhmemes/sdlock.png") + sys.exit(0) + + clearScreen() print(f"MSET9 {VERSION} SETUP by zoogie") print("What is your console model and version?") @@ -99,21 +113,6 @@ def prinfo(content): 0xB1: "TWN Region" } -# Section: insureRoot -if not os.path.exists("Nintendo 3DS/"): - prbad("Error 1: Are you sure you're running this script from the root of your SD card (right next to 'Nintendo 3DS')? You need to!") - prinfo(f"Current dir: {cwd}") - time.sleep(10) - sys.exit(0) - -# Section: sdWritable -writeable = os.access(cwd, os.W_OK) -if not writeable: - prbad("Error 2: Your sd is write protected! Please ensure the switch on the side of your SD card is facing upwards.") - prinfo("Visual aid: https://nintendohomebrew.com/assets/img/nhmemes/sdlock.png") - time.sleep(10) - sys.exit(0) - # Section: sdwalk for root, dirs, files in os.walk("Nintendo 3DS/", topdown=True): From 51d1e67d36f937b1067471a889faa76c717671ef Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Sun, 15 Oct 2023 16:12:03 -0400 Subject: [PATCH 07/22] Fix another round of blueness beating --- MSET9_installer_script/errors.txt | 23 +++-- MSET9_installer_script/mset9.bat | 1 + MSET9_installer_script/mset9.py | 138 ++++++++++++++++-------------- 3 files changed, 86 insertions(+), 76 deletions(-) diff --git a/MSET9_installer_script/errors.txt b/MSET9_installer_script/errors.txt index ccd723e..dd26e4d 100644 --- a/MSET9_installer_script/errors.txt +++ b/MSET9_installer_script/errors.txt @@ -1,15 +1,12 @@ -Error 1: Not running on the SD Card root. /Nintendo 3DS/ not found. -Error 2: Write protected SD Card. Ensure switch is facing up. -Error 3: Attempting to change target console version during exploit -Error 4: No Home Menu Extdata. Shouldn't happen pretty much ever. -Error 5: No Mii Maker Data, follow MSET9 Troublshooting page. -Error 6: Not running on the SD Card root. No ID0s detected. -Error 7: Multiple ID0s, follow MSET9 Troublshooting page. -Error 8: Missing expected file. Reextract MSET9 zip file. -Error 9: File size does not match expected. Reextract MSET9 zip file. -Error 10: Mismatched checksum. Redownload and Reextract MSET9 zip file. -Error 11: Failed to initially enter the directory. This shouldn't happen pretty much ever. -Error 12: Could not change back into SD directory. Ensure the SD Card has been reinserted. -Error 13: Database problem. Follow the troubleshooting to reset the DBs. +Error 01: Not running on the SD Card root. /Nintendo 3DS/ not found. +Error 02: Write protected SD Card. Ensure switch is facing up. +Error 03: Attempting to change target console version during exploit. +Error 04: No Home Menu Extdata. Shouldn't happen pretty much ever. +Error 05: No Mii Maker Data, follow MSET9 Troublshooting page. +Error 06: Not enough free space on disk. Clean out unused files. +Error 07: Multiple ID0s, follow MSET9 Troublshooting page. +Error 08: Missing/Malformed file. Reextract MSET9 zip file. +Error 09: Could not change back into SD directory. Ensure the SD Card has been reinserted. +Error 10: Database problem. Follow the troubleshooting to reset the DBs. MSET9 Troublshooting Page: https://3ds.hacks.guide/troubleshooting#installing-boot9strap-mset9 \ No newline at end of file diff --git a/MSET9_installer_script/mset9.bat b/MSET9_installer_script/mset9.bat index d15ac8d..1300d3c 100644 --- a/MSET9_installer_script/mset9.bat +++ b/MSET9_installer_script/mset9.bat @@ -1,3 +1,4 @@ +@echo off py -V > nul if %errorlevel% NEQ 0 ( echo Python 3 is not installed. diff --git a/MSET9_installer_script/mset9.py b/MSET9_installer_script/mset9.py index 3703a2a..d62ea15 100644 --- a/MSET9_installer_script/mset9.py +++ b/MSET9_installer_script/mset9.py @@ -1,5 +1,5 @@ #!/usr/bin/python3 -import os, sys, platform, time, shutil, binascii +import os, platform, time, shutil, binascii VERSION = "v1.1" @@ -18,27 +18,47 @@ def prbad(content): def prinfo(content): print(f"[*] {content}") +def exitOnEnter(errCode = 0): + input("[*] Press Enter to exit...") + exit(errCode) + cwd = os.path.dirname(os.path.abspath(__file__)) try: os.chdir(cwd) except Exception: - prbad("Error 11: Failed to set cwd: " + cwd) - exit(1) + prbad("Failed to set cwd: " + cwd) + prbad("This should pretty much never happen. try running the script again.") + exitOnEnter() # Section: insureRoot if not os.path.exists("Nintendo 3DS/"): - prbad("Error 1: Are you sure you're running this script from the root of your SD card (right next to 'Nintendo 3DS')? You need to!") + prbad("Error 01: Are you sure you're running this script from the root of your SD card (right next to 'Nintendo 3DS')? You need to!") prinfo(f"Current dir: {cwd}") time.sleep(10) - sys.exit(0) + exitOnEnter() # Section: sdWritable writeable = os.access(cwd, os.W_OK) +try: # Bodge for windows + with open("test.txt", "w") as f: + f.write("test") + f.close() + os.remove("test.txt") +except: + writeable = False + if not writeable: - prbad("Error 2: Your sd is write protected! Please ensure the switch on the side of your SD card is facing upwards.") + prbad("Error 02: Your sd is write protected! Please ensure the switch on the side of your SD card is facing upwards.") prinfo("Visual aid: https://nintendohomebrew.com/assets/img/nhmemes/sdlock.png") - sys.exit(0) + exitOnEnter() +# Section: SD card free space +# ensure 16MB free space +freeSpace = shutil.disk_usage(cwd).free +if freeSpace < 16777216: + prbad(f"Error 06: You need at least 16MB free space on your SD card, you have {(freeSpace / 1000000):.2f} bytes!") + prinfo("Please free up some space and try again.") + exitOnEnter() clearScreen() print(f"MSET9 {VERSION} SETUP by zoogie") @@ -58,7 +78,7 @@ def prinfo(content): except KeyboardInterrupt: print() prgood("Goodbye!") - exit() + exitOnEnter() except: sysModelVerSelect = 42 if sysModelVerSelect == 1: @@ -96,9 +116,9 @@ def prinfo(content): extdataRoot = "" realId1BackupTag = "_user-id1" -haxState = 0 # 0 setup state, 1 hax state id0Count = 0 id0List = [] +id1List = [] homeMenuExtdata = [0x8F, 0x98, 0x82, 0xA1, 0xA9, 0xB1] # us,eu,jp,ch,kr,tw miiMakerExtdata = [0x217, 0x227, 0x207, 0x267, 0x277, 0x287] # us,eu,jp,ch,kr,tw @@ -131,10 +151,11 @@ def prinfo(content): id1 = name id0 = root realId1Path = os.path.join(root, name) + id1List.append(realId1Path) if realId1BackupTag in name: - haxState = 1 - + prinfo("Restoring previous Id1 backup...") + os.rename(realId1Path, id0 + "/" + id1[:32]) # Otherwise, add it to the id0 list because we need to make sure we only have one id0 else: if len(name) == 32: @@ -145,13 +166,15 @@ def prinfo(content): if "sdmc" in name and len(name) == 32: # If the MSET9 folder doesn't match the proper haxid1 for the selected console version if hackedId1 != name: - prbad("Error 3: don't change console version in the middle of MSET9!") + prbad("Error 03: don't change console version in the middle of MSET9!") prbad("Make sure to run option 4, Remove MSET9 before you change modes!") - time.sleep(2) prinfo("Removing mismatched haxid1...") shutil.rmtree(os.path.join(root, name)) - prgood("done.") - time.sleep(3) + if os.path.exists(realId1Path) and realId1BackupTag in realId1Path: + prinfo("Renaming original Id1...") + os.rename(realId1Path, id0 + "/" + id1[:32]) + prgood("Done.") + homeDataPath, miiDataPath, homeHex, miiHex = "", "", 0x0, 0x0 def sanity(): @@ -163,11 +186,16 @@ def sanity(): prinfo("Performing sanity checks...") prinfo("Ensuring extracted files exist...") - check("boot9strap/boot9strap.firm", 0, 0x08129C1F) - check("boot.firm") - check("boot.3dsx") - check("b9") - check("SafeB9S.bin") + fileSanity = 0 + fileSanity += softcheck("boot9strap/boot9strap.firm", 0, 0x08129C1F, 1) + fileSanity += softcheck("boot.firm", retval = 1) + fileSanity += softcheck("boot.3dsx", retval = 1) + fileSanity += softcheck("b9", retval = 1) + fileSanity += softcheck("SafeB9S.bin", retval = 1) + if fileSanity > 0: + prbad("Error 08: One or more files are missing or malformed!") + prinfo("Please extract the MSET9 zip file again, being sure to Overwrite any files.") + exitOnEnter() prgood("All files look good!") prinfo("Checking databases...") @@ -189,7 +217,7 @@ def sanity(): prinfo("Created empty databases.") prinfo("please reset the database files in settings -> data management -> nintendo 3ds -> software first before coming back!") prinfo("Visual guide: https://3ds.hacks.guide/images/screenshots/database-reset.jpg") - sys.exit(0) + exitOnEnter() else: prgood("Databases look good!") @@ -210,10 +238,10 @@ def sanity(): break if not menuExtdataGood: - prbad("Error 4: No Home Menu Data!") + prbad("Error 04: No Home Menu Data!") prinfo("This shouldn't really happen, Put the sd card back in your console.") prinfo("Turn it on and off again, then restart the script.") - sys.exit(0) + exitOnEnter() prinfo("Checking for mii maker extdata...") for i in miiMakerExtdata: @@ -226,9 +254,9 @@ def sanity(): break if not miiExtdataGood: - prbad("Err 5: No Mii Maker Data!") + prbad("Error 05: No Mii Maker Data!") prinfo("Please go to https://3ds.hacks.guide/troubleshooting#installing-boot9strap-mset9 for instructions.") - sys.exit(0) + exitOnEnter() def injection(): global realId1Path, id1 @@ -251,6 +279,13 @@ def injection(): shutil.copytree(homeDataPath, hackedId1Path + f"/extdata/00000000/{homeHex:08X}") shutil.copytree(miiDataPath, hackedId1Path + f"/extdata/00000000/{miiHex:08X}") + prinfo("Injecting trigger file...") + triggerFilePath = id0 + "/" + hackedId1 + "/extdata/" + trigger + if not os.path.exists(triggerFilePath): + with open(triggerFilePath, "w") as f: + f.write("plz be haxxed mister arm9, thx") + f.close() + if os.path.exists(realId1Path): prinfo("Backing up real Id1...") os.rename(realId1Path, realId1Path + realId1BackupTag) @@ -258,12 +293,6 @@ def injection(): id1 += realId1BackupTag realId1Path = f"{id0}/{id1}" - prinfo("Injecting trigger file...") - triggerFilePath = id0 + "/" + hackedId1 + "/extdata/" + trigger - if not os.path.exists(triggerFilePath): - with open(triggerFilePath, "w") as f: - f.write("plz be haxxed mister arm9, thx") - f.close() prgood("Done.") def delete(): @@ -275,7 +304,7 @@ def delete(): prinfo("Nothing to remove!") def remove(): - global haxState, realId1Path, id0, id1 + global realId1Path, id0, id1 prinfo("Removing MSET9...") if not os.path.exists(id0 + "/" + hackedId1) and (os.path.exists(realId1Path) and realId1BackupTag not in realId1Path): prinfo("Nothing to remove!") @@ -290,10 +319,9 @@ def remove(): shutil.rmtree(id0 + "/" + hackedId1) id1 = id1[:32] realId1Path = id0 + "/" + id1 - haxState = 0 prgood("done.") -def softcheck(keyfile, expectedSize, crc32, retval): +def softcheck(keyfile, expectedSize = None, crc32 = None, retval = 0): shortname = keyfile.rsplit("/")[-1] if not os.path.exists(keyfile): prbad(f"{shortname} does not exist on SD card!") @@ -314,43 +342,21 @@ def softcheck(keyfile, expectedSize, crc32, retval): prgood(f"{shortname} looks good!") return 0 -def check(keyfile, expectedSize = None, crc32 = None): - shortname = keyfile.rsplit("/")[-1] - if not os.path.exists(keyfile): - prbad(f"Error 8: {shortname} does not exist on SD card!") - prinfo("Please extract the MSET9 zip file again, being sure to Overwrite any files.") - sys.exit(0) - elif expectedSize: - fileSize = os.path.getsize(keyfile) - if expectedSize != fileSize: - prbad(f"Error 9: {shortname} is size {fileSize:,} bytes, not expected {expectedSize:,} bytes") - prinfo("Please extract the MSET9 zip file again, being sure to Overwrite any files.") - sys.exit(0) - elif crc32: - with open(keyfile, "rb") as f: - checksum = binascii.crc32(f.read()) - if crc32 != checksum: - prbad(f"Error 10: {shortname} was not recognized as the correct file") - prinfo("Please extract the MSET9 zip file again, being sure to Overwrite any files.") - f.close() - sys.exit(0) - f.close() - prinfo("Detected ID0(s):") for i in id0List: prinfo(i) print() if id0Count != 1: - prbad(f"Error 7: You don't have 1 ID0 in your Nintendo 3DS folder, you have {id0Count}!") - prinfo("Consult:\nhttps://3ds.hacks.guide/troubleshooting#installing-boot9strap-mset9\nfor help!") - sys.exit(0) + prbad(f"Error 07: You don't have 1 ID0 in your Nintendo 3DS folder, you have {id0Count}!") + prinfo("Consult: https://3ds.hacks.guide/troubleshooting#installing-boot9strap-mset9 for help!") + exitOnEnter() def reapplyWorkingDir(): try: os.chdir(cwd) return True except Exception: - prbad("Error 12: Couldn't reapply cwd, is sdcard reinserted?") + prbad("Error 09: Couldn't reapply working directory, is sdcard reinserted?") return False clearScreen() @@ -373,20 +379,26 @@ def reapplyWorkingDir(): except: sysModelVerSelect = 42 - # Separated to maybe fix removable bug - if not reapplyWorkingDir(): - continue #already prints error if fail + try: + os.chdir(cwd) + except Exception: + prbad("Error 09: Couldn't reapply working directory, is sdcard reinserted?") + exitOnEnter() if sysModelVerSelect == 1: sanity() prgood("Looking good!\n") + exitOnEnter() elif sysModelVerSelect == 2: sanity() injection() + exitOnEnter() elif sysModelVerSelect == 3: delete() + exitOnEnter() elif sysModelVerSelect == 4: remove() + exitOnEnter() elif sysModelVerSelect == 5 or "exit": prgood("Goodbye!") break From 4671166b5c0f04371d1b918400b11f9c083c3574 Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Sun, 15 Oct 2023 16:41:44 -0400 Subject: [PATCH 08/22] This probably definitely doesn't work i'll just wait for testers --- MSET9_installer_script/mset9.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/MSET9_installer_script/mset9.py b/MSET9_installer_script/mset9.py index d62ea15..dbef419 100644 --- a/MSET9_installer_script/mset9.py +++ b/MSET9_installer_script/mset9.py @@ -153,9 +153,6 @@ def exitOnEnter(errCode = 0): realId1Path = os.path.join(root, name) id1List.append(realId1Path) - if realId1BackupTag in name: - prinfo("Restoring previous Id1 backup...") - os.rename(realId1Path, id0 + "/" + id1[:32]) # Otherwise, add it to the id0 list because we need to make sure we only have one id0 else: if len(name) == 32: From 5ce65272c9369f938721b137ff7486c9b068f89d Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Mon, 16 Oct 2023 10:21:57 -0400 Subject: [PATCH 09/22] Fix probably second to last round of Blueness bugs --- MSET9_installer_script/errors.txt | 2 + MSET9_installer_script/mset9.py | 121 ++++++++++++++++-------------- 2 files changed, 67 insertions(+), 56 deletions(-) diff --git a/MSET9_installer_script/errors.txt b/MSET9_installer_script/errors.txt index dd26e4d..5256d33 100644 --- a/MSET9_installer_script/errors.txt +++ b/MSET9_installer_script/errors.txt @@ -8,5 +8,7 @@ Error 07: Multiple ID0s, follow MSET9 Troublshooting page. Error 08: Missing/Malformed file. Reextract MSET9 zip file. Error 09: Could not change back into SD directory. Ensure the SD Card has been reinserted. Error 10: Database problem. Follow the troubleshooting to reset the DBs. +Error 11: Running as MacOS. MacOS is not supported. +Error 12: Multiple ID1s, follow MSET9 Troublshooting page. MSET9 Troublshooting Page: https://3ds.hacks.guide/troubleshooting#installing-boot9strap-mset9 \ No newline at end of file diff --git a/MSET9_installer_script/mset9.py b/MSET9_installer_script/mset9.py index dbef419..11bdaf2 100644 --- a/MSET9_installer_script/mset9.py +++ b/MSET9_installer_script/mset9.py @@ -3,12 +3,6 @@ VERSION = "v1.1" -def clearScreen(): - if platform.system() == "Windows": - os.system("cls") - else: - os.system("clear") - def prgood(content): print(f"[\033[0;32m✓\033[0m] {content}") @@ -22,6 +16,19 @@ def exitOnEnter(errCode = 0): input("[*] Press Enter to exit...") exit(errCode) +osver = platform.system() + +if osver == "Darwin": + prbad("Error 11: macOS is not supported!") + prinfo("Please use a Windows or Linux computer.") + exitOnEnter() + +def clearScreen(): + if osver == "Windows": + os.system("cls") + else: + os.system("clear") + cwd = os.path.dirname(os.path.abspath(__file__)) try: os.chdir(cwd) @@ -117,8 +124,8 @@ def exitOnEnter(errCode = 0): extdataRoot = "" realId1BackupTag = "_user-id1" id0Count = 0 +id1Count = 0 id0List = [] -id1List = [] homeMenuExtdata = [0x8F, 0x98, 0x82, 0xA1, 0xA9, 0xB1] # us,eu,jp,ch,kr,tw miiMakerExtdata = [0x217, 0x227, 0x207, 0x267, 0x277, 0x287] # us,eu,jp,ch,kr,tw @@ -131,47 +138,7 @@ def exitOnEnter(errCode = 0): 0xA1: "CHN Region", 0xA9: "KOR Region", 0xB1: "TWN Region" -} - -# Section: sdwalk -for root, dirs, files in os.walk("Nintendo 3DS/", topdown=True): - - for name in dirs: - # If the name doesn't contain sdmc (Ignores MSET9 exploit folder) - if "sdmc" not in name and len(name[:32]) == 32: - try: - # Check to see if the file name encodes as an int (is hex only) - hexVerify = int(name[:32], 16) - except: - continue - if type(hexVerify) is int: - # Check if the folder (which is either id1 or id0) has the extdata folder - # if it does, it's an id1 folder - if os.path.exists(os.path.join(root, name) + "/extdata"): - id1 = name - id0 = root - realId1Path = os.path.join(root, name) - id1List.append(realId1Path) - - # Otherwise, add it to the id0 list because we need to make sure we only have one id0 - else: - if len(name) == 32: - id0Count += 1 - id0List.append(os.path.join(root, name)) - - # CHeck if we have an MSET9 Hacked id1 folder - if "sdmc" in name and len(name) == 32: - # If the MSET9 folder doesn't match the proper haxid1 for the selected console version - if hackedId1 != name: - prbad("Error 03: don't change console version in the middle of MSET9!") - prbad("Make sure to run option 4, Remove MSET9 before you change modes!") - prinfo("Removing mismatched haxid1...") - shutil.rmtree(os.path.join(root, name)) - if os.path.exists(realId1Path) and realId1BackupTag in realId1Path: - prinfo("Renaming original Id1...") - os.rename(realId1Path, id0 + "/" + id1[:32]) - prgood("Done.") - +} homeDataPath, miiDataPath, homeHex, miiHex = "", "", 0x0, 0x0 def sanity(): @@ -199,7 +166,7 @@ def sanity(): checkTitledb = softcheck(realId1Path + "/dbs/title.db", 0x31E400, 0, 1) checkImportdb = softcheck(realId1Path + "/dbs/import.db", 0x31E400, 0, 1) if checkTitledb or checkImportdb: - prbad("Error 13: Database(s) malformed or missing!") + prbad("Error 10: Database(s) malformed or missing!") if not ( os.path.exists(realId1Path + "/dbs/import.db") or os.path.exists(realId1Path + "/dbs/title.db") @@ -238,6 +205,7 @@ def sanity(): prbad("Error 04: No Home Menu Data!") prinfo("This shouldn't really happen, Put the sd card back in your console.") prinfo("Turn it on and off again, then restart the script.") + prinfo("For assistance, come visit us: https://discord.gg/nintendohomebrew") exitOnEnter() prinfo("Checking for mii maker extdata...") @@ -339,6 +307,50 @@ def softcheck(keyfile, expectedSize = None, crc32 = None, retval = 0): prgood(f"{shortname} looks good!") return 0 +def reapplyWorkingDir(): + try: + os.chdir(cwd) + return True + except Exception: + prbad("Error 09: Couldn't reapply working directory, is sdcard reinserted?") + return False + +# Section: sdwalk +for root, dirs, files in os.walk("Nintendo 3DS/", topdown=True): + + for name in dirs: + # If the name doesn't contain sdmc (Ignores MSET9 exploit folder) + if "sdmc" not in name and len(name[:32]) == 32: + try: + # Check to see if the file name encodes as an int (is hex only) + hexVerify = int(name[:32], 16) + except: + continue + if type(hexVerify) is int: + # Check if the folder (which is either id1 or id0) has the extdata folder + # if it does, it's an id1 folder + if os.path.exists(os.path.join(root, name) + "/extdata"): + id1Count += 1 + id1 = name + id0 = root + realId1Path = os.path.join(root, name) + + # Otherwise, add it to the id0 list because we need to make sure we only have one id0 + else: + if len(name) == 32: + id0Count += 1 + id0List.append(os.path.join(root, name)) + + # CHeck if we have an MSET9 Hacked id1 folder + if "sdmc" in name and len(name) == 32: + # If the MSET9 folder doesn't match the proper haxid1 for the selected console version + if hackedId1 != name: + prbad("Error 03: don't change console version in the middle of MSET9!") + prbad("Please restart the setup.") + remove() + exitOnEnter() + + prinfo("Detected ID0(s):") for i in id0List: prinfo(i) @@ -348,13 +360,10 @@ def softcheck(keyfile, expectedSize = None, crc32 = None, retval = 0): prinfo("Consult: https://3ds.hacks.guide/troubleshooting#installing-boot9strap-mset9 for help!") exitOnEnter() -def reapplyWorkingDir(): - try: - os.chdir(cwd) - return True - except Exception: - prbad("Error 09: Couldn't reapply working directory, is sdcard reinserted?") - return False +if id1Count != 1: + prbad(f"Error 12: You don't have 1 ID1 in your Nintendo 3DS folder, you have {id1Count}!") + prinfo("Consult: https://3ds.hacks.guide/troubleshooting#installing-boot9strap-mset9 for help!") + exitOnEnter() clearScreen() print(f"MSET9 {VERSION} SETUP by zoogie") From e1ac1f106a00ea0833a544fb5c3670bb93a38c2d Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Mon, 16 Oct 2023 11:10:06 -0400 Subject: [PATCH 10/22] Attempt to remove all hacked Id1s on removal --- MSET9_installer_script/mset9.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/MSET9_installer_script/mset9.py b/MSET9_installer_script/mset9.py index 11bdaf2..1f874cf 100644 --- a/MSET9_installer_script/mset9.py +++ b/MSET9_installer_script/mset9.py @@ -78,6 +78,12 @@ def clearScreen(): print("3. Old 3DS, 11.4.0 to 11.7.0") print("4. New 3DS, 11.4.0 to 11.7.0") +encodedId1s = { + 1: "FFFFFFFA119907488546696508A10122054B984768465946C0AA171C4346034CA047B84700900A0871A0050899CE0408730064006D00630000900A0862003900", + 2: "FFFFFFFA119907488546696508A10122054B984768465946C0AA171C4346034CA047B84700900A0871A005085DCE0408730064006D00630000900A0862003900", + 3: "FFFFFFFA119907488546696508A10122054B984768465946C0AA171C4346034CA047B84700900A08499E050899CC0408730064006D00630000900A0862003900", + 4: "FFFFFFFA119907488546696508A10122054B984768465946C0AA171C4346034CA047B84700900A08459E050881CC0408730064006D00630000900A0862003900" +} hackedId1Encoded, consoleModel, consoleFirmware = "", "", "" while 1: try: @@ -89,25 +95,25 @@ def clearScreen(): except: sysModelVerSelect = 42 if sysModelVerSelect == 1: - hackedId1Encoded = "FFFFFFFA119907488546696508A10122054B984768465946C0AA171C4346034CA047B84700900A0871A0050899CE0408730064006D00630000900A0862003900" + hackedId1Encoded = encodedId1s[1] consoleModel = "OLD3DS" consoleFirmware = "11.8-11.17" break if sysModelVerSelect == 2: - hackedId1Encoded = "FFFFFFFA119907488546696508A10122054B984768465946C0AA171C4346034CA047B84700900A0871A005085DCE0408730064006D00630000900A0862003900" + hackedId1Encoded = encodedId1s[2] consoleModel = "NEW3DS" consoleFirmware = "11.8-11.17" break if sysModelVerSelect == 3: - hackedId1Encoded = "FFFFFFFA119907488546696508A10122054B984768465946C0AA171C4346034CA047B84700900A08499E050899CC0408730064006D00630000900A0862003900" + hackedId1Encoded = encodedId1s[3] consoleModel = "OLD3DS" consoleFirmware = "11.4-11.7" break if sysModelVerSelect == 4: - hackedId1Encoded = "FFFFFFFA119907488546696508A10122054B984768465946C0AA171C4346034CA047B84700900A08459E050881CC0408730064006D00630000900A0862003900" + hackedId1Encoded = encodedId1s[4] consoleModel = "NEW3DS" consoleFirmware = "11.4-11.7" break @@ -279,9 +285,10 @@ def remove(): prinfo("Renaming original Id1...") os.rename(realId1Path, id0 + "/" + id1[:32]) # print(id1_path, id1_root+"/"+id1[:32]) - if os.path.exists(id0 + "/" + hackedId1): - prinfo("Deleting hacked Id1...") - shutil.rmtree(id0 + "/" + hackedId1) + for id1Index in range(1,5): # Attempt to remove *all* hacked id1s + if os.path.exists(id0 + "/" + bytes.fromhex(encodedId1s[id1Index]).decode("utf-16le")): + prinfo("Deleting hacked Id1...") + shutil.rmtree(id0 + "/" + hackedId1) id1 = id1[:32] realId1Path = id0 + "/" + id1 prgood("done.") From 4d174663c14110c464fdfb685c22bbe37318007d Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Mon, 16 Oct 2023 12:08:17 -0400 Subject: [PATCH 11/22] Clarify Error 01 --- MSET9_installer_script/mset9.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MSET9_installer_script/mset9.py b/MSET9_installer_script/mset9.py index 1f874cf..0e98c66 100644 --- a/MSET9_installer_script/mset9.py +++ b/MSET9_installer_script/mset9.py @@ -39,7 +39,8 @@ def clearScreen(): # Section: insureRoot if not os.path.exists("Nintendo 3DS/"): - prbad("Error 01: Are you sure you're running this script from the root of your SD card (right next to 'Nintendo 3DS')? You need to!") + prbad("Error 01: Couldn't find Nintendo 3DS folder! eject the SD card, and put it back in your console.") + prbad("Turn it on and off again, then restart the script.") prinfo(f"Current dir: {cwd}") time.sleep(10) exitOnEnter() From 6e54ae296c4d497dbb461c9b2d524c3cc0d4dc10 Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Mon, 16 Oct 2023 14:13:07 -0400 Subject: [PATCH 12/22] Fix option 4 and clarify error 1 again --- MSET9_installer_script/mset9.bat | 1 + MSET9_installer_script/mset9.py | 16 ++++++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/MSET9_installer_script/mset9.bat b/MSET9_installer_script/mset9.bat index 1300d3c..868b29b 100644 --- a/MSET9_installer_script/mset9.bat +++ b/MSET9_installer_script/mset9.bat @@ -1,4 +1,5 @@ @echo off +chcp 65001 py -V > nul if %errorlevel% NEQ 0 ( echo Python 3 is not installed. diff --git a/MSET9_installer_script/mset9.py b/MSET9_installer_script/mset9.py index 0e98c66..85d9010 100644 --- a/MSET9_installer_script/mset9.py +++ b/MSET9_installer_script/mset9.py @@ -40,7 +40,7 @@ def clearScreen(): # Section: insureRoot if not os.path.exists("Nintendo 3DS/"): prbad("Error 01: Couldn't find Nintendo 3DS folder! eject the SD card, and put it back in your console.") - prbad("Turn it on and off again, then restart the script.") + prbad("Turn it on and off again, then restart the script. Make sure you are running in the SD Card root!") prinfo(f"Current dir: {cwd}") time.sleep(10) exitOnEnter() @@ -248,8 +248,10 @@ def injection(): shutil.copytree(realId1Path + "/dbs", hackedId1Path + "/dbs") prinfo("Copying extdata to hacked Id1...") - shutil.copytree(homeDataPath, hackedId1Path + f"/extdata/00000000/{homeHex:08X}") - shutil.copytree(miiDataPath, hackedId1Path + f"/extdata/00000000/{miiHex:08X}") + if not os.path.exists(hackedId1Path + f"/extdata/00000000/{homeHex:08X}"): + shutil.copytree(homeDataPath, hackedId1Path + f"/extdata/00000000/{homeHex:08X}") + if not os.path.exists(hackedId1Path + f"/extdata/00000000/{miiHex:08X}"): + shutil.copytree(miiDataPath, hackedId1Path + f"/extdata/00000000/{miiHex:08X}") prinfo("Injecting trigger file...") triggerFilePath = id0 + "/" + hackedId1 + "/extdata/" + trigger @@ -287,9 +289,10 @@ def remove(): os.rename(realId1Path, id0 + "/" + id1[:32]) # print(id1_path, id1_root+"/"+id1[:32]) for id1Index in range(1,5): # Attempt to remove *all* hacked id1s - if os.path.exists(id0 + "/" + bytes.fromhex(encodedId1s[id1Index]).decode("utf-16le")): + maybeHackedId = bytes.fromhex(encodedId1s[id1Index]).decode("utf-16le") + if os.path.exists(id0 + "/" + maybeHackedId): prinfo("Deleting hacked Id1...") - shutil.rmtree(id0 + "/" + hackedId1) + shutil.rmtree(id0 + "/" + maybeHackedId) id1 = id1[:32] realId1Path = id0 + "/" + id1 prgood("done.") @@ -349,9 +352,10 @@ def reapplyWorkingDir(): id0Count += 1 id0List.append(os.path.join(root, name)) + for name in dirs: # Run the check for existing install after figuring out the structure # CHeck if we have an MSET9 Hacked id1 folder if "sdmc" in name and len(name) == 32: - # If the MSET9 folder doesn't match the proper haxid1 for the selected console version + # If the MSET9 folder doesn't match the proper haxid1 for the selected console version if hackedId1 != name: prbad("Error 03: don't change console version in the middle of MSET9!") prbad("Please restart the setup.") From 9d347909ede49e2dc6c92e1ae69ebc86b0045b39 Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Mon, 16 Oct 2023 14:39:04 -0400 Subject: [PATCH 13/22] Make menus clearer hopefully --- MSET9_installer_script/mset9.bat | 2 +- MSET9_installer_script/mset9.py | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/MSET9_installer_script/mset9.bat b/MSET9_installer_script/mset9.bat index 868b29b..a7929bf 100644 --- a/MSET9_installer_script/mset9.bat +++ b/MSET9_installer_script/mset9.bat @@ -1,5 +1,5 @@ @echo off -chcp 65001 +chcp 65001 > nul py -V > nul if %errorlevel% NEQ 0 ( echo Python 3 is not installed. diff --git a/MSET9_installer_script/mset9.py b/MSET9_installer_script/mset9.py index 85d9010..63e9432 100644 --- a/MSET9_installer_script/mset9.py +++ b/MSET9_installer_script/mset9.py @@ -74,6 +74,7 @@ def clearScreen(): print("Old 3DS has two shoulder buttons (L and R)") print("New 3DS has four shoulder buttons (L, R, ZL, ZR)") print("\n-- Please type in a number then hit return --\n") +print("↓ Input one of these Numbers!") print("1. Old 3DS, 11.8.0 to 11.17.0") print("2. New 3DS, 11.8.0 to 11.17.0") print("3. Old 3DS, 11.4.0 to 11.7.0") @@ -88,7 +89,11 @@ def clearScreen(): hackedId1Encoded, consoleModel, consoleFirmware = "", "", "" while 1: try: - sysModelVerSelect = int(input(">>> ")) + sysModelVerSelect = input(">>> ") + if sysModelVerSelect.startswith("11"): + prbad("Don't type the firmware version, just the selection number!") + sysModelVerSelect = 42 + sysModelVerSelect = int(sysModelVerSelect) except KeyboardInterrupt: print() prgood("Goodbye!") @@ -120,7 +125,7 @@ def clearScreen(): break else: - print("Invalid input, try again.") + prbad("Invalid input, try again.") trigger = "002F003A.txt" # all 3ds ":/" in hex hackedId1 = bytes.fromhex(hackedId1Encoded).decode("utf-16le") # ID1 - arm injected payload in readable format @@ -382,6 +387,7 @@ def reapplyWorkingDir(): print(f"Using {consoleModel} {consoleFirmware}") print("\n-- Please type in a number then hit return --\n") +print("↓ Input one of these Numbers!") print("1. Perform sanity checks") print("2. Inject MSET9 exploit") print(f"3. Delete trigger file {trigger}") From b306ed386a0a117b2a91bcf14fbb455008780048 Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Mon, 16 Oct 2023 14:42:52 -0400 Subject: [PATCH 14/22] Change language a bit --- MSET9_installer_script/mset9.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MSET9_installer_script/mset9.py b/MSET9_installer_script/mset9.py index 63e9432..a3f072b 100644 --- a/MSET9_installer_script/mset9.py +++ b/MSET9_installer_script/mset9.py @@ -69,7 +69,7 @@ def clearScreen(): exitOnEnter() clearScreen() -print(f"MSET9 {VERSION} SETUP by zoogie") +print(f"MSET9 {VERSION} SETUP by zoogie and Aven") print("What is your console model and version?") print("Old 3DS has two shoulder buttons (L and R)") print("New 3DS has four shoulder buttons (L, R, ZL, ZR)") @@ -159,7 +159,7 @@ def sanity(): miiExtdataGood = False print() - prinfo("Performing sanity checks...") + prinfo("Performing validation checks...") prinfo("Ensuring extracted files exist...") fileSanity = 0 @@ -383,12 +383,12 @@ def reapplyWorkingDir(): exitOnEnter() clearScreen() -print(f"MSET9 {VERSION} SETUP by zoogie") +print(f"MSET9 {VERSION} SETUP by zoogie and Aven") print(f"Using {consoleModel} {consoleFirmware}") print("\n-- Please type in a number then hit return --\n") print("↓ Input one of these Numbers!") -print("1. Perform sanity checks") +print("1. Perform validation checks") print("2. Inject MSET9 exploit") print(f"3. Delete trigger file {trigger}") print("4. Manually Remove MSET9") From b781528d4f37ff66c345758f37c858568625cbcf Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Tue, 17 Oct 2023 13:21:16 -0400 Subject: [PATCH 15/22] Make end of sections clearer for guide purposes --- MSET9_installer_script/mset9.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/MSET9_installer_script/mset9.py b/MSET9_installer_script/mset9.py index a3f072b..13c0a7e 100644 --- a/MSET9_installer_script/mset9.py +++ b/MSET9_installer_script/mset9.py @@ -159,7 +159,7 @@ def sanity(): miiExtdataGood = False print() - prinfo("Performing validation checks...") + prinfo("Performing sanity checks...") prinfo("Ensuring extracted files exist...") fileSanity = 0 @@ -272,7 +272,7 @@ def injection(): id1 += realId1BackupTag realId1Path = f"{id0}/{id1}" - prgood("Done.") + prgood("MSET9 successfully injected!") def delete(): prinfo("Deleting trigger file...") @@ -285,9 +285,6 @@ def delete(): def remove(): global realId1Path, id0, id1 prinfo("Removing MSET9...") - if not os.path.exists(id0 + "/" + hackedId1) and (os.path.exists(realId1Path) and realId1BackupTag not in realId1Path): - prinfo("Nothing to remove!") - return if os.path.exists(realId1Path) and realId1BackupTag in realId1Path: prinfo("Renaming original Id1...") @@ -300,7 +297,7 @@ def remove(): shutil.rmtree(id0 + "/" + maybeHackedId) id1 = id1[:32] realId1Path = id0 + "/" + id1 - prgood("done.") + prgood("Successfully removed MSET9!") def softcheck(keyfile, expectedSize = None, crc32 = None, retval = 0): shortname = keyfile.rsplit("/")[-1] @@ -388,7 +385,7 @@ def reapplyWorkingDir(): print("\n-- Please type in a number then hit return --\n") print("↓ Input one of these Numbers!") -print("1. Perform validation checks") +print("1. Perform sanity checks") print("2. Inject MSET9 exploit") print(f"3. Delete trigger file {trigger}") print("4. Manually Remove MSET9") @@ -411,7 +408,7 @@ def reapplyWorkingDir(): if sysModelVerSelect == 1: sanity() - prgood("Looking good!\n") + prgood("Everything appears to be functional!\n") exitOnEnter() elif sysModelVerSelect == 2: sanity() From 21ef45054f558b1c48e63c33dd8941e8a5d52705 Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Tue, 17 Oct 2023 14:15:04 -0400 Subject: [PATCH 16/22] Remove deleting trigger file --- MSET9_installer_script/mset9.py | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/MSET9_installer_script/mset9.py b/MSET9_installer_script/mset9.py index 13c0a7e..bf9e101 100644 --- a/MSET9_installer_script/mset9.py +++ b/MSET9_installer_script/mset9.py @@ -39,10 +39,9 @@ def clearScreen(): # Section: insureRoot if not os.path.exists("Nintendo 3DS/"): - prbad("Error 01: Couldn't find Nintendo 3DS folder! eject the SD card, and put it back in your console.") - prbad("Turn it on and off again, then restart the script. Make sure you are running in the SD Card root!") + prbad("Error 01: Couldn't find Nintendo 3DS folder! Make sure you are running in the SD Card root!") + prbad("If that doesn't work, eject the SD card, and put it back in your console. Turn it on and off again, then restart the script.") prinfo(f"Current dir: {cwd}") - time.sleep(10) exitOnEnter() # Section: sdWritable @@ -274,14 +273,6 @@ def injection(): prgood("MSET9 successfully injected!") -def delete(): - prinfo("Deleting trigger file...") - triggerFilePath = id0 + "/" + hackedId1 + "/extdata/" + trigger - if os.path.exists(triggerFilePath): - os.remove(triggerFilePath) - prgood("done.") - prinfo("Nothing to remove!") - def remove(): global realId1Path, id0, id1 prinfo("Removing MSET9...") @@ -386,10 +377,9 @@ def reapplyWorkingDir(): print("\n-- Please type in a number then hit return --\n") print("↓ Input one of these Numbers!") print("1. Perform sanity checks") -print("2. Inject MSET9 exploit") -print(f"3. Delete trigger file {trigger}") -print("4. Manually Remove MSET9") -print("5. Exit") +print("2. Inject MSET9 payload") +print("3. Remove MSET9") +print("4. Exit") while 1: try: @@ -415,12 +405,9 @@ def reapplyWorkingDir(): injection() exitOnEnter() elif sysModelVerSelect == 3: - delete() - exitOnEnter() - elif sysModelVerSelect == 4: remove() exitOnEnter() - elif sysModelVerSelect == 5 or "exit": + elif sysModelVerSelect == 4 or "exit": prgood("Goodbye!") break else: From 0887084cf3891203c8e3247f7663685592c0e2f9 Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Tue, 17 Oct 2023 14:23:57 -0400 Subject: [PATCH 17/22] Fix control+C on second menu --- MSET9_installer_script/mset9.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MSET9_installer_script/mset9.py b/MSET9_installer_script/mset9.py index bf9e101..78bbfca 100644 --- a/MSET9_installer_script/mset9.py +++ b/MSET9_installer_script/mset9.py @@ -385,7 +385,7 @@ def reapplyWorkingDir(): try: sysModelVerSelect = int(input(">>> ")) except KeyboardInterrupt: - sysModelVerSelect = 5 # exit on Ctrl+C + sysModelVerSelect = 4 # exit on Ctrl+C print() except: sysModelVerSelect = 42 From c3231ffe736fd00e3c14583865611043fd0689fb Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Tue, 17 Oct 2023 14:34:16 -0400 Subject: [PATCH 18/22] Check write protect again because blueness --- MSET9_installer_script/mset9.py | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/MSET9_installer_script/mset9.py b/MSET9_installer_script/mset9.py index 78bbfca..55bf8ba 100644 --- a/MSET9_installer_script/mset9.py +++ b/MSET9_installer_script/mset9.py @@ -45,19 +45,23 @@ def clearScreen(): exitOnEnter() # Section: sdWritable -writeable = os.access(cwd, os.W_OK) -try: # Bodge for windows - with open("test.txt", "w") as f: - f.write("test") - f.close() - os.remove("test.txt") -except: - writeable = False - -if not writeable: - prbad("Error 02: Your sd is write protected! Please ensure the switch on the side of your SD card is facing upwards.") - prinfo("Visual aid: https://nintendohomebrew.com/assets/img/nhmemes/sdlock.png") - exitOnEnter() +def writeProtectCheck(): + prinfo("Checking if SD card is writeable...") + writeable = os.access(cwd, os.W_OK) + try: # Bodge for windows + with open("test.txt", "w") as f: + f.write("test") + f.close() + os.remove("test.txt") + except: + writeable = False + + if not writeable: + prbad("Error 02: Your sd is write protected! Please ensure the switch on the side of your SD card is facing upwards.") + prinfo("Visual aid: https://nintendohomebrew.com/assets/img/nhmemes/sdlock.png") + exitOnEnter() + else: + prgood("SD card is writeable!") # Section: SD card free space # ensure 16MB free space @@ -160,6 +164,8 @@ def sanity(): print() prinfo("Performing sanity checks...") + writeProtectCheck() + prinfo("Ensuring extracted files exist...") fileSanity = 0 fileSanity += softcheck("boot9strap/boot9strap.firm", 0, 0x08129C1F, 1) From 93fc4c78dd4d6f683ae8376666a6139d13b9f527 Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Tue, 17 Oct 2023 14:41:56 -0400 Subject: [PATCH 19/22] Readd nothing to remove message --- MSET9_installer_script/mset9.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MSET9_installer_script/mset9.py b/MSET9_installer_script/mset9.py index 55bf8ba..c0457c7 100644 --- a/MSET9_installer_script/mset9.py +++ b/MSET9_installer_script/mset9.py @@ -286,6 +286,10 @@ def remove(): if os.path.exists(realId1Path) and realId1BackupTag in realId1Path: prinfo("Renaming original Id1...") os.rename(realId1Path, id0 + "/" + id1[:32]) + else: + prgood("Nothing to remove!") + return + # print(id1_path, id1_root+"/"+id1[:32]) for id1Index in range(1,5): # Attempt to remove *all* hacked id1s maybeHackedId = bytes.fromhex(encodedId1s[id1Index]).decode("utf-16le") From ed59a7e5b674121a1a1411fecd2ef08f841ca6e9 Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Tue, 17 Oct 2023 14:51:54 -0400 Subject: [PATCH 20/22] Fix appending backup a zillion times --- MSET9_installer_script/mset9.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/MSET9_installer_script/mset9.py b/MSET9_installer_script/mset9.py index c0457c7..cbd097a 100644 --- a/MSET9_installer_script/mset9.py +++ b/MSET9_installer_script/mset9.py @@ -272,10 +272,13 @@ def injection(): if os.path.exists(realId1Path): prinfo("Backing up real Id1...") - os.rename(realId1Path, realId1Path + realId1BackupTag) - - id1 += realId1BackupTag - realId1Path = f"{id0}/{id1}" + if not os.path.exists(realId1Path + realId1BackupTag): + os.rename(realId1Path, realId1Path + realId1BackupTag) + id1 += realId1BackupTag + realId1Path = f"{id0}/{id1}" + else: + prinfo("Skipping backup because a backup already exists!") + prgood("MSET9 successfully injected!") From 23e0fe6118a95591e5683b5a1fb3081e387acb32 Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Tue, 17 Oct 2023 14:56:10 -0400 Subject: [PATCH 21/22] Fix appending backup a zillion times but for real --- MSET9_installer_script/mset9.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/MSET9_installer_script/mset9.py b/MSET9_installer_script/mset9.py index cbd097a..1f68aba 100644 --- a/MSET9_installer_script/mset9.py +++ b/MSET9_installer_script/mset9.py @@ -270,14 +270,13 @@ def injection(): f.write("plz be haxxed mister arm9, thx") f.close() - if os.path.exists(realId1Path): - prinfo("Backing up real Id1...") - if not os.path.exists(realId1Path + realId1BackupTag): - os.rename(realId1Path, realId1Path + realId1BackupTag) - id1 += realId1BackupTag - realId1Path = f"{id0}/{id1}" - else: - prinfo("Skipping backup because a backup already exists!") + if os.path.exists(realId1Path) and realId1BackupTag not in realId1Path: + prinfo("Backing up real Id1..."): + os.rename(realId1Path, realId1Path + realId1BackupTag) + id1 += realId1BackupTag + realId1Path = f"{id0}/{id1}" + else: + prinfo("Skipping backup because a backup already exists!") prgood("MSET9 successfully injected!") From 73d9bd3a0dfed0676289e308a34f9f6fbea8351f Mon Sep 17 00:00:00 2001 From: Jade Herd Date: Tue, 17 Oct 2023 14:56:37 -0400 Subject: [PATCH 22/22] Blind --- MSET9_installer_script/mset9.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MSET9_installer_script/mset9.py b/MSET9_installer_script/mset9.py index 1f68aba..0657cf7 100644 --- a/MSET9_installer_script/mset9.py +++ b/MSET9_installer_script/mset9.py @@ -271,7 +271,7 @@ def injection(): f.close() if os.path.exists(realId1Path) and realId1BackupTag not in realId1Path: - prinfo("Backing up real Id1..."): + prinfo("Backing up real Id1...") os.rename(realId1Path, realId1Path + realId1BackupTag) id1 += realId1BackupTag realId1Path = f"{id0}/{id1}"