Yes, but first I want to fix some bugsWill you add it on the github as an alpha 1?
Yes, but first I want to fix some bugsWill you add it on the github as an alpha 1?
NeoSlyde is banned from this thread for derailment and harassment. If any more problems should arise, please use the report button.
I need a hint not stricly related to RX.
I'm on FW 4.5 and I'm going to update sysnand to 9.2.0-20 EUR with sysupdater (I know how to do) and then I'll need to downgrade MSET back to 4.x version.
Is it the same if I remove the MSET CIA from the updtaes folder (so I don't nedd to downgrade MSET after FW update), or it's needed for the first configuration of the new FW?
Let me know please.
#!/usr/bin/python
# -*- coding: utf-8 -*-
from urllib2 import urlopen, URLError, HTTPError
import platform
import os
try:
fileName = "msetdg.bin";
tid = [0x00020000, 0x00020000, 0x00021000, 0x00021000, 0x00022000, 0x00022000, 0x00027000, 0x00027000, 0x00026000, 0x00028000] #JPN 4/6, USA 4/6, EUR 4/6, KOR 4/5, CHN 4, TWN 4
tver = [0x1A, 0x22, 0x1F, 0x2D, 0x19, 0x23, 0x04, 0x08, 0x06, 0x05]
choice = 0
while choice not in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10):
os.system('cls') if platform.system() == "Windows" else os.system('clear')
print "Select your 3DS region :\n\n [1] JPN (4.x MSET)\n [2] JPN (6.x MSET)\n\n [3] USA (4.x MSET)\n [4] USA (6.x MSET)\n\n [5] EUR (4.x MSET)\n [6] EUR (6.x MSET)\n\n [7] KOR (4.x MSET)\n [8] KOR (5.x MSET)\n\n [9] CHN (4.x MSET)\n\n [10] TWN (4.x MSET)\n"
choice = int(raw_input("Selection : "))
url="http://nus.cdn.c.shop.nintendowifi.net/ccs/download/00040010%08X/%08X"%(tid[choice-1], tver[choice-1])
print "Downloading MSET from the CDN..."
f = urlopen(url)
with open(fileName, "wb") as lf:
lf.write(f.read())
print "Downloaded!"
except HTTPError, e:
print "HTTP Error:", e.code, url
except URLError, e:
print "URL Error:", e.reason, url
#include "downgradeapp.h"
#include "common.h"
#include "screenshot.h"
#include "fs.h"
#include "ff.h"
#include "console.h"
#include "draw.h"
#include "hid.h"
#include "ncch.h"
#include "crypto.h"
#include "TitleKeyDecrypt.h"
#include "NandDumper.h"
#include "aes.h"
#include "polarssl/sha2.h"
#include "stdio.h"
#include "filepack.h"
#define bswap_16(a) ((((a) << 8) & 0xff00) | (((a) >> 8) & 0xff))
#define bswap_32(a) ((((a) << 24) & 0xff000000) | (((a) << 8) & 0xff0000) | (((a) >> 8) & 0xff00) | (((a) >> 24) & 0xff))
typedef struct {
unsigned int id;
unsigned short index;
unsigned short type;
unsigned int size;
unsigned char signature[0x20];
} tmd_chunk_struct;
unsigned char region = 0;
char *regions[6] = { "Japan", "USA", "Europe", "China", "Korea", "Taiwan" };
char tmpstr[256];
FILINFO curInfo;
DIR myDir;
char cntpath[256]; // Contains the NAND content path
char tmdpath[256]; // Contains the NAND TMD path
char* getContentAppPath(){
return (char*)&cntpath;
}
char* getTMDAppPath(){
return (char*)&tmdpath;
}
void print_sha256(unsigned char hash[32])
{
int i;
for (i = 0; i < 32; i++)
{
print("%02X", hash[i]);
if (i == 16)
{
/* Continue printing the SHA-256 sum in a new line after 34 characters (17 bytes) */
print("\n"); ConsoleShow();
}
}
ConsoleShow();
}
int FindApp(unsigned int tid_low, unsigned int tid_high, int drive)
{
char *folder = (char*)&tmpstr;
memset(folder, 0, 256);
DIR* curDir = &myDir;
memset((unsigned char*)curDir, 0, sizeof(DIR));
FILINFO *myInfo = &curInfo;
memset((unsigned char*)myInfo, 0, sizeof(FILINFO));
myInfo->fname[0] = 'A';
sprintf(folder, "%d:title/%08x/%08x/content", drive, tid_low, tid_high);
if (f_opendir(curDir, folder) != FR_OK) return 0;
char path[256];
unsigned short latest_ver = 0, cur_ver = 0;
bool is_v0 = false;
for (int i = 0; myInfo->fname[0] != 0; i++)
{
if (f_readdir(curDir, myInfo)) break;
if (myInfo->fname[0] == '.') continue;
if (strstr(myInfo->fname, ".tmd") || strstr(myInfo->fname, ".TMD"))
{
memset(&path, 0, 256);
sprintf(path, "%s/%s", folder, myInfo->fname);
File tmp;
if (!FileOpen(&tmp, path, 0)) continue;
unsigned int size = FileGetSize(&tmp);
if (size < 0xB34)
{
FileClose(&tmp);
continue;
}
/* Get the TMD version */
/* There can be some instances in which more than one TMD/content file is available */
/* Of course, we want to use the latest one */
if (FileRead(&tmp, &cur_ver, 2, 0x1DC) != 2)
{
FileClose(&tmp);
continue;
}
/* Change Endianness */
cur_ver = bswap_16(cur_ver);
/* Verify the version number */
if ((latest_ver == 0 && !is_v0) || cur_ver > latest_ver)
{
tmd_chunk_struct tmd_entry;
memset(&tmd_entry, 0xFF, 0x30);
int cont = 0;
unsigned int b_read = 0;
while (tmd_entry.index != 0)
{
cont++;
b_read = FileRead(&tmp, &tmd_entry, 0x30, size - (cont * 0x30));
if (b_read != 0x30) break;
}
FileClose(&tmp);
if (b_read != 0x30) continue;
memset(&path, 0, 256);
sprintf(path, "%s/%08x.app", folder, bswap_32(tmd_entry.id)); // Change Endianness
if (FileOpen(&tmp, path, 0))
{
FileClose(&tmp);
latest_ver = cur_ver;
if (cur_ver == 0) is_v0 = true;
/* Save TMD and content paths */
sprintf(tmdpath, "%s/%s", folder, myInfo->fname);
sprintf(cntpath, "%s/%08x.app", folder, bswap_32(tmd_entry.id));
}
} else {
FileClose(&tmp);
}
} else {
continue;
}
}
f_closedir(curDir);
if (latest_ver == 0 && !is_v0) return 0;
return 1;
}
int CheckRegion(int drive)
{
File secureinfo;
print("Opening SecureInfo_A... "); ConsoleShow();
sprintf(tmpstr, "%d:rw/sys/SecureInfo_A", drive);
if (!FileOpen(&secureinfo, tmpstr, 0))
{
print("Error.\nTrying with SecureInfo_B... "); ConsoleShow();
memset(&tmpstr, 0, 256);
sprintf(tmpstr, "%d:rw/sys/SecureInfo_B", drive);
if (!FileOpen(&secureinfo, tmpstr, 0))
{
print("Error.\nProcess failed!\n"); ConsoleShow();
return -1;
}
}
print("OK!\n"); ConsoleShow();
FileRead(&secureinfo, ®ion, 1, 0x100);
FileClose(&secureinfo);
if (region > 0x06)
{
print("Error: unsupported region.\nProcess failed!\n"); ConsoleShow();
return -1;
} else {
/* Avoid problems with the unused "AUS" region code */
if (region >= 3) region--;
print("Region: %s\n", regions[region]); ConsoleShow();
}
return 0;
}
int CheckRegionSilent(int drive)
{
File secureinfo;
sprintf(tmpstr, "%d:rw/sys/SecureInfo_A", drive);
if (!FileOpen(&secureinfo, tmpstr, 0))
{
memset(&tmpstr, 0, 256);
sprintf(tmpstr, "%d:rw/sys/SecureInfo_B", drive);
if (!FileOpen(&secureinfo, tmpstr, 0))
{
print("Error.\nProcess failed!\n"); ConsoleShow();
return -1;
}
}
FileRead(&secureinfo, ®ion, 1, 0x100);
FileClose(&secureinfo);
if (region > 0x06)
{
print("Error: unsupported region.\nProcess failed!\n"); ConsoleShow();
return -1;
} else {
/* Avoid problems with the unused "AUS" region code */
if (region >= 3) region--;
}
return 0;
}
int checkDgFile(char* path, unsigned int hash)
{
unsigned char* buf = (unsigned char*)0x21000000;
unsigned int rb, fixedsize = 0x00400000;
File fp;
if (FileOpen(&fp, path, 0))
{
rb = FileRead(&fp, buf, fixedsize, 0);
FileClose(&fp);
if (!CheckHash(buf, rb, hash)) return 0;
} else {
return 0;
}
return 1;
}
void downgradeMSET()
{
File dg;
char *dgpath = "0:msetdg.bin";
unsigned int titleid_low = 0x00040010;
unsigned int titleid_high[6] = { 0x00020000, 0x00021000, 0x00022000, 0x00026000, 0x00027000, 0x00028000 }; //JPN, USA, EUR, CHN, KOR, TWN
unsigned int mset_hash[10] = { 0x96AEC379, 0xED315608, 0x3387F2CD, 0xEDAC05D7, 0xACC1BE62, 0xF0FF9F08, 0x565BCF20, 0xA04654C6, 0xAFD07166, 0xD40B12F4 }; //JPN, USA, EUR, CHN, KOR, TWN
unsigned short mset_ver[10] = { 3074, 5127, 3078, 5128, 3075, 5127, 8, 1026, 2049, 8 };
unsigned short mset_dg_ver = 0;
ConsoleInit();
ConsoleSetTitle(" MSET DOWNGRADER");
int checkLoop = 0;
CheckRegionSilent(SYS_NAND);
print("What would you like to\nDowngrade to?\n\n"); ConsoleShow();
print("[A] 4.x MSET\n[B] 5.x/6.x MSET\n"); ConsoleShow();
InputWait();
while( checkLoop < 1 )
{
InputWait();
char buttonInput = GetInput();
if (buttonInput == 1)
{
if (region == 0)
{
mset_dg_ver = 0;
}
else if (region == 1)
{
mset_dg_ver = 2;
}
else if (region == 2)
{
mset_dg_ver = 4;
}
else if (region == 3)
{
mset_dg_ver = 6;
}
else if (region == 4)
{
mset_dg_ver = 7;
}
else if (region == 5)
{
mset_dg_ver = 9;
}
else
{
print("region is: %u\n", region); ConsoleShow();
print("Unsupported Region!\n"); ConsoleShow();
mset_dg_ver = 0;
}
checkLoop = 1;
}
else if (buttonInput == 2)
{
if (region == 0)
{
mset_dg_ver = 1;
}
else if (region == 1)
{
mset_dg_ver = 3;
}
else if (region == 2)
{
mset_dg_ver = 5;
}
else if (region == 3)
{
mset_dg_ver = 6;
print("CHN Region Detected!\nFalling back to 4.x MSET\n"); ConsoleShow();
}
else if (region == 4)
{
mset_dg_ver = 8;
}
else if (region == 5)
{
mset_dg_ver = 9;
print("TWN Region Detected!\nFalling back to 4.x MSET\n"); ConsoleShow();
}
else
{
print("Unsupported Region!\n"); ConsoleShow();
mset_dg_ver = 0;
}
checkLoop = 1;
}
buttonInput = '\0';
}
print("Opening MSET app...\n"); ConsoleShow();
if (CheckRegion(SYS_NAND) == 0)
{
if (FindApp(titleid_low, titleid_high[region], SYS_NAND)) // SysNAND only
{
if (FileOpen(&dg, tmdpath, 0))
{
/* Get the MSET TMD version */
unsigned short tmd_ver;
FileRead(&dg, &tmd_ver, 2, 0x1DC);
tmd_ver = bswap_16(tmd_ver);
FileClose(&dg);
/* Verify version number */
if (tmd_ver > mset_ver[mset_dg_ver])
{
/* Open MSET content file */
if (FileOpen(&dg, cntpath, 0))
{
unsigned int check_val;
FileRead(&dg, &check_val, 4, 0x130);
FileClose(&dg);
if (check_val != 0)
{
if (checkDgFile(dgpath, mset_hash[mset_dg_ver]))
{
print("Opening downgrade pack... "); ConsoleShow();
if (FileOpen(&dg, dgpath, 0))
{
print("OK!\n"); ConsoleShow();
unsigned int dgsize = FileGetSize(&dg);
unsigned char *buf = (unsigned char*)0x21000000;
FileRead(&dg, buf, dgsize, 0);
/* Downgrade pack decryption */
u8 iv[0x10] = {0};
u8 Key[0x10] = {0};
GetTitleKey(&Key[0], titleid_low, titleid_high[region], SYS_NAND);
aes_context aes_ctxt;
aes_setkey_dec(&aes_ctxt, Key, 0x80);
aes_crypt_cbc(&aes_ctxt, AES_DECRYPT, dgsize, iv, buf, buf);
FileWrite(&dg, buf, dgsize, 0);
FileClose(&dg);
if (*((unsigned int*)(buf + 0x100)) == 0x4843434E) // "NCCH" magic word
{
print("Downgrading... "); ConsoleShow();
if (FSFileCopy(cntpath, dgpath) == 0)
{
print("done!\nRemoving downgrade pack... "); ConsoleShow();
f_unlink(dgpath);
print("done.\n"); ConsoleShow();
} else {
print("\nError downgrading MSET content.\nRemoving downgrade pack... "); ConsoleShow();
f_unlink(dgpath);
print("done.\n"); ConsoleShow();
}
} else {
print("Error: bad downgrade pack.\n"); ConsoleShow();
}
} else {
print("Error.\n"); ConsoleShow();
}
} else {
print("Error: bad downgrade pack.\n"); ConsoleShow();
}
} else {
print("Your MSET version is exploitable.\nDowngrade isn't necessary.\n"); ConsoleShow();
}
} else {
print("Error opening MSET content file.\n"); ConsoleShow();
}
} else {
print("Your MSET version is exploitable.\nDowngrade isn't necessary.\n"); ConsoleShow();
}
} else {
print("Error opening MSET TMD.\n"); ConsoleShow();
}
} else {
print("Error: couldn't find MSET data.\n"); ConsoleShow();
}
}
print("\nPress A to exit\n");
ConsoleShow();
WaitForButton(BUTTON_A);
}
void manageFBI(bool restore)
{
int drive;
unsigned int titleid_low = 0x00040010;
unsigned int titleid_high[6] = { 0x00020300, 0x00021300, 0x00022300, 0x00026300, 0x00027300, 0x00028300 }; //JPN, USA, EUR, CHN, KOR, TWN
char *backup_path = "rxTools/h&s_backup";
File tmp;
char path[256] = {0};
char path2[256] = {0};
unsigned char *buf = (unsigned char *)0x21000000;
unsigned int size;
unsigned short tmd_ver;
unsigned int sd_cntsize;
unsigned short sd_tmd_ver;
unsigned char TmdCntInfoRecSum[32] = {0};
unsigned char CntInfoRecSum[32] = {0};
unsigned char TmdCntChnkRecSum[32] = {0};
unsigned char CntChnkRecSum[32] = {0};
unsigned char TmdCntDataSum[32] = {0};
unsigned char CntDataSum[32] = {0};
if ((drive = NandSwitch()) == UNK_NAND) return;
ConsoleInit();
ConsoleSetTitle(restore ? " RESTORE HEALTH & SAFETY" : " FBI INSTALLATION");
if (CheckRegion(drive) == 0)
{
if (FindApp(titleid_low, titleid_high[region], drive))
{
/* Open the NAND H&S TMD */
FileOpen(&tmp, tmdpath, 0);
FileRead(&tmp, buf, 0xB34, 0);
FileClose(&tmp);
/* Get the title version from the TMD */
tmd_ver = (unsigned short)((buf[0x1DC] << 8) | buf[0x1DD]);
print("TMD Version: v%u.\n", tmd_ver);
if (!restore)
{
/* Get the stored content size from the TMD */
unsigned int cntsize = (unsigned int)((buf[0xB10] << 24) | (buf[0xB11] << 16) | (buf[0xB12] << 8) | buf[0xB13]);
/* Open the NAND H&S content file and read it to the memory buffer */
FileOpen(&tmp, cntpath, 0);
FileRead(&tmp, buf + 0x1000, cntsize, 0);
FileClose(&tmp);
/* Create the Health & Safety data backup directory */
f_mkdir(backup_path);
memset(&tmpstr, 0, 256);
sprintf(tmpstr, "%s/%s", backup_path, regions[region]);
f_mkdir(tmpstr);
memset(&tmpstr, 0, 256);
sprintf(tmpstr, "%s/%s/v%u", backup_path, regions[region], tmd_ver);
f_mkdir(tmpstr);
/* Backup the H&S TMD */
sprintf(path, "0:%s/%.12s", tmpstr, tmdpath+34);
if (FileOpen(&tmp, path, 1))
{
size = FileWrite(&tmp, buf, 0xB34, 0);
FileClose(&tmp);
if (size == 0xB34)
{
print("NAND H&S TMD backup created.\n"); ConsoleShow();
/* Backup the H&S content file */
memset(&path, 0, 256);
sprintf(path, "0:%s/%.12s", tmpstr, cntpath+34);
if (FileOpen(&tmp, path, 1))
{
size = FileWrite(&tmp, buf + 0x1000, cntsize, 0);
FileClose(&tmp);
if (size == cntsize)
{
print("NAND H&S content backup created.\n"); ConsoleShow();
} else {
print("Error writing H&S content backup.\n"); ConsoleShow();
goto out;
}
} else {
print("Error creating H&S content backup.\n"); ConsoleShow();
goto out;
}
} else {
print("Error writing H&S TMD backup.\n"); ConsoleShow();
goto out;
}
} else {
print("Error creating H&S TMD backup.\n"); ConsoleShow();
goto out;
}
/* Generate the FBI data paths */
sprintf(path, "0:fbi_inject.tmd");
sprintf(path2, "0:fbi_inject.app");
print("Editing H&S Information... "); ConsoleShow();
} else {
/* Generate the H&S backup data paths */
memset(&tmpstr, 0, 256);
sprintf(tmpstr, "%s/%s/v%u", backup_path, regions[region], tmd_ver);
sprintf(path, "0:%s/%.12s", tmpstr, tmdpath+34);
sprintf(path2, "0:%s/%.12s", tmpstr, cntpath+34);
print("Restoring H&S Information... "); ConsoleShow();
}
/* Open the SD TMD */
if (FileOpen(&tmp, path, 0))
{
size = FileGetSize(&tmp);
if (size == 0xB34)
{
FileRead(&tmp, buf, 0xB34, 0);
FileClose(&tmp);
/* Get the SD TMD version and stored content size */
sd_tmd_ver = (unsigned short)((buf[0x1DC] << 8) | buf[0x1DD]);
sd_cntsize = (unsigned int)((buf[0xB10] << 24) | (buf[0xB11] << 16) | (buf[0xB12] << 8) | buf[0xB13]);
if (sd_tmd_ver == tmd_ver)
{
/* Get the SHA-256 hashes */
memcpy(TmdCntInfoRecSum, buf + 0x1E4, 32);
memcpy(TmdCntChnkRecSum, buf + 0x208, 32);
memcpy(TmdCntDataSum, buf + 0xB14, 32);
/* Verify the Content Info Record hash */
sha2(buf + 0x204, 0x900, CntInfoRecSum, 0);
if (memcmp(CntInfoRecSum, TmdCntInfoRecSum, 32) == 0)
{
/* Verify the Content Chunk Record hash */
sha2(buf + 0xB04, 0x30, CntChnkRecSum, 0);
if (memcmp(CntChnkRecSum, TmdCntChnkRecSum, 32) == 0)
{
/* Open the SD content file */
if (FileOpen(&tmp, path2, 0))
{
size = FileGetSize(&tmp);
if (size == sd_cntsize)
{
FileRead(&tmp, buf + 0x1000, sd_cntsize, 0);
FileClose(&tmp);
/* Verify the Content Data hash */
sha2(buf + 0x1000, sd_cntsize, CntDataSum, 0);
if (memcmp(CntDataSum, TmdCntDataSum, 32) == 0)
{
/* Now we are ready to rock 'n roll */
if (FSFileCopy(tmdpath, path) == 0)
{
if (FSFileCopy(cntpath, path2) == 0)
{
print("OK!\nDeleting %s data... ", restore ? "backup" : "FBI injection"); ConsoleShow();
f_unlink(path);
f_unlink(path2);
print("OK!\n"); ConsoleShow();
} else {
print("\nError %s content file.\n", restore ? "restoring H&S" : "injecting FBI"); ConsoleShow();
}
} else {
print("\nError %s TMD.\n", restore ? "restoring H&S" : "injecting FBI"); ConsoleShow();
}
} else {
print("\nError: invalid Content Data hash.\nGot:\n"); ConsoleShow();
print_sha256(CntDataSum);
print("\nExpected:\n"); ConsoleShow();
print_sha256(TmdCntDataSum);
}
} else {
FileClose(&tmp);
print("\nInvalid %s content size.\nGot: v%u / Expected: v%u\n", restore ? "backup" : "FBI", size, sd_cntsize); ConsoleShow();
}
} else {
print("\nError opening %s content.\n", restore ? "backup" : "FBI");
}
} else {
print("\nError: invalid Content Chunk hash.\nGot:\n"); ConsoleShow();
print_sha256(CntChnkRecSum);
print("\nExpected:\n"); ConsoleShow();
print_sha256(TmdCntChnkRecSum);
}
} else {
print("\nError: invalid Content Info hash.\nGot:\n"); ConsoleShow();
print_sha256(CntInfoRecSum);
print("\nExpected:\n"); ConsoleShow();
print_sha256(TmdCntInfoRecSum);
}
} else {
print("\nError: invalid %s TMD version.\nGot: v%u / Expected: v%u\n", restore ? "backup" : "FBI", sd_tmd_ver, tmd_ver); ConsoleShow();
}
} else {
FileClose(&tmp);
print("\nError: invalid %s TMD size.\nGot: %u / Expected: %u\n", restore ? "backup" : "FBI", size, 0xB34); ConsoleShow();
}
} else {
print("\nError opening %s TMD.\n", restore ? "backup" : "FBI"); ConsoleShow();
}
} else {
print("Error: couldn't find H&S data.\n"); ConsoleShow();
}
}
out:
print("\nPress A to exit.");
ConsoleShow();
WaitForButton(BUTTON_A);
}
void installFBI()
{
/* Injects FBI TMD and content file to the Health & Safety App */
manageFBI(false);
}
void restoreHS()
{
/* Restores original Health & Safety TMD and content file to the NAND */
manageFBI(true);
}
If everything works fine, you should send a pull request.Alright! Time for rxTools 3.0b7!
Added: 6.x MSET Downgrade features from downgrade menu
Added: 6.x MSET Downgrade options to msetdg.py
Added: 6.x-modified rxinstaller.nds by @Apache Thunder
Enjoy!
Download: https://anonfiles.com/file/993ca626533f4fa4cb34db434b6438b4
Modified source:
Code:#!/usr/bin/python # -*- coding: utf-8 -*- from urllib2 import urlopen, URLError, HTTPError import platform import os try: fileName = "msetdg.bin"; tid = [0x00020000, 0x00020000, 0x00021000, 0x00021000, 0x00022000, 0x00022000, 0x00027000, 0x00027000, 0x00026000, 0x00028000] #JPN 4/6, USA 4/6, EUR 4/6, KOR 4/5, CHN 4, TWN 4 tver = [0x1A, 0x22, 0x1F, 0x2D, 0x19, 0x23, 0x04, 0x08, 0x06, 0x05] choice = 0 while choice not in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10): os.system('cls') if platform.system() == "Windows" else os.system('clear') print "Select your 3DS region :\n\n [1] JPN (4.x MSET)\n [2] JPN (6.x MSET)\n\n [3] USA (4.x MSET)\n [4] USA (6.x MSET)\n\n [5] EUR (4.x MSET)\n [6] EUR (6.x MSET)\n\n [7] KOR (4.x MSET)\n [8] KOR (5.x MSET)\n\n [9] CHN (4.x MSET)\n\n [10] TWN (4.x MSET)\n" choice = int(raw_input("Selection : ")) url="http://nus.cdn.c.shop.nintendowifi.net/ccs/download/00040010%08X/%08X"%(tid[choice-1], tver[choice-1]) print "Downloading MSET from the CDN..." f = urlopen(url) with open(fileName, "wb") as lf: lf.write(f.read()) print "Downloaded!" except HTTPError, e: print "HTTP Error:", e.code, url except URLError, e: print "URL Error:", e.reason, url
Code:#include "downgradeapp.h" #include "common.h" #include "screenshot.h" #include "fs.h" #include "ff.h" #include "console.h" #include "draw.h" #include "hid.h" #include "ncch.h" #include "crypto.h" #include "TitleKeyDecrypt.h" #include "NandDumper.h" #include "aes.h" #include "polarssl/sha2.h" #include "stdio.h" #include "filepack.h" #define bswap_16(a) ((((a) << 8) & 0xff00) | (((a) >> 8) & 0xff)) #define bswap_32(a) ((((a) << 24) & 0xff000000) | (((a) << 8) & 0xff0000) | (((a) >> 8) & 0xff00) | (((a) >> 24) & 0xff)) typedef struct { unsigned int id; unsigned short index; unsigned short type; unsigned int size; unsigned char signature[0x20]; } tmd_chunk_struct; unsigned char region = 0; char *regions[6] = { "Japan", "USA", "Europe", "China", "Korea", "Taiwan" }; char tmpstr[256]; FILINFO curInfo; DIR myDir; char cntpath[256]; // Contains the NAND content path char tmdpath[256]; // Contains the NAND TMD path char* getContentAppPath(){ return (char*)&cntpath; } char* getTMDAppPath(){ return (char*)&tmdpath; } void print_sha256(unsigned char hash[32]) { int i; for (i = 0; i < 32; i++) { print("%02X", hash[i]); if (i == 16) { /* Continue printing the SHA-256 sum in a new line after 34 characters (17 bytes) */ print("\n"); ConsoleShow(); } } ConsoleShow(); } int FindApp(unsigned int tid_low, unsigned int tid_high, int drive) { char *folder = (char*)&tmpstr; memset(folder, 0, 256); DIR* curDir = &myDir; memset((unsigned char*)curDir, 0, sizeof(DIR)); FILINFO *myInfo = &curInfo; memset((unsigned char*)myInfo, 0, sizeof(FILINFO)); myInfo->fname[0] = 'A'; sprintf(folder, "%d:title/%08x/%08x/content", drive, tid_low, tid_high); if (f_opendir(curDir, folder) != FR_OK) return 0; char path[256]; unsigned short latest_ver = 0, cur_ver = 0; bool is_v0 = false; for (int i = 0; myInfo->fname[0] != 0; i++) { if (f_readdir(curDir, myInfo)) break; if (myInfo->fname[0] == '.') continue; if (strstr(myInfo->fname, ".tmd") || strstr(myInfo->fname, ".TMD")) { memset(&path, 0, 256); sprintf(path, "%s/%s", folder, myInfo->fname); File tmp; if (!FileOpen(&tmp, path, 0)) continue; unsigned int size = FileGetSize(&tmp); if (size < 0xB34) { FileClose(&tmp); continue; } /* Get the TMD version */ /* There can be some instances in which more than one TMD/content file is available */ /* Of course, we want to use the latest one */ if (FileRead(&tmp, &cur_ver, 2, 0x1DC) != 2) { FileClose(&tmp); continue; } /* Change Endianness */ cur_ver = bswap_16(cur_ver); /* Verify the version number */ if ((latest_ver == 0 && !is_v0) || cur_ver > latest_ver) { tmd_chunk_struct tmd_entry; memset(&tmd_entry, 0xFF, 0x30); int cont = 0; unsigned int b_read = 0; while (tmd_entry.index != 0) { cont++; b_read = FileRead(&tmp, &tmd_entry, 0x30, size - (cont * 0x30)); if (b_read != 0x30) break; } FileClose(&tmp); if (b_read != 0x30) continue; memset(&path, 0, 256); sprintf(path, "%s/%08x.app", folder, bswap_32(tmd_entry.id)); // Change Endianness if (FileOpen(&tmp, path, 0)) { FileClose(&tmp); latest_ver = cur_ver; if (cur_ver == 0) is_v0 = true; /* Save TMD and content paths */ sprintf(tmdpath, "%s/%s", folder, myInfo->fname); sprintf(cntpath, "%s/%08x.app", folder, bswap_32(tmd_entry.id)); } } else { FileClose(&tmp); } } else { continue; } } f_closedir(curDir); if (latest_ver == 0 && !is_v0) return 0; return 1; } int CheckRegion(int drive) { File secureinfo; print("Opening SecureInfo_A... "); ConsoleShow(); sprintf(tmpstr, "%d:rw/sys/SecureInfo_A", drive); if (!FileOpen(&secureinfo, tmpstr, 0)) { print("Error.\nTrying with SecureInfo_B... "); ConsoleShow(); memset(&tmpstr, 0, 256); sprintf(tmpstr, "%d:rw/sys/SecureInfo_B", drive); if (!FileOpen(&secureinfo, tmpstr, 0)) { print("Error.\nProcess failed!\n"); ConsoleShow(); return -1; } } print("OK!\n"); ConsoleShow(); FileRead(&secureinfo, ®ion, 1, 0x100); FileClose(&secureinfo); if (region > 0x06) { print("Error: unsupported region.\nProcess failed!\n"); ConsoleShow(); return -1; } else { /* Avoid problems with the unused "AUS" region code */ if (region >= 3) region--; print("Region: %s\n", regions[region]); ConsoleShow(); } return 0; } int CheckRegionSilent(int drive) { File secureinfo; sprintf(tmpstr, "%d:rw/sys/SecureInfo_A", drive); if (!FileOpen(&secureinfo, tmpstr, 0)) { memset(&tmpstr, 0, 256); sprintf(tmpstr, "%d:rw/sys/SecureInfo_B", drive); if (!FileOpen(&secureinfo, tmpstr, 0)) { print("Error.\nProcess failed!\n"); ConsoleShow(); return -1; } } FileRead(&secureinfo, ®ion, 1, 0x100); FileClose(&secureinfo); if (region > 0x06) { print("Error: unsupported region.\nProcess failed!\n"); ConsoleShow(); return -1; } else { /* Avoid problems with the unused "AUS" region code */ if (region >= 3) region--; } return 0; } int checkDgFile(char* path, unsigned int hash) { unsigned char* buf = (unsigned char*)0x21000000; unsigned int rb, fixedsize = 0x00400000; File fp; if (FileOpen(&fp, path, 0)) { rb = FileRead(&fp, buf, fixedsize, 0); FileClose(&fp); if (!CheckHash(buf, rb, hash)) return 0; } else { return 0; } return 1; } void downgradeMSET() { File dg; char *dgpath = "0:msetdg.bin"; unsigned int titleid_low = 0x00040010; unsigned int titleid_high[6] = { 0x00020000, 0x00021000, 0x00022000, 0x00026000, 0x00027000, 0x00028000 }; //JPN, USA, EUR, CHN, KOR, TWN unsigned int mset_hash[10] = { 0x96AEC379, 0xED315608, 0x3387F2CD, 0xEDAC05D7, 0xACC1BE62, 0xF0FF9F08, 0x565BCF20, 0xA04654C6, 0xAFD07166, 0xD40B12F4 }; //JPN, USA, EUR, CHN, KOR, TWN unsigned short mset_ver[10] = { 3074, 5127, 3078, 5128, 3075, 5127, 8, 1026, 2049, 8 }; unsigned short mset_dg_ver = 0; ConsoleInit(); ConsoleSetTitle(" MSET DOWNGRADER"); int checkLoop = 0; CheckRegionSilent(SYS_NAND); print("What would you like to\nDowngrade to?\n\n"); ConsoleShow(); print("[A] 4.x MSET\n[B] 5.x/6.x MSET\n"); ConsoleShow(); InputWait(); while( checkLoop < 1 ) { InputWait(); char buttonInput = GetInput(); if (buttonInput == 1) { if (region == 0) { mset_dg_ver = 0; } else if (region == 1) { mset_dg_ver = 2; } else if (region == 2) { mset_dg_ver = 4; } else if (region == 3) { mset_dg_ver = 6; } else if (region == 4) { mset_dg_ver = 7; } else if (region == 5) { mset_dg_ver = 9; } else { print("region is: %u\n", region); ConsoleShow(); print("Unsupported Region!\n"); ConsoleShow(); mset_dg_ver = 0; } checkLoop = 1; } else if (buttonInput == 2) { if (region == 0) { mset_dg_ver = 1; } else if (region == 1) { mset_dg_ver = 3; } else if (region == 2) { mset_dg_ver = 5; } else if (region == 3) { mset_dg_ver = 6; print("CHN Region Detected!\nFalling back to 4.x MSET\n"); ConsoleShow(); } else if (region == 4) { mset_dg_ver = 8; } else if (region == 5) { mset_dg_ver = 9; print("TWN Region Detected!\nFalling back to 4.x MSET\n"); ConsoleShow(); } else { print("Unsupported Region!\n"); ConsoleShow(); mset_dg_ver = 0; } checkLoop = 1; } buttonInput = '\0'; } print("Opening MSET app...\n"); ConsoleShow(); if (CheckRegion(SYS_NAND) == 0) { if (FindApp(titleid_low, titleid_high[region], SYS_NAND)) // SysNAND only { if (FileOpen(&dg, tmdpath, 0)) { /* Get the MSET TMD version */ unsigned short tmd_ver; FileRead(&dg, &tmd_ver, 2, 0x1DC); tmd_ver = bswap_16(tmd_ver); FileClose(&dg); /* Verify version number */ if (tmd_ver > mset_ver[mset_dg_ver]) { /* Open MSET content file */ if (FileOpen(&dg, cntpath, 0)) { unsigned int check_val; FileRead(&dg, &check_val, 4, 0x130); FileClose(&dg); if (check_val != 0) { if (checkDgFile(dgpath, mset_hash[mset_dg_ver])) { print("Opening downgrade pack... "); ConsoleShow(); if (FileOpen(&dg, dgpath, 0)) { print("OK!\n"); ConsoleShow(); unsigned int dgsize = FileGetSize(&dg); unsigned char *buf = (unsigned char*)0x21000000; FileRead(&dg, buf, dgsize, 0); /* Downgrade pack decryption */ u8 iv[0x10] = {0}; u8 Key[0x10] = {0}; GetTitleKey(&Key[0], titleid_low, titleid_high[region], SYS_NAND); aes_context aes_ctxt; aes_setkey_dec(&aes_ctxt, Key, 0x80); aes_crypt_cbc(&aes_ctxt, AES_DECRYPT, dgsize, iv, buf, buf); FileWrite(&dg, buf, dgsize, 0); FileClose(&dg); if (*((unsigned int*)(buf + 0x100)) == 0x4843434E) // "NCCH" magic word { print("Downgrading... "); ConsoleShow(); if (FSFileCopy(cntpath, dgpath) == 0) { print("done!\nRemoving downgrade pack... "); ConsoleShow(); f_unlink(dgpath); print("done.\n"); ConsoleShow(); } else { print("\nError downgrading MSET content.\nRemoving downgrade pack... "); ConsoleShow(); f_unlink(dgpath); print("done.\n"); ConsoleShow(); } } else { print("Error: bad downgrade pack.\n"); ConsoleShow(); } } else { print("Error.\n"); ConsoleShow(); } } else { print("Error: bad downgrade pack.\n"); ConsoleShow(); } } else { print("Your MSET version is exploitable.\nDowngrade isn't necessary.\n"); ConsoleShow(); } } else { print("Error opening MSET content file.\n"); ConsoleShow(); } } else { print("Your MSET version is exploitable.\nDowngrade isn't necessary.\n"); ConsoleShow(); } } else { print("Error opening MSET TMD.\n"); ConsoleShow(); } } else { print("Error: couldn't find MSET data.\n"); ConsoleShow(); } } print("\nPress A to exit\n"); ConsoleShow(); WaitForButton(BUTTON_A); } void manageFBI(bool restore) { int drive; unsigned int titleid_low = 0x00040010; unsigned int titleid_high[6] = { 0x00020300, 0x00021300, 0x00022300, 0x00026300, 0x00027300, 0x00028300 }; //JPN, USA, EUR, CHN, KOR, TWN char *backup_path = "rxTools/h&s_backup"; File tmp; char path[256] = {0}; char path2[256] = {0}; unsigned char *buf = (unsigned char *)0x21000000; unsigned int size; unsigned short tmd_ver; unsigned int sd_cntsize; unsigned short sd_tmd_ver; unsigned char TmdCntInfoRecSum[32] = {0}; unsigned char CntInfoRecSum[32] = {0}; unsigned char TmdCntChnkRecSum[32] = {0}; unsigned char CntChnkRecSum[32] = {0}; unsigned char TmdCntDataSum[32] = {0}; unsigned char CntDataSum[32] = {0}; if ((drive = NandSwitch()) == UNK_NAND) return; ConsoleInit(); ConsoleSetTitle(restore ? " RESTORE HEALTH & SAFETY" : " FBI INSTALLATION"); if (CheckRegion(drive) == 0) { if (FindApp(titleid_low, titleid_high[region], drive)) { /* Open the NAND H&S TMD */ FileOpen(&tmp, tmdpath, 0); FileRead(&tmp, buf, 0xB34, 0); FileClose(&tmp); /* Get the title version from the TMD */ tmd_ver = (unsigned short)((buf[0x1DC] << 8) | buf[0x1DD]); print("TMD Version: v%u.\n", tmd_ver); if (!restore) { /* Get the stored content size from the TMD */ unsigned int cntsize = (unsigned int)((buf[0xB10] << 24) | (buf[0xB11] << 16) | (buf[0xB12] << 8) | buf[0xB13]); /* Open the NAND H&S content file and read it to the memory buffer */ FileOpen(&tmp, cntpath, 0); FileRead(&tmp, buf + 0x1000, cntsize, 0); FileClose(&tmp); /* Create the Health & Safety data backup directory */ f_mkdir(backup_path); memset(&tmpstr, 0, 256); sprintf(tmpstr, "%s/%s", backup_path, regions[region]); f_mkdir(tmpstr); memset(&tmpstr, 0, 256); sprintf(tmpstr, "%s/%s/v%u", backup_path, regions[region], tmd_ver); f_mkdir(tmpstr); /* Backup the H&S TMD */ sprintf(path, "0:%s/%.12s", tmpstr, tmdpath+34); if (FileOpen(&tmp, path, 1)) { size = FileWrite(&tmp, buf, 0xB34, 0); FileClose(&tmp); if (size == 0xB34) { print("NAND H&S TMD backup created.\n"); ConsoleShow(); /* Backup the H&S content file */ memset(&path, 0, 256); sprintf(path, "0:%s/%.12s", tmpstr, cntpath+34); if (FileOpen(&tmp, path, 1)) { size = FileWrite(&tmp, buf + 0x1000, cntsize, 0); FileClose(&tmp); if (size == cntsize) { print("NAND H&S content backup created.\n"); ConsoleShow(); } else { print("Error writing H&S content backup.\n"); ConsoleShow(); goto out; } } else { print("Error creating H&S content backup.\n"); ConsoleShow(); goto out; } } else { print("Error writing H&S TMD backup.\n"); ConsoleShow(); goto out; } } else { print("Error creating H&S TMD backup.\n"); ConsoleShow(); goto out; } /* Generate the FBI data paths */ sprintf(path, "0:fbi_inject.tmd"); sprintf(path2, "0:fbi_inject.app"); print("Editing H&S Information... "); ConsoleShow(); } else { /* Generate the H&S backup data paths */ memset(&tmpstr, 0, 256); sprintf(tmpstr, "%s/%s/v%u", backup_path, regions[region], tmd_ver); sprintf(path, "0:%s/%.12s", tmpstr, tmdpath+34); sprintf(path2, "0:%s/%.12s", tmpstr, cntpath+34); print("Restoring H&S Information... "); ConsoleShow(); } /* Open the SD TMD */ if (FileOpen(&tmp, path, 0)) { size = FileGetSize(&tmp); if (size == 0xB34) { FileRead(&tmp, buf, 0xB34, 0); FileClose(&tmp); /* Get the SD TMD version and stored content size */ sd_tmd_ver = (unsigned short)((buf[0x1DC] << 8) | buf[0x1DD]); sd_cntsize = (unsigned int)((buf[0xB10] << 24) | (buf[0xB11] << 16) | (buf[0xB12] << 8) | buf[0xB13]); if (sd_tmd_ver == tmd_ver) { /* Get the SHA-256 hashes */ memcpy(TmdCntInfoRecSum, buf + 0x1E4, 32); memcpy(TmdCntChnkRecSum, buf + 0x208, 32); memcpy(TmdCntDataSum, buf + 0xB14, 32); /* Verify the Content Info Record hash */ sha2(buf + 0x204, 0x900, CntInfoRecSum, 0); if (memcmp(CntInfoRecSum, TmdCntInfoRecSum, 32) == 0) { /* Verify the Content Chunk Record hash */ sha2(buf + 0xB04, 0x30, CntChnkRecSum, 0); if (memcmp(CntChnkRecSum, TmdCntChnkRecSum, 32) == 0) { /* Open the SD content file */ if (FileOpen(&tmp, path2, 0)) { size = FileGetSize(&tmp); if (size == sd_cntsize) { FileRead(&tmp, buf + 0x1000, sd_cntsize, 0); FileClose(&tmp); /* Verify the Content Data hash */ sha2(buf + 0x1000, sd_cntsize, CntDataSum, 0); if (memcmp(CntDataSum, TmdCntDataSum, 32) == 0) { /* Now we are ready to rock 'n roll */ if (FSFileCopy(tmdpath, path) == 0) { if (FSFileCopy(cntpath, path2) == 0) { print("OK!\nDeleting %s data... ", restore ? "backup" : "FBI injection"); ConsoleShow(); f_unlink(path); f_unlink(path2); print("OK!\n"); ConsoleShow(); } else { print("\nError %s content file.\n", restore ? "restoring H&S" : "injecting FBI"); ConsoleShow(); } } else { print("\nError %s TMD.\n", restore ? "restoring H&S" : "injecting FBI"); ConsoleShow(); } } else { print("\nError: invalid Content Data hash.\nGot:\n"); ConsoleShow(); print_sha256(CntDataSum); print("\nExpected:\n"); ConsoleShow(); print_sha256(TmdCntDataSum); } } else { FileClose(&tmp); print("\nInvalid %s content size.\nGot: v%u / Expected: v%u\n", restore ? "backup" : "FBI", size, sd_cntsize); ConsoleShow(); } } else { print("\nError opening %s content.\n", restore ? "backup" : "FBI"); } } else { print("\nError: invalid Content Chunk hash.\nGot:\n"); ConsoleShow(); print_sha256(CntChnkRecSum); print("\nExpected:\n"); ConsoleShow(); print_sha256(TmdCntChnkRecSum); } } else { print("\nError: invalid Content Info hash.\nGot:\n"); ConsoleShow(); print_sha256(CntInfoRecSum); print("\nExpected:\n"); ConsoleShow(); print_sha256(TmdCntInfoRecSum); } } else { print("\nError: invalid %s TMD version.\nGot: v%u / Expected: v%u\n", restore ? "backup" : "FBI", sd_tmd_ver, tmd_ver); ConsoleShow(); } } else { FileClose(&tmp); print("\nError: invalid %s TMD size.\nGot: %u / Expected: %u\n", restore ? "backup" : "FBI", size, 0xB34); ConsoleShow(); } } else { print("\nError opening %s TMD.\n", restore ? "backup" : "FBI"); ConsoleShow(); } } else { print("Error: couldn't find H&S data.\n"); ConsoleShow(); } } out: print("\nPress A to exit."); ConsoleShow(); WaitForButton(BUTTON_A); } void installFBI() { /* Injects FBI TMD and content file to the Health & Safety App */ manageFBI(false); } void restoreHS() { /* Restores original Health & Safety TMD and content file to the NAND */ manageFBI(true); }
... and you should also remove the whitelist and twl_firm.
no reason, twl & whitelist are only left with older versions to improve NDS flashcard compatibility, but if the card your using is compatible with 9.x there no real advantage to keeping them on a older versionI should or I have to?
For whitelist, I use a R4 2014 Dual Core the works perfectly, so no need to delete that title (I will do it in future if I need), but why leave old twl_firm?
Thanks.no reason, twl & whitelist are only left with older versions to improve NDS flashcard compatibility, but if the card your using is compatible with 9.x there no real advantage to keeping them on a older version
Alright! Time for rxTools 3.0b7!
Added: 6.x MSET Downgrade features from downgrade menu
Added: 6.x MSET Downgrade options to msetdg.py
Added: 6.x-modified rxinstaller.nds by @Apache Thunder
Enjoy!
Download: https://anonfiles.com/file/993ca626533f4fa4cb34db434b6438b4
Modified source:
Code:#!/usr/bin/python # -*- coding: utf-8 -*- from urllib2 import urlopen, URLError, HTTPError import platform import os try: fileName = "msetdg.bin"; tid = [0x00020000, 0x00020000, 0x00021000, 0x00021000, 0x00022000, 0x00022000, 0x00027000, 0x00027000, 0x00026000, 0x00028000] #JPN 4/6, USA 4/6, EUR 4/6, KOR 4/5, CHN 4, TWN 4 tver = [0x1A, 0x22, 0x1F, 0x2D, 0x19, 0x23, 0x04, 0x08, 0x06, 0x05] choice = 0 while choice not in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10): os.system('cls') if platform.system() == "Windows" else os.system('clear') print "Select your 3DS region :\n\n [1] JPN (4.x MSET)\n [2] JPN (6.x MSET)\n\n [3] USA (4.x MSET)\n [4] USA (6.x MSET)\n\n [5] EUR (4.x MSET)\n [6] EUR (6.x MSET)\n\n [7] KOR (4.x MSET)\n [8] KOR (5.x MSET)\n\n [9] CHN (4.x MSET)\n\n [10] TWN (4.x MSET)\n" choice = int(raw_input("Selection : ")) url="http://nus.cdn.c.shop.nintendowifi.net/ccs/download/00040010%08X/%08X"%(tid[choice-1], tver[choice-1]) print "Downloading MSET from the CDN..." f = urlopen(url) with open(fileName, "wb") as lf: lf.write(f.read()) print "Downloaded!" except HTTPError, e: print "HTTP Error:", e.code, url except URLError, e: print "URL Error:", e.reason, url
Code:#include "downgradeapp.h" #include "common.h" #include "screenshot.h" #include "fs.h" #include "ff.h" #include "console.h" #include "draw.h" #include "hid.h" #include "ncch.h" #include "crypto.h" #include "TitleKeyDecrypt.h" #include "NandDumper.h" #include "aes.h" #include "polarssl/sha2.h" #include "stdio.h" #include "filepack.h" #define bswap_16(a) ((((a) << 8) & 0xff00) | (((a) >> 8) & 0xff)) #define bswap_32(a) ((((a) << 24) & 0xff000000) | (((a) << 8) & 0xff0000) | (((a) >> 8) & 0xff00) | (((a) >> 24) & 0xff)) typedef struct { unsigned int id; unsigned short index; unsigned short type; unsigned int size; unsigned char signature[0x20]; } tmd_chunk_struct; unsigned char region = 0; char *regions[6] = { "Japan", "USA", "Europe", "China", "Korea", "Taiwan" }; char tmpstr[256]; FILINFO curInfo; DIR myDir; char cntpath[256]; // Contains the NAND content path char tmdpath[256]; // Contains the NAND TMD path char* getContentAppPath(){ return (char*)&cntpath; } char* getTMDAppPath(){ return (char*)&tmdpath; } void print_sha256(unsigned char hash[32]) { int i; for (i = 0; i < 32; i++) { print("%02X", hash[i]); if (i == 16) { /* Continue printing the SHA-256 sum in a new line after 34 characters (17 bytes) */ print("\n"); ConsoleShow(); } } ConsoleShow(); } int FindApp(unsigned int tid_low, unsigned int tid_high, int drive) { char *folder = (char*)&tmpstr; memset(folder, 0, 256); DIR* curDir = &myDir; memset((unsigned char*)curDir, 0, sizeof(DIR)); FILINFO *myInfo = &curInfo; memset((unsigned char*)myInfo, 0, sizeof(FILINFO)); myInfo->fname[0] = 'A'; sprintf(folder, "%d:title/%08x/%08x/content", drive, tid_low, tid_high); if (f_opendir(curDir, folder) != FR_OK) return 0; char path[256]; unsigned short latest_ver = 0, cur_ver = 0; bool is_v0 = false; for (int i = 0; myInfo->fname[0] != 0; i++) { if (f_readdir(curDir, myInfo)) break; if (myInfo->fname[0] == '.') continue; if (strstr(myInfo->fname, ".tmd") || strstr(myInfo->fname, ".TMD")) { memset(&path, 0, 256); sprintf(path, "%s/%s", folder, myInfo->fname); File tmp; if (!FileOpen(&tmp, path, 0)) continue; unsigned int size = FileGetSize(&tmp); if (size < 0xB34) { FileClose(&tmp); continue; } /* Get the TMD version */ /* There can be some instances in which more than one TMD/content file is available */ /* Of course, we want to use the latest one */ if (FileRead(&tmp, &cur_ver, 2, 0x1DC) != 2) { FileClose(&tmp); continue; } /* Change Endianness */ cur_ver = bswap_16(cur_ver); /* Verify the version number */ if ((latest_ver == 0 && !is_v0) || cur_ver > latest_ver) { tmd_chunk_struct tmd_entry; memset(&tmd_entry, 0xFF, 0x30); int cont = 0; unsigned int b_read = 0; while (tmd_entry.index != 0) { cont++; b_read = FileRead(&tmp, &tmd_entry, 0x30, size - (cont * 0x30)); if (b_read != 0x30) break; } FileClose(&tmp); if (b_read != 0x30) continue; memset(&path, 0, 256); sprintf(path, "%s/%08x.app", folder, bswap_32(tmd_entry.id)); // Change Endianness if (FileOpen(&tmp, path, 0)) { FileClose(&tmp); latest_ver = cur_ver; if (cur_ver == 0) is_v0 = true; /* Save TMD and content paths */ sprintf(tmdpath, "%s/%s", folder, myInfo->fname); sprintf(cntpath, "%s/%08x.app", folder, bswap_32(tmd_entry.id)); } } else { FileClose(&tmp); } } else { continue; } } f_closedir(curDir); if (latest_ver == 0 && !is_v0) return 0; return 1; } int CheckRegion(int drive) { File secureinfo; print("Opening SecureInfo_A... "); ConsoleShow(); sprintf(tmpstr, "%d:rw/sys/SecureInfo_A", drive); if (!FileOpen(&secureinfo, tmpstr, 0)) { print("Error.\nTrying with SecureInfo_B... "); ConsoleShow(); memset(&tmpstr, 0, 256); sprintf(tmpstr, "%d:rw/sys/SecureInfo_B", drive); if (!FileOpen(&secureinfo, tmpstr, 0)) { print("Error.\nProcess failed!\n"); ConsoleShow(); return -1; } } print("OK!\n"); ConsoleShow(); FileRead(&secureinfo, ®ion, 1, 0x100); FileClose(&secureinfo); if (region > 0x06) { print("Error: unsupported region.\nProcess failed!\n"); ConsoleShow(); return -1; } else { /* Avoid problems with the unused "AUS" region code */ if (region >= 3) region--; print("Region: %s\n", regions[region]); ConsoleShow(); } return 0; } int CheckRegionSilent(int drive) { File secureinfo; sprintf(tmpstr, "%d:rw/sys/SecureInfo_A", drive); if (!FileOpen(&secureinfo, tmpstr, 0)) { memset(&tmpstr, 0, 256); sprintf(tmpstr, "%d:rw/sys/SecureInfo_B", drive); if (!FileOpen(&secureinfo, tmpstr, 0)) { print("Error.\nProcess failed!\n"); ConsoleShow(); return -1; } } FileRead(&secureinfo, ®ion, 1, 0x100); FileClose(&secureinfo); if (region > 0x06) { print("Error: unsupported region.\nProcess failed!\n"); ConsoleShow(); return -1; } else { /* Avoid problems with the unused "AUS" region code */ if (region >= 3) region--; } return 0; } int checkDgFile(char* path, unsigned int hash) { unsigned char* buf = (unsigned char*)0x21000000; unsigned int rb, fixedsize = 0x00400000; File fp; if (FileOpen(&fp, path, 0)) { rb = FileRead(&fp, buf, fixedsize, 0); FileClose(&fp); if (!CheckHash(buf, rb, hash)) return 0; } else { return 0; } return 1; } void downgradeMSET() { File dg; char *dgpath = "0:msetdg.bin"; unsigned int titleid_low = 0x00040010; unsigned int titleid_high[6] = { 0x00020000, 0x00021000, 0x00022000, 0x00026000, 0x00027000, 0x00028000 }; //JPN, USA, EUR, CHN, KOR, TWN unsigned int mset_hash[10] = { 0x96AEC379, 0xED315608, 0x3387F2CD, 0xEDAC05D7, 0xACC1BE62, 0xF0FF9F08, 0x565BCF20, 0xA04654C6, 0xAFD07166, 0xD40B12F4 }; //JPN, USA, EUR, CHN, KOR, TWN unsigned short mset_ver[10] = { 3074, 5127, 3078, 5128, 3075, 5127, 8, 1026, 2049, 8 }; unsigned short mset_dg_ver = 0; ConsoleInit(); ConsoleSetTitle(" MSET DOWNGRADER"); int checkLoop = 0; CheckRegionSilent(SYS_NAND); print("What would you like to\nDowngrade to?\n\n"); ConsoleShow(); print("[A] 4.x MSET\n[B] 5.x/6.x MSET\n"); ConsoleShow(); InputWait(); while( checkLoop < 1 ) { InputWait(); char buttonInput = GetInput(); if (buttonInput == 1) { if (region == 0) { mset_dg_ver = 0; } else if (region == 1) { mset_dg_ver = 2; } else if (region == 2) { mset_dg_ver = 4; } else if (region == 3) { mset_dg_ver = 6; } else if (region == 4) { mset_dg_ver = 7; } else if (region == 5) { mset_dg_ver = 9; } else { print("region is: %u\n", region); ConsoleShow(); print("Unsupported Region!\n"); ConsoleShow(); mset_dg_ver = 0; } checkLoop = 1; } else if (buttonInput == 2) { if (region == 0) { mset_dg_ver = 1; } else if (region == 1) { mset_dg_ver = 3; } else if (region == 2) { mset_dg_ver = 5; } else if (region == 3) { mset_dg_ver = 6; print("CHN Region Detected!\nFalling back to 4.x MSET\n"); ConsoleShow(); } else if (region == 4) { mset_dg_ver = 8; } else if (region == 5) { mset_dg_ver = 9; print("TWN Region Detected!\nFalling back to 4.x MSET\n"); ConsoleShow(); } else { print("Unsupported Region!\n"); ConsoleShow(); mset_dg_ver = 0; } checkLoop = 1; } buttonInput = '\0'; } print("Opening MSET app...\n"); ConsoleShow(); if (CheckRegion(SYS_NAND) == 0) { if (FindApp(titleid_low, titleid_high[region], SYS_NAND)) // SysNAND only { if (FileOpen(&dg, tmdpath, 0)) { /* Get the MSET TMD version */ unsigned short tmd_ver; FileRead(&dg, &tmd_ver, 2, 0x1DC); tmd_ver = bswap_16(tmd_ver); FileClose(&dg); /* Verify version number */ if (tmd_ver > mset_ver[mset_dg_ver]) { /* Open MSET content file */ if (FileOpen(&dg, cntpath, 0)) { unsigned int check_val; FileRead(&dg, &check_val, 4, 0x130); FileClose(&dg); if (check_val != 0) { if (checkDgFile(dgpath, mset_hash[mset_dg_ver])) { print("Opening downgrade pack... "); ConsoleShow(); if (FileOpen(&dg, dgpath, 0)) { print("OK!\n"); ConsoleShow(); unsigned int dgsize = FileGetSize(&dg); unsigned char *buf = (unsigned char*)0x21000000; FileRead(&dg, buf, dgsize, 0); /* Downgrade pack decryption */ u8 iv[0x10] = {0}; u8 Key[0x10] = {0}; GetTitleKey(&Key[0], titleid_low, titleid_high[region], SYS_NAND); aes_context aes_ctxt; aes_setkey_dec(&aes_ctxt, Key, 0x80); aes_crypt_cbc(&aes_ctxt, AES_DECRYPT, dgsize, iv, buf, buf); FileWrite(&dg, buf, dgsize, 0); FileClose(&dg); if (*((unsigned int*)(buf + 0x100)) == 0x4843434E) // "NCCH" magic word { print("Downgrading... "); ConsoleShow(); if (FSFileCopy(cntpath, dgpath) == 0) { print("done!\nRemoving downgrade pack... "); ConsoleShow(); f_unlink(dgpath); print("done.\n"); ConsoleShow(); } else { print("\nError downgrading MSET content.\nRemoving downgrade pack... "); ConsoleShow(); f_unlink(dgpath); print("done.\n"); ConsoleShow(); } } else { print("Error: bad downgrade pack.\n"); ConsoleShow(); } } else { print("Error.\n"); ConsoleShow(); } } else { print("Error: bad downgrade pack.\n"); ConsoleShow(); } } else { print("Your MSET version is exploitable.\nDowngrade isn't necessary.\n"); ConsoleShow(); } } else { print("Error opening MSET content file.\n"); ConsoleShow(); } } else { print("Your MSET version is exploitable.\nDowngrade isn't necessary.\n"); ConsoleShow(); } } else { print("Error opening MSET TMD.\n"); ConsoleShow(); } } else { print("Error: couldn't find MSET data.\n"); ConsoleShow(); } } print("\nPress A to exit\n"); ConsoleShow(); WaitForButton(BUTTON_A); } void manageFBI(bool restore) { int drive; unsigned int titleid_low = 0x00040010; unsigned int titleid_high[6] = { 0x00020300, 0x00021300, 0x00022300, 0x00026300, 0x00027300, 0x00028300 }; //JPN, USA, EUR, CHN, KOR, TWN char *backup_path = "rxTools/h&s_backup"; File tmp; char path[256] = {0}; char path2[256] = {0}; unsigned char *buf = (unsigned char *)0x21000000; unsigned int size; unsigned short tmd_ver; unsigned int sd_cntsize; unsigned short sd_tmd_ver; unsigned char TmdCntInfoRecSum[32] = {0}; unsigned char CntInfoRecSum[32] = {0}; unsigned char TmdCntChnkRecSum[32] = {0}; unsigned char CntChnkRecSum[32] = {0}; unsigned char TmdCntDataSum[32] = {0}; unsigned char CntDataSum[32] = {0}; if ((drive = NandSwitch()) == UNK_NAND) return; ConsoleInit(); ConsoleSetTitle(restore ? " RESTORE HEALTH & SAFETY" : " FBI INSTALLATION"); if (CheckRegion(drive) == 0) { if (FindApp(titleid_low, titleid_high[region], drive)) { /* Open the NAND H&S TMD */ FileOpen(&tmp, tmdpath, 0); FileRead(&tmp, buf, 0xB34, 0); FileClose(&tmp); /* Get the title version from the TMD */ tmd_ver = (unsigned short)((buf[0x1DC] << 8) | buf[0x1DD]); print("TMD Version: v%u.\n", tmd_ver); if (!restore) { /* Get the stored content size from the TMD */ unsigned int cntsize = (unsigned int)((buf[0xB10] << 24) | (buf[0xB11] << 16) | (buf[0xB12] << 8) | buf[0xB13]); /* Open the NAND H&S content file and read it to the memory buffer */ FileOpen(&tmp, cntpath, 0); FileRead(&tmp, buf + 0x1000, cntsize, 0); FileClose(&tmp); /* Create the Health & Safety data backup directory */ f_mkdir(backup_path); memset(&tmpstr, 0, 256); sprintf(tmpstr, "%s/%s", backup_path, regions[region]); f_mkdir(tmpstr); memset(&tmpstr, 0, 256); sprintf(tmpstr, "%s/%s/v%u", backup_path, regions[region], tmd_ver); f_mkdir(tmpstr); /* Backup the H&S TMD */ sprintf(path, "0:%s/%.12s", tmpstr, tmdpath+34); if (FileOpen(&tmp, path, 1)) { size = FileWrite(&tmp, buf, 0xB34, 0); FileClose(&tmp); if (size == 0xB34) { print("NAND H&S TMD backup created.\n"); ConsoleShow(); /* Backup the H&S content file */ memset(&path, 0, 256); sprintf(path, "0:%s/%.12s", tmpstr, cntpath+34); if (FileOpen(&tmp, path, 1)) { size = FileWrite(&tmp, buf + 0x1000, cntsize, 0); FileClose(&tmp); if (size == cntsize) { print("NAND H&S content backup created.\n"); ConsoleShow(); } else { print("Error writing H&S content backup.\n"); ConsoleShow(); goto out; } } else { print("Error creating H&S content backup.\n"); ConsoleShow(); goto out; } } else { print("Error writing H&S TMD backup.\n"); ConsoleShow(); goto out; } } else { print("Error creating H&S TMD backup.\n"); ConsoleShow(); goto out; } /* Generate the FBI data paths */ sprintf(path, "0:fbi_inject.tmd"); sprintf(path2, "0:fbi_inject.app"); print("Editing H&S Information... "); ConsoleShow(); } else { /* Generate the H&S backup data paths */ memset(&tmpstr, 0, 256); sprintf(tmpstr, "%s/%s/v%u", backup_path, regions[region], tmd_ver); sprintf(path, "0:%s/%.12s", tmpstr, tmdpath+34); sprintf(path2, "0:%s/%.12s", tmpstr, cntpath+34); print("Restoring H&S Information... "); ConsoleShow(); } /* Open the SD TMD */ if (FileOpen(&tmp, path, 0)) { size = FileGetSize(&tmp); if (size == 0xB34) { FileRead(&tmp, buf, 0xB34, 0); FileClose(&tmp); /* Get the SD TMD version and stored content size */ sd_tmd_ver = (unsigned short)((buf[0x1DC] << 8) | buf[0x1DD]); sd_cntsize = (unsigned int)((buf[0xB10] << 24) | (buf[0xB11] << 16) | (buf[0xB12] << 8) | buf[0xB13]); if (sd_tmd_ver == tmd_ver) { /* Get the SHA-256 hashes */ memcpy(TmdCntInfoRecSum, buf + 0x1E4, 32); memcpy(TmdCntChnkRecSum, buf + 0x208, 32); memcpy(TmdCntDataSum, buf + 0xB14, 32); /* Verify the Content Info Record hash */ sha2(buf + 0x204, 0x900, CntInfoRecSum, 0); if (memcmp(CntInfoRecSum, TmdCntInfoRecSum, 32) == 0) { /* Verify the Content Chunk Record hash */ sha2(buf + 0xB04, 0x30, CntChnkRecSum, 0); if (memcmp(CntChnkRecSum, TmdCntChnkRecSum, 32) == 0) { /* Open the SD content file */ if (FileOpen(&tmp, path2, 0)) { size = FileGetSize(&tmp); if (size == sd_cntsize) { FileRead(&tmp, buf + 0x1000, sd_cntsize, 0); FileClose(&tmp); /* Verify the Content Data hash */ sha2(buf + 0x1000, sd_cntsize, CntDataSum, 0); if (memcmp(CntDataSum, TmdCntDataSum, 32) == 0) { /* Now we are ready to rock 'n roll */ if (FSFileCopy(tmdpath, path) == 0) { if (FSFileCopy(cntpath, path2) == 0) { print("OK!\nDeleting %s data... ", restore ? "backup" : "FBI injection"); ConsoleShow(); f_unlink(path); f_unlink(path2); print("OK!\n"); ConsoleShow(); } else { print("\nError %s content file.\n", restore ? "restoring H&S" : "injecting FBI"); ConsoleShow(); } } else { print("\nError %s TMD.\n", restore ? "restoring H&S" : "injecting FBI"); ConsoleShow(); } } else { print("\nError: invalid Content Data hash.\nGot:\n"); ConsoleShow(); print_sha256(CntDataSum); print("\nExpected:\n"); ConsoleShow(); print_sha256(TmdCntDataSum); } } else { FileClose(&tmp); print("\nInvalid %s content size.\nGot: v%u / Expected: v%u\n", restore ? "backup" : "FBI", size, sd_cntsize); ConsoleShow(); } } else { print("\nError opening %s content.\n", restore ? "backup" : "FBI"); } } else { print("\nError: invalid Content Chunk hash.\nGot:\n"); ConsoleShow(); print_sha256(CntChnkRecSum); print("\nExpected:\n"); ConsoleShow(); print_sha256(TmdCntChnkRecSum); } } else { print("\nError: invalid Content Info hash.\nGot:\n"); ConsoleShow(); print_sha256(CntInfoRecSum); print("\nExpected:\n"); ConsoleShow(); print_sha256(TmdCntInfoRecSum); } } else { print("\nError: invalid %s TMD version.\nGot: v%u / Expected: v%u\n", restore ? "backup" : "FBI", sd_tmd_ver, tmd_ver); ConsoleShow(); } } else { FileClose(&tmp); print("\nError: invalid %s TMD size.\nGot: %u / Expected: %u\n", restore ? "backup" : "FBI", size, 0xB34); ConsoleShow(); } } else { print("\nError opening %s TMD.\n", restore ? "backup" : "FBI"); ConsoleShow(); } } else { print("Error: couldn't find H&S data.\n"); ConsoleShow(); } } out: print("\nPress A to exit."); ConsoleShow(); WaitForButton(BUTTON_A); } void installFBI() { /* Injects FBI TMD and content file to the Health & Safety App */ manageFBI(false); } void restoreHS() { /* Restores original Health & Safety TMD and content file to the NAND */ manageFBI(true); }
3.0b7 is a beta build of rxTools 3.0. If you're using code.bins for installing the ROP chain, I recommend you try the nds installer, or make sure the code.bin is actually designed for your version of MSET and firmware.just try you new beta, but stuck at ... d Rop file LoadCode.dat :ok
executing .... (i saw screen bliking ... )
then nothing ...
im on o3ds xl 9.2
rxtools 2.6 wa booting great, i did remplace code.bin, rxtools.dat ... and add theme folder ...
3.0b7 is a beta build of rxTools 3.0. If you're using code.bins for installing the ROP chain, I recommend you try the nds installer, or make sure the code.bin is actually designed for your version of MSET and firmware.
If you're on a 3DSXL, you really don't need this anyway, and it won't bring anything useful for you.
is this version stable?Alright! Time for rxTools 3.0b7!
Added: 6.x MSET Downgrade features from downgrade menu
Added: 6.x MSET Downgrade options to msetdg.py
Added: 6.x-modified rxinstaller.nds by @Apache Thunder
Enjoy!
Download: https://anonfiles.com/file/993ca626533f4fa4cb34db434b6438b4
Modified source:
Code:#!/usr/bin/python # -*- coding: utf-8 -*- from urllib2 import urlopen, URLError, HTTPError import platform import os try: fileName = "msetdg.bin"; tid = [0x00020000, 0x00020000, 0x00021000, 0x00021000, 0x00022000, 0x00022000, 0x00027000, 0x00027000, 0x00026000, 0x00028000] #JPN 4/6, USA 4/6, EUR 4/6, KOR 4/5, CHN 4, TWN 4 tver = [0x1A, 0x22, 0x1F, 0x2D, 0x19, 0x23, 0x04, 0x08, 0x06, 0x05] choice = 0 while choice not in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10): os.system('cls') if platform.system() == "Windows" else os.system('clear') print "Select your 3DS region :\n\n [1] JPN (4.x MSET)\n [2] JPN (6.x MSET)\n\n [3] USA (4.x MSET)\n [4] USA (6.x MSET)\n\n [5] EUR (4.x MSET)\n [6] EUR (6.x MSET)\n\n [7] KOR (4.x MSET)\n [8] KOR (5.x MSET)\n\n [9] CHN (4.x MSET)\n\n [10] TWN (4.x MSET)\n" choice = int(raw_input("Selection : ")) url="http://nus.cdn.c.shop.nintendowifi.net/ccs/download/00040010%08X/%08X"%(tid[choice-1], tver[choice-1]) print "Downloading MSET from the CDN..." f = urlopen(url) with open(fileName, "wb") as lf: lf.write(f.read()) print "Downloaded!" except HTTPError, e: print "HTTP Error:", e.code, url except URLError, e: print "URL Error:", e.reason, url
Code:#include "downgradeapp.h" #include "common.h" #include "screenshot.h" #include "fs.h" #include "ff.h" #include "console.h" #include "draw.h" #include "hid.h" #include "ncch.h" #include "crypto.h" #include "TitleKeyDecrypt.h" #include "NandDumper.h" #include "aes.h" #include "polarssl/sha2.h" #include "stdio.h" #include "filepack.h" #define bswap_16(a) ((((a) << 8) & 0xff00) | (((a) >> 8) & 0xff)) #define bswap_32(a) ((((a) << 24) & 0xff000000) | (((a) << 8) & 0xff0000) | (((a) >> 8) & 0xff00) | (((a) >> 24) & 0xff)) typedef struct { unsigned int id; unsigned short index; unsigned short type; unsigned int size; unsigned char signature[0x20]; } tmd_chunk_struct; unsigned char region = 0; char *regions[6] = { "Japan", "USA", "Europe", "China", "Korea", "Taiwan" }; char tmpstr[256]; FILINFO curInfo; DIR myDir; char cntpath[256]; // Contains the NAND content path char tmdpath[256]; // Contains the NAND TMD path char* getContentAppPath(){ return (char*)&cntpath; } char* getTMDAppPath(){ return (char*)&tmdpath; } void print_sha256(unsigned char hash[32]) { int i; for (i = 0; i < 32; i++) { print("%02X", hash[i]); if (i == 16) { /* Continue printing the SHA-256 sum in a new line after 34 characters (17 bytes) */ print("\n"); ConsoleShow(); } } ConsoleShow(); } int FindApp(unsigned int tid_low, unsigned int tid_high, int drive) { char *folder = (char*)&tmpstr; memset(folder, 0, 256); DIR* curDir = &myDir; memset((unsigned char*)curDir, 0, sizeof(DIR)); FILINFO *myInfo = &curInfo; memset((unsigned char*)myInfo, 0, sizeof(FILINFO)); myInfo->fname[0] = 'A'; sprintf(folder, "%d:title/%08x/%08x/content", drive, tid_low, tid_high); if (f_opendir(curDir, folder) != FR_OK) return 0; char path[256]; unsigned short latest_ver = 0, cur_ver = 0; bool is_v0 = false; for (int i = 0; myInfo->fname[0] != 0; i++) { if (f_readdir(curDir, myInfo)) break; if (myInfo->fname[0] == '.') continue; if (strstr(myInfo->fname, ".tmd") || strstr(myInfo->fname, ".TMD")) { memset(&path, 0, 256); sprintf(path, "%s/%s", folder, myInfo->fname); File tmp; if (!FileOpen(&tmp, path, 0)) continue; unsigned int size = FileGetSize(&tmp); if (size < 0xB34) { FileClose(&tmp); continue; } /* Get the TMD version */ /* There can be some instances in which more than one TMD/content file is available */ /* Of course, we want to use the latest one */ if (FileRead(&tmp, &cur_ver, 2, 0x1DC) != 2) { FileClose(&tmp); continue; } /* Change Endianness */ cur_ver = bswap_16(cur_ver); /* Verify the version number */ if ((latest_ver == 0 && !is_v0) || cur_ver > latest_ver) { tmd_chunk_struct tmd_entry; memset(&tmd_entry, 0xFF, 0x30); int cont = 0; unsigned int b_read = 0; while (tmd_entry.index != 0) { cont++; b_read = FileRead(&tmp, &tmd_entry, 0x30, size - (cont * 0x30)); if (b_read != 0x30) break; } FileClose(&tmp); if (b_read != 0x30) continue; memset(&path, 0, 256); sprintf(path, "%s/%08x.app", folder, bswap_32(tmd_entry.id)); // Change Endianness if (FileOpen(&tmp, path, 0)) { FileClose(&tmp); latest_ver = cur_ver; if (cur_ver == 0) is_v0 = true; /* Save TMD and content paths */ sprintf(tmdpath, "%s/%s", folder, myInfo->fname); sprintf(cntpath, "%s/%08x.app", folder, bswap_32(tmd_entry.id)); } } else { FileClose(&tmp); } } else { continue; } } f_closedir(curDir); if (latest_ver == 0 && !is_v0) return 0; return 1; } int CheckRegion(int drive) { File secureinfo; print("Opening SecureInfo_A... "); ConsoleShow(); sprintf(tmpstr, "%d:rw/sys/SecureInfo_A", drive); if (!FileOpen(&secureinfo, tmpstr, 0)) { print("Error.\nTrying with SecureInfo_B... "); ConsoleShow(); memset(&tmpstr, 0, 256); sprintf(tmpstr, "%d:rw/sys/SecureInfo_B", drive); if (!FileOpen(&secureinfo, tmpstr, 0)) { print("Error.\nProcess failed!\n"); ConsoleShow(); return -1; } } print("OK!\n"); ConsoleShow(); FileRead(&secureinfo, ®ion, 1, 0x100); FileClose(&secureinfo); if (region > 0x06) { print("Error: unsupported region.\nProcess failed!\n"); ConsoleShow(); return -1; } else { /* Avoid problems with the unused "AUS" region code */ if (region >= 3) region--; print("Region: %s\n", regions[region]); ConsoleShow(); } return 0; } int CheckRegionSilent(int drive) { File secureinfo; sprintf(tmpstr, "%d:rw/sys/SecureInfo_A", drive); if (!FileOpen(&secureinfo, tmpstr, 0)) { memset(&tmpstr, 0, 256); sprintf(tmpstr, "%d:rw/sys/SecureInfo_B", drive); if (!FileOpen(&secureinfo, tmpstr, 0)) { print("Error.\nProcess failed!\n"); ConsoleShow(); return -1; } } FileRead(&secureinfo, ®ion, 1, 0x100); FileClose(&secureinfo); if (region > 0x06) { print("Error: unsupported region.\nProcess failed!\n"); ConsoleShow(); return -1; } else { /* Avoid problems with the unused "AUS" region code */ if (region >= 3) region--; } return 0; } int checkDgFile(char* path, unsigned int hash) { unsigned char* buf = (unsigned char*)0x21000000; unsigned int rb, fixedsize = 0x00400000; File fp; if (FileOpen(&fp, path, 0)) { rb = FileRead(&fp, buf, fixedsize, 0); FileClose(&fp); if (!CheckHash(buf, rb, hash)) return 0; } else { return 0; } return 1; } void downgradeMSET() { File dg; char *dgpath = "0:msetdg.bin"; unsigned int titleid_low = 0x00040010; unsigned int titleid_high[6] = { 0x00020000, 0x00021000, 0x00022000, 0x00026000, 0x00027000, 0x00028000 }; //JPN, USA, EUR, CHN, KOR, TWN unsigned int mset_hash[10] = { 0x96AEC379, 0xED315608, 0x3387F2CD, 0xEDAC05D7, 0xACC1BE62, 0xF0FF9F08, 0x565BCF20, 0xA04654C6, 0xAFD07166, 0xD40B12F4 }; //JPN, USA, EUR, CHN, KOR, TWN unsigned short mset_ver[10] = { 3074, 5127, 3078, 5128, 3075, 5127, 8, 1026, 2049, 8 }; unsigned short mset_dg_ver = 0; ConsoleInit(); ConsoleSetTitle(" MSET DOWNGRADER"); int checkLoop = 0; CheckRegionSilent(SYS_NAND); print("What would you like to\nDowngrade to?\n\n"); ConsoleShow(); print("[A] 4.x MSET\n[B] 5.x/6.x MSET\n"); ConsoleShow(); InputWait(); while( checkLoop < 1 ) { InputWait(); char buttonInput = GetInput(); if (buttonInput == 1) { if (region == 0) { mset_dg_ver = 0; } else if (region == 1) { mset_dg_ver = 2; } else if (region == 2) { mset_dg_ver = 4; } else if (region == 3) { mset_dg_ver = 6; } else if (region == 4) { mset_dg_ver = 7; } else if (region == 5) { mset_dg_ver = 9; } else { print("region is: %u\n", region); ConsoleShow(); print("Unsupported Region!\n"); ConsoleShow(); mset_dg_ver = 0; } checkLoop = 1; } else if (buttonInput == 2) { if (region == 0) { mset_dg_ver = 1; } else if (region == 1) { mset_dg_ver = 3; } else if (region == 2) { mset_dg_ver = 5; } else if (region == 3) { mset_dg_ver = 6; print("CHN Region Detected!\nFalling back to 4.x MSET\n"); ConsoleShow(); } else if (region == 4) { mset_dg_ver = 8; } else if (region == 5) { mset_dg_ver = 9; print("TWN Region Detected!\nFalling back to 4.x MSET\n"); ConsoleShow(); } else { print("Unsupported Region!\n"); ConsoleShow(); mset_dg_ver = 0; } checkLoop = 1; } buttonInput = '\0'; } print("Opening MSET app...\n"); ConsoleShow(); if (CheckRegion(SYS_NAND) == 0) { if (FindApp(titleid_low, titleid_high[region], SYS_NAND)) // SysNAND only { if (FileOpen(&dg, tmdpath, 0)) { /* Get the MSET TMD version */ unsigned short tmd_ver; FileRead(&dg, &tmd_ver, 2, 0x1DC); tmd_ver = bswap_16(tmd_ver); FileClose(&dg); /* Verify version number */ if (tmd_ver > mset_ver[mset_dg_ver]) { /* Open MSET content file */ if (FileOpen(&dg, cntpath, 0)) { unsigned int check_val; FileRead(&dg, &check_val, 4, 0x130); FileClose(&dg); if (check_val != 0) { if (checkDgFile(dgpath, mset_hash[mset_dg_ver])) { print("Opening downgrade pack... "); ConsoleShow(); if (FileOpen(&dg, dgpath, 0)) { print("OK!\n"); ConsoleShow(); unsigned int dgsize = FileGetSize(&dg); unsigned char *buf = (unsigned char*)0x21000000; FileRead(&dg, buf, dgsize, 0); /* Downgrade pack decryption */ u8 iv[0x10] = {0}; u8 Key[0x10] = {0}; GetTitleKey(&Key[0], titleid_low, titleid_high[region], SYS_NAND); aes_context aes_ctxt; aes_setkey_dec(&aes_ctxt, Key, 0x80); aes_crypt_cbc(&aes_ctxt, AES_DECRYPT, dgsize, iv, buf, buf); FileWrite(&dg, buf, dgsize, 0); FileClose(&dg); if (*((unsigned int*)(buf + 0x100)) == 0x4843434E) // "NCCH" magic word { print("Downgrading... "); ConsoleShow(); if (FSFileCopy(cntpath, dgpath) == 0) { print("done!\nRemoving downgrade pack... "); ConsoleShow(); f_unlink(dgpath); print("done.\n"); ConsoleShow(); } else { print("\nError downgrading MSET content.\nRemoving downgrade pack... "); ConsoleShow(); f_unlink(dgpath); print("done.\n"); ConsoleShow(); } } else { print("Error: bad downgrade pack.\n"); ConsoleShow(); } } else { print("Error.\n"); ConsoleShow(); } } else { print("Error: bad downgrade pack.\n"); ConsoleShow(); } } else { print("Your MSET version is exploitable.\nDowngrade isn't necessary.\n"); ConsoleShow(); } } else { print("Error opening MSET content file.\n"); ConsoleShow(); } } else { print("Your MSET version is exploitable.\nDowngrade isn't necessary.\n"); ConsoleShow(); } } else { print("Error opening MSET TMD.\n"); ConsoleShow(); } } else { print("Error: couldn't find MSET data.\n"); ConsoleShow(); } } print("\nPress A to exit\n"); ConsoleShow(); WaitForButton(BUTTON_A); } void manageFBI(bool restore) { int drive; unsigned int titleid_low = 0x00040010; unsigned int titleid_high[6] = { 0x00020300, 0x00021300, 0x00022300, 0x00026300, 0x00027300, 0x00028300 }; //JPN, USA, EUR, CHN, KOR, TWN char *backup_path = "rxTools/h&s_backup"; File tmp; char path[256] = {0}; char path2[256] = {0}; unsigned char *buf = (unsigned char *)0x21000000; unsigned int size; unsigned short tmd_ver; unsigned int sd_cntsize; unsigned short sd_tmd_ver; unsigned char TmdCntInfoRecSum[32] = {0}; unsigned char CntInfoRecSum[32] = {0}; unsigned char TmdCntChnkRecSum[32] = {0}; unsigned char CntChnkRecSum[32] = {0}; unsigned char TmdCntDataSum[32] = {0}; unsigned char CntDataSum[32] = {0}; if ((drive = NandSwitch()) == UNK_NAND) return; ConsoleInit(); ConsoleSetTitle(restore ? " RESTORE HEALTH & SAFETY" : " FBI INSTALLATION"); if (CheckRegion(drive) == 0) { if (FindApp(titleid_low, titleid_high[region], drive)) { /* Open the NAND H&S TMD */ FileOpen(&tmp, tmdpath, 0); FileRead(&tmp, buf, 0xB34, 0); FileClose(&tmp); /* Get the title version from the TMD */ tmd_ver = (unsigned short)((buf[0x1DC] << 8) | buf[0x1DD]); print("TMD Version: v%u.\n", tmd_ver); if (!restore) { /* Get the stored content size from the TMD */ unsigned int cntsize = (unsigned int)((buf[0xB10] << 24) | (buf[0xB11] << 16) | (buf[0xB12] << 8) | buf[0xB13]); /* Open the NAND H&S content file and read it to the memory buffer */ FileOpen(&tmp, cntpath, 0); FileRead(&tmp, buf + 0x1000, cntsize, 0); FileClose(&tmp); /* Create the Health & Safety data backup directory */ f_mkdir(backup_path); memset(&tmpstr, 0, 256); sprintf(tmpstr, "%s/%s", backup_path, regions[region]); f_mkdir(tmpstr); memset(&tmpstr, 0, 256); sprintf(tmpstr, "%s/%s/v%u", backup_path, regions[region], tmd_ver); f_mkdir(tmpstr); /* Backup the H&S TMD */ sprintf(path, "0:%s/%.12s", tmpstr, tmdpath+34); if (FileOpen(&tmp, path, 1)) { size = FileWrite(&tmp, buf, 0xB34, 0); FileClose(&tmp); if (size == 0xB34) { print("NAND H&S TMD backup created.\n"); ConsoleShow(); /* Backup the H&S content file */ memset(&path, 0, 256); sprintf(path, "0:%s/%.12s", tmpstr, cntpath+34); if (FileOpen(&tmp, path, 1)) { size = FileWrite(&tmp, buf + 0x1000, cntsize, 0); FileClose(&tmp); if (size == cntsize) { print("NAND H&S content backup created.\n"); ConsoleShow(); } else { print("Error writing H&S content backup.\n"); ConsoleShow(); goto out; } } else { print("Error creating H&S content backup.\n"); ConsoleShow(); goto out; } } else { print("Error writing H&S TMD backup.\n"); ConsoleShow(); goto out; } } else { print("Error creating H&S TMD backup.\n"); ConsoleShow(); goto out; } /* Generate the FBI data paths */ sprintf(path, "0:fbi_inject.tmd"); sprintf(path2, "0:fbi_inject.app"); print("Editing H&S Information... "); ConsoleShow(); } else { /* Generate the H&S backup data paths */ memset(&tmpstr, 0, 256); sprintf(tmpstr, "%s/%s/v%u", backup_path, regions[region], tmd_ver); sprintf(path, "0:%s/%.12s", tmpstr, tmdpath+34); sprintf(path2, "0:%s/%.12s", tmpstr, cntpath+34); print("Restoring H&S Information... "); ConsoleShow(); } /* Open the SD TMD */ if (FileOpen(&tmp, path, 0)) { size = FileGetSize(&tmp); if (size == 0xB34) { FileRead(&tmp, buf, 0xB34, 0); FileClose(&tmp); /* Get the SD TMD version and stored content size */ sd_tmd_ver = (unsigned short)((buf[0x1DC] << 8) | buf[0x1DD]); sd_cntsize = (unsigned int)((buf[0xB10] << 24) | (buf[0xB11] << 16) | (buf[0xB12] << 8) | buf[0xB13]); if (sd_tmd_ver == tmd_ver) { /* Get the SHA-256 hashes */ memcpy(TmdCntInfoRecSum, buf + 0x1E4, 32); memcpy(TmdCntChnkRecSum, buf + 0x208, 32); memcpy(TmdCntDataSum, buf + 0xB14, 32); /* Verify the Content Info Record hash */ sha2(buf + 0x204, 0x900, CntInfoRecSum, 0); if (memcmp(CntInfoRecSum, TmdCntInfoRecSum, 32) == 0) { /* Verify the Content Chunk Record hash */ sha2(buf + 0xB04, 0x30, CntChnkRecSum, 0); if (memcmp(CntChnkRecSum, TmdCntChnkRecSum, 32) == 0) { /* Open the SD content file */ if (FileOpen(&tmp, path2, 0)) { size = FileGetSize(&tmp); if (size == sd_cntsize) { FileRead(&tmp, buf + 0x1000, sd_cntsize, 0); FileClose(&tmp); /* Verify the Content Data hash */ sha2(buf + 0x1000, sd_cntsize, CntDataSum, 0); if (memcmp(CntDataSum, TmdCntDataSum, 32) == 0) { /* Now we are ready to rock 'n roll */ if (FSFileCopy(tmdpath, path) == 0) { if (FSFileCopy(cntpath, path2) == 0) { print("OK!\nDeleting %s data... ", restore ? "backup" : "FBI injection"); ConsoleShow(); f_unlink(path); f_unlink(path2); print("OK!\n"); ConsoleShow(); } else { print("\nError %s content file.\n", restore ? "restoring H&S" : "injecting FBI"); ConsoleShow(); } } else { print("\nError %s TMD.\n", restore ? "restoring H&S" : "injecting FBI"); ConsoleShow(); } } else { print("\nError: invalid Content Data hash.\nGot:\n"); ConsoleShow(); print_sha256(CntDataSum); print("\nExpected:\n"); ConsoleShow(); print_sha256(TmdCntDataSum); } } else { FileClose(&tmp); print("\nInvalid %s content size.\nGot: v%u / Expected: v%u\n", restore ? "backup" : "FBI", size, sd_cntsize); ConsoleShow(); } } else { print("\nError opening %s content.\n", restore ? "backup" : "FBI"); } } else { print("\nError: invalid Content Chunk hash.\nGot:\n"); ConsoleShow(); print_sha256(CntChnkRecSum); print("\nExpected:\n"); ConsoleShow(); print_sha256(TmdCntChnkRecSum); } } else { print("\nError: invalid Content Info hash.\nGot:\n"); ConsoleShow(); print_sha256(CntInfoRecSum); print("\nExpected:\n"); ConsoleShow(); print_sha256(TmdCntInfoRecSum); } } else { print("\nError: invalid %s TMD version.\nGot: v%u / Expected: v%u\n", restore ? "backup" : "FBI", sd_tmd_ver, tmd_ver); ConsoleShow(); } } else { FileClose(&tmp); print("\nError: invalid %s TMD size.\nGot: %u / Expected: %u\n", restore ? "backup" : "FBI", size, 0xB34); ConsoleShow(); } } else { print("\nError opening %s TMD.\n", restore ? "backup" : "FBI"); ConsoleShow(); } } else { print("Error: couldn't find H&S data.\n"); ConsoleShow(); } } out: print("\nPress A to exit."); ConsoleShow(); WaitForButton(BUTTON_A); } void installFBI() { /* Injects FBI TMD and content file to the Health & Safety App */ manageFBI(false); } void restoreHS() { /* Restores original Health & Safety TMD and content file to the NAND */ manageFBI(true); }
It's a beta, there's no such thing as "stable". All it has is the "works for me" guarantee. Tested it pretty hard though, to make sure it was tight. Sometimes it auto catches the "A" button and tries to go from there though, so if it does, it's either installing the 4.x ROP chain like you wanted anyway, or it'll error with wrong hash for the downgrade pack (because wrong version) and you can exit and try again. Either way, no brick risk.is this version stable?
If everything works fine, you should send a pull request.
https://github.com/roxas75/rxTools/pulls
If you still have NNID available in MSET, you didn't downgrade MSET.im really lost, downgrated mset but still have nnid option in setting, and rop.nds not working, cant boot via mset ....
If you want to "remove" the DS Cart Whitelist...Don't. It will brick TWL mode if you try to run TWL without it installed. You should "downgrade" it instead.