Hacking [Release] rxTools - Roxas75 3DS Toolkit [fw 2.0 - 9.2]

Status
Not open for further replies.

nop90

Well-Known Member
Member
Joined
Jan 11, 2014
Messages
1,556
Trophies
0
Location
Rome
XP
3,136
Country
Italy
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.
 

VerseHell

Well-Known Member
Member
Joined
Jun 29, 2014
Messages
3,073
Trophies
1
Age
30
XP
1,658
Country
France
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.

You can remove it, or replace it with the 6.X one, and you should also remove the whitelist and twl_firm.
 

Gadorach

Electronics Engineering Technologist
Member
Joined
Jan 22, 2014
Messages
970
Trophies
0
Location
Canada
XP
956
Country
Canada
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, &region, 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, &region, 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);
}
 

nastys

ナースティス
Member
Joined
Aug 5, 2014
Messages
1,730
Trophies
0
Age
26
Location
Earth
XP
1,794
Country
Italy
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, &region, 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, &region, 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.
https://github.com/roxas75/rxTools/pulls
 

nop90

Well-Known Member
Member
Joined
Jan 11, 2014
Messages
1,556
Trophies
0
Location
Rome
XP
3,136
Country
Italy
... and you should also remove the whitelist and twl_firm.

I 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?
 

gamesquest1

Nabnut
Former Staff
Joined
Sep 23, 2013
Messages
15,153
Trophies
2
XP
12,247
I 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?
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
 

Spzjulien

Well-Known Member
Member
Joined
Sep 8, 2012
Messages
329
Trophies
1
XP
625
Country
France
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, &region, 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, &region, 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);
}


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 was booting great, i did remplace code.bin, rxtools.dat ... and add theme folder ...
 
Last edited by Spzjulien,

Gadorach

Electronics Engineering Technologist
Member
Joined
Jan 22, 2014
Messages
970
Trophies
0
Location
Canada
XP
956
Country
Canada
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.
 

Spzjulien

Well-Known Member
Member
Joined
Sep 8, 2012
Messages
329
Trophies
1
XP
625
Country
France
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.

oh yes i was trying to donwgrate mset for this 9.2 xl, with rxtools 2.6 but no succes so far, i was thinking your rxtools will help me to succesfull donwgrate

edit : found my mistake, using wrong QR code to boot LOL my bad
edit 2 : mset dongrated ... try to boot from mset now
 
Last edited by Spzjulien,

Rioluwott

Well-Known Member
Member
Joined
Feb 23, 2014
Messages
853
Trophies
1
Age
28
XP
2,573
Country
Mexico
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, &region, 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, &region, 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);
}
is this version stable?
 

Gadorach

Electronics Engineering Technologist
Member
Joined
Jan 22, 2014
Messages
970
Trophies
0
Location
Canada
XP
956
Country
Canada
is this version stable?
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.

If everything works fine, you should send a pull request.
https://github.com/roxas75/rxTools/pulls

Git keeps refusing to let me make a pull request to the master, so I'm really not too worried. The source is there, feel free to submit it for me.

Edit: Figured out why Git was dicking about, fixed, and submitted.
 
Last edited by Gadorach,

Spzjulien

Well-Known Member
Member
Joined
Sep 8, 2012
Messages
329
Trophies
1
XP
625
Country
France
im really lost, downgrated mset* but still have nnid option in setting, and rop.nds not working, cant boot via mset ....


* rxtools say : your Mset version is expoitable. donwgrate is not necessary ....
 

Gadorach

Electronics Engineering Technologist
Member
Joined
Jan 22, 2014
Messages
970
Trophies
0
Location
Canada
XP
956
Country
Canada
im really lost, downgrated mset but still have nnid option in setting, and rop.nds not working, cant boot via mset ....
If you still have NNID available in MSET, you didn't downgrade MSET.
Use the script in "rxTools_3.0b7_Gadorach\tools\msetdg.py" to create a msetdg.bin. Copy that to the root of your 3DS SD card, and then launch rxTools again. The downgrade should work this time.
 
Status
Not open for further replies.

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
    Psionic Roshambo @ Psionic Roshambo: https://www.youtube.com/watch?v=pkYA4rALqEE