From 1fec5c15d46af4fc5c72d6e118477683f05a35c6 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Sat, 7 Jan 2023 21:42:13 -0800 Subject: [PATCH] Fix N3DS parsing and printing --- BurnOutSharp.Builders/N3DS.cs | 30 +++---- BurnOutSharp.Models/N3DS/InitialData.cs | 3 +- BurnOutSharp.Models/N3DS/NCCHHeader.cs | 2 +- BurnOutSharp.Wrappers/N3DS.cs | 110 +++++++++++++++++------- 4 files changed, 98 insertions(+), 47 deletions(-) diff --git a/BurnOutSharp.Builders/N3DS.cs b/BurnOutSharp.Builders/N3DS.cs index 32ac33e6..c134c1c2 100644 --- a/BurnOutSharp.Builders/N3DS.cs +++ b/BurnOutSharp.Builders/N3DS.cs @@ -82,17 +82,13 @@ namespace BurnOutSharp.Builders #region Development Card Info Header - // TODO: Hook up a builder flag to enable development parsing - if (false) - { - // Try to parse the development card info header - var developmentCardInfoHeader = ParseDevelopmentCardInfoHeader(data); - if (developmentCardInfoHeader == null) - return null; + // Try to parse the development card info header + var developmentCardInfoHeader = ParseDevelopmentCardInfoHeader(data); + if (developmentCardInfoHeader == null) + return null; - // Set the development card info header - cart.DevelopmentCardInfoHeader = developmentCardInfoHeader; - } + // Set the development card info header + cart.DevelopmentCardInfoHeader = developmentCardInfoHeader; #endregion @@ -109,6 +105,10 @@ namespace BurnOutSharp.Builders #endregion + // TODO: Parse partition extended headers (decrypted only) + // TODO: Parse ExeFS file entries (decrypted only) + // TODO: Parse ExeFS filename table (decrypted only) + return cart; } @@ -124,7 +124,7 @@ namespace BurnOutSharp.Builders header.RSA2048Signature = data.ReadBytes(0x100); byte[] magicNumber = data.ReadBytes(4); - header.MagicNumber = Encoding.ASCII.GetString(magicNumber).TrimEnd('\0');; + header.MagicNumber = Encoding.ASCII.GetString(magicNumber).TrimEnd('\0'); ; if (header.MagicNumber != NCSDMagicNumber) return null; @@ -269,10 +269,7 @@ namespace BurnOutSharp.Builders header.RSA2048Signature = data.ReadBytes(0x100); byte[] magicId = data.ReadBytes(4); - header.MagicID = Encoding.ASCII.GetString(magicId).TrimEnd('\0');; - if (header.MagicID != NCCHMagicNumber) - return null; - + header.MagicID = Encoding.ASCII.GetString(magicId).TrimEnd('\0'); header.ContentSizeInMediaUnits = data.ReadUInt32(); header.PartitionId = data.ReadUInt64(); header.MakerCode = data.ReadUInt16(); @@ -281,7 +278,8 @@ namespace BurnOutSharp.Builders header.ProgramId = data.ReadBytes(8); header.Reserved1 = data.ReadBytes(0x10); header.LogoRegionHash = data.ReadBytes(0x20); - header.ProductCode = data.ReadBytes(0x10); + byte[] productCode = data.ReadBytes(0x10); + header.ProductCode = Encoding.ASCII.GetString(productCode).TrimEnd('\0'); header.ExtendedHeaderHash = data.ReadBytes(0x20); header.ExtendedHeaderSizeInBytes = data.ReadUInt32(); header.Reserved2 = data.ReadBytes(4); diff --git a/BurnOutSharp.Models/N3DS/InitialData.cs b/BurnOutSharp.Models/N3DS/InitialData.cs index 9415671c..1b57c223 100644 --- a/BurnOutSharp.Models/N3DS/InitialData.cs +++ b/BurnOutSharp.Models/N3DS/InitialData.cs @@ -9,7 +9,8 @@ namespace BurnOutSharp.Models.N3DS public byte[] CardSeedKeyY; /// - /// Encrypted card seed (AES-CCM, keyslot 0x3B for retail cards, see CTRCARD_SECSEED) /// + /// Encrypted card seed (AES-CCM, keyslot 0x3B for retail cards, see CTRCARD_SECSEED) + /// public byte[] EncryptedCardSeed; /// diff --git a/BurnOutSharp.Models/N3DS/NCCHHeader.cs b/BurnOutSharp.Models/N3DS/NCCHHeader.cs index c363398b..1ea8c092 100644 --- a/BurnOutSharp.Models/N3DS/NCCHHeader.cs +++ b/BurnOutSharp.Models/N3DS/NCCHHeader.cs @@ -59,7 +59,7 @@ /// /// Product code /// - public byte[] ProductCode; + public string ProductCode; /// /// Extended header SHA-256 hash (SHA256 of 2x Alignment Size, beginning at 0x0 of ExHeader) diff --git a/BurnOutSharp.Wrappers/N3DS.cs b/BurnOutSharp.Wrappers/N3DS.cs index d8371b1a..64977ab9 100644 --- a/BurnOutSharp.Wrappers/N3DS.cs +++ b/BurnOutSharp.Wrappers/N3DS.cs @@ -371,6 +371,39 @@ namespace BurnOutSharp.Wrappers Console.WriteLine($" Card seed AES-MAC: {BitConverter.ToString(DCIH_ID_CardSeedAESMAC).Replace('-', ' ')}"); Console.WriteLine($" Card seed nonce: {BitConverter.ToString(DCIH_ID_CardSeedNonce).Replace('-', ' ')}"); Console.WriteLine($" Reserved: {BitConverter.ToString(DCIH_ID_Reserved).Replace('-', ' ')}"); + Console.WriteLine(); + + Console.WriteLine(" Backup Header:"); + Console.WriteLine(" -------------------------"); + Console.WriteLine($" Magic ID: {DCIH_ID_BackupHeader.MagicID}"); + Console.WriteLine($" Content size in media units: {DCIH_ID_BackupHeader.ContentSizeInMediaUnits}"); + Console.WriteLine($" Partition ID: {DCIH_ID_BackupHeader.PartitionId}"); + Console.WriteLine($" Maker code: {DCIH_ID_BackupHeader.MakerCode}"); + Console.WriteLine($" Version: {DCIH_ID_BackupHeader.Version}"); + Console.WriteLine($" Verification hash: {DCIH_ID_BackupHeader.VerificationHash}"); + Console.WriteLine($" Program ID: {BitConverter.ToString(DCIH_ID_BackupHeader.ProgramId).Replace('-', ' ')}"); + Console.WriteLine($" Reserved 1: {BitConverter.ToString(DCIH_ID_BackupHeader.Reserved1).Replace('-', ' ')}"); + Console.WriteLine($" Logo region SHA-256 hash: {BitConverter.ToString(DCIH_ID_BackupHeader.LogoRegionHash).Replace('-', ' ')}"); + Console.WriteLine($" Product code: {DCIH_ID_BackupHeader.ProductCode}"); + Console.WriteLine($" Extended header SHA-256 hash: {BitConverter.ToString(DCIH_ID_BackupHeader.ExtendedHeaderHash).Replace('-', ' ')}"); + Console.WriteLine($" Extended header size in bytes: {DCIH_ID_BackupHeader.ExtendedHeaderSizeInBytes}"); + Console.WriteLine($" Reserved 2: {BitConverter.ToString(DCIH_ID_BackupHeader.Reserved2).Replace('-', ' ')}"); + Console.WriteLine($" Flags: {DCIH_ID_BackupHeader.Flags}"); + Console.WriteLine($" Plain region offset, in media units: {DCIH_ID_BackupHeader.PlainRegionOffsetInMediaUnits}"); + Console.WriteLine($" Plain region size, in media units: {DCIH_ID_BackupHeader.PlainRegionSizeInMediaUnits}"); + Console.WriteLine($" Logo region offset, in media units: {DCIH_ID_BackupHeader.LogoRegionOffsetInMediaUnits}"); + Console.WriteLine($" Logo region size, in media units: {DCIH_ID_BackupHeader.LogoRegionSizeInMediaUnits}"); + Console.WriteLine($" ExeFS offset, in media units: {DCIH_ID_BackupHeader.ExeFSOffsetInMediaUnits}"); + Console.WriteLine($" ExeFS size, in media units: {DCIH_ID_BackupHeader.ExeFSSizeInMediaUnits}"); + Console.WriteLine($" ExeFS hash region size, in media units: {DCIH_ID_BackupHeader.ExeFSHashRegionSizeInMediaUnits}"); + Console.WriteLine($" Reserved 3: {BitConverter.ToString(DCIH_ID_BackupHeader.Reserved3).Replace('-', ' ')}"); + Console.WriteLine($" RomFS offset, in media units: {DCIH_ID_BackupHeader.RomFSOffsetInMediaUnits}"); + Console.WriteLine($" RomFS size, in media units: {DCIH_ID_BackupHeader.RomFSSizeInMediaUnits}"); + Console.WriteLine($" RomFS hash region size, in media units: {DCIH_ID_BackupHeader.RomFSHashRegionSizeInMediaUnits}"); + Console.WriteLine($" Reserved 4: {BitConverter.ToString(DCIH_ID_BackupHeader.Reserved4).Replace('-', ' ')}"); + Console.WriteLine($" ExeFS superblock SHA-256 hash: {BitConverter.ToString(DCIH_ID_BackupHeader.ExeFSSuperblockHash).Replace('-', ' ')}"); + Console.WriteLine($" RomFS superblock SHA-256 hash: {BitConverter.ToString(DCIH_ID_BackupHeader.RomFSSuperblockHash).Replace('-', ' ')}"); + // TODO: Print Backup Header? Console.WriteLine(); @@ -413,35 +446,54 @@ namespace BurnOutSharp.Wrappers { var partitionHeader = Partitions[i]; Console.WriteLine($" NCCH Partition Header {i}"); - Console.WriteLine($" RSA-2048 SHA-256 signature: {BitConverter.ToString(partitionHeader.RSA2048Signature).Replace('-', ' ')}"); - Console.WriteLine($" Magic ID: {partitionHeader.MagicID}"); - Console.WriteLine($" Content size in media units: {partitionHeader.ContentSizeInMediaUnits}"); - Console.WriteLine($" Partition ID: {partitionHeader.PartitionId}"); - Console.WriteLine($" Maker code: {partitionHeader.MakerCode}"); - Console.WriteLine($" Version: {partitionHeader.Version}"); - Console.WriteLine($" Verification hash: {partitionHeader.VerificationHash}"); - Console.WriteLine($" Program ID: {BitConverter.ToString(partitionHeader.ProgramId).Replace('-', ' ')}"); - Console.WriteLine($" Reserved 1: {BitConverter.ToString(partitionHeader.Reserved1).Replace('-', ' ')}"); - Console.WriteLine($" Logo region SHA-256 hash: {BitConverter.ToString(partitionHeader.LogoRegionHash).Replace('-', ' ')}"); - Console.WriteLine($" Product code: {BitConverter.ToString(partitionHeader.ProductCode).Replace('-', ' ')}"); - Console.WriteLine($" Extended header SHA-256 hash: {BitConverter.ToString(partitionHeader.ExtendedHeaderHash).Replace('-', ' ')}"); - Console.WriteLine($" Extended header size in bytes: {partitionHeader.ExtendedHeaderSizeInBytes}"); - Console.WriteLine($" Reserved 2: {BitConverter.ToString(partitionHeader.Reserved2).Replace('-', ' ')}"); - Console.WriteLine($" Flags: {partitionHeader.Flags}"); - Console.WriteLine($" Plain region offset, in media units: {partitionHeader.PlainRegionOffsetInMediaUnits}"); - Console.WriteLine($" Plain region size, in media units: {partitionHeader.PlainRegionSizeInMediaUnits}"); - Console.WriteLine($" Logo region offset, in media units: {partitionHeader.LogoRegionOffsetInMediaUnits}"); - Console.WriteLine($" Logo region size, in media units: {partitionHeader.LogoRegionSizeInMediaUnits}"); - Console.WriteLine($" ExeFS offset, in media units: {partitionHeader.ExeFSOffsetInMediaUnits}"); - Console.WriteLine($" ExeFS size, in media units: {partitionHeader.ExeFSSizeInMediaUnits}"); - Console.WriteLine($" ExeFS hash region size, in media units: {partitionHeader.ExeFSHashRegionSizeInMediaUnits}"); - Console.WriteLine($" Reserved 3: {BitConverter.ToString(partitionHeader.Reserved3).Replace('-', ' ')}"); - Console.WriteLine($" RomFS offset, in media units: {partitionHeader.RomFSOffsetInMediaUnits}"); - Console.WriteLine($" RomFS size, in media units: {partitionHeader.RomFSSizeInMediaUnits}"); - Console.WriteLine($" RomFS hash region size, in media units: {partitionHeader.RomFSHashRegionSizeInMediaUnits}"); - Console.WriteLine($" Reserved 4: {BitConverter.ToString(partitionHeader.Reserved4).Replace('-', ' ')}"); - Console.WriteLine($" ExeFS superblock SHA-256 hash: {BitConverter.ToString(partitionHeader.ExeFSSuperblockHash).Replace('-', ' ')}"); - Console.WriteLine($" RomFS superblock SHA-256 hash: {BitConverter.ToString(partitionHeader.RomFSSuperblockHash).Replace('-', ' ')}"); + if (partitionHeader.MagicID == string.Empty) + { + Console.WriteLine($" Empty partition, no data can be parsed"); + } + else if (partitionHeader.MagicID != Models.N3DS.Constants.NCCHMagicNumber) + { + Console.WriteLine($" Unrecognized partition data, no data can be parsed"); + } + else + { + Console.WriteLine($" RSA-2048 SHA-256 signature: {BitConverter.ToString(partitionHeader.RSA2048Signature).Replace('-', ' ')}"); + Console.WriteLine($" Magic ID: {partitionHeader.MagicID}"); + Console.WriteLine($" Content size in media units: {partitionHeader.ContentSizeInMediaUnits}"); + Console.WriteLine($" Partition ID: {partitionHeader.PartitionId}"); + Console.WriteLine($" Maker code: {partitionHeader.MakerCode}"); + Console.WriteLine($" Version: {partitionHeader.Version}"); + Console.WriteLine($" Verification hash: {partitionHeader.VerificationHash}"); + Console.WriteLine($" Program ID: {BitConverter.ToString(partitionHeader.ProgramId).Replace('-', ' ')}"); + Console.WriteLine($" Reserved 1: {BitConverter.ToString(partitionHeader.Reserved1).Replace('-', ' ')}"); + Console.WriteLine($" Logo region SHA-256 hash: {BitConverter.ToString(partitionHeader.LogoRegionHash).Replace('-', ' ')}"); + Console.WriteLine($" Product code: {partitionHeader.ProductCode}"); + Console.WriteLine($" Extended header SHA-256 hash: {BitConverter.ToString(partitionHeader.ExtendedHeaderHash).Replace('-', ' ')}"); + Console.WriteLine($" Extended header size in bytes: {partitionHeader.ExtendedHeaderSizeInBytes}"); + Console.WriteLine($" Reserved 2: {BitConverter.ToString(partitionHeader.Reserved2).Replace('-', ' ')}"); + Console.WriteLine(" Flags:"); + Console.WriteLine($" Reserved 0: {partitionHeader.Flags.Reserved0}"); + Console.WriteLine($" Reserved 1: {partitionHeader.Flags.Reserved1}"); + Console.WriteLine($" Reserved 2: {partitionHeader.Flags.Reserved2}"); + Console.WriteLine($" Crypto method: {partitionHeader.Flags.CryptoMethod}"); + Console.WriteLine($" Content platform: {partitionHeader.Flags.ContentPlatform}"); + Console.WriteLine($" Content type: {partitionHeader.Flags.MediaPlatformIndex}"); + Console.WriteLine($" Content unit size: {partitionHeader.Flags.ContentUnitSize}"); + Console.WriteLine($" Bitmasks: {partitionHeader.Flags.BitMasks}"); + Console.WriteLine($" Plain region offset, in media units: {partitionHeader.PlainRegionOffsetInMediaUnits}"); + Console.WriteLine($" Plain region size, in media units: {partitionHeader.PlainRegionSizeInMediaUnits}"); + Console.WriteLine($" Logo region offset, in media units: {partitionHeader.LogoRegionOffsetInMediaUnits}"); + Console.WriteLine($" Logo region size, in media units: {partitionHeader.LogoRegionSizeInMediaUnits}"); + Console.WriteLine($" ExeFS offset, in media units: {partitionHeader.ExeFSOffsetInMediaUnits}"); + Console.WriteLine($" ExeFS size, in media units: {partitionHeader.ExeFSSizeInMediaUnits}"); + Console.WriteLine($" ExeFS hash region size, in media units: {partitionHeader.ExeFSHashRegionSizeInMediaUnits}"); + Console.WriteLine($" Reserved 3: {BitConverter.ToString(partitionHeader.Reserved3).Replace('-', ' ')}"); + Console.WriteLine($" RomFS offset, in media units: {partitionHeader.RomFSOffsetInMediaUnits}"); + Console.WriteLine($" RomFS size, in media units: {partitionHeader.RomFSSizeInMediaUnits}"); + Console.WriteLine($" RomFS hash region size, in media units: {partitionHeader.RomFSHashRegionSizeInMediaUnits}"); + Console.WriteLine($" Reserved 4: {BitConverter.ToString(partitionHeader.Reserved4).Replace('-', ' ')}"); + Console.WriteLine($" ExeFS superblock SHA-256 hash: {BitConverter.ToString(partitionHeader.ExeFSSuperblockHash).Replace('-', ' ')}"); + Console.WriteLine($" RomFS superblock SHA-256 hash: {BitConverter.ToString(partitionHeader.RomFSSuperblockHash).Replace('-', ' ')}"); + } } } Console.WriteLine();