private static bool GetAsciiKey(NANDReader reader, int offset, out string key) { Debug.SendDebug("Grabbing ASCII Key @ 0x{0:X}", offset); key = null; reader.Lba = (uint)(offset / 0x4000); if (offset % 0x4000 > 0) { reader.Seek(offset % 0x4000, SeekOrigin.Current); } //reader.Seek(offset, SeekOrigin.Begin); var tmp = reader.ReadBytes(0x10); try { key = Encoding.ASCII.GetString(tmp); try { CpukeyUtils.VerifyCpuKey(key); return(true); } catch (X360UtilsException ex) { Debug.SendDebug(ex.ToString()); return(false); } } catch { return(false); } }
public byte[] GetSmcConfig(NANDReader reader) { if (reader.RawLength == 0x1080000) // 16MB NAND { reader.Lba = 0xF7C000 / 0x4000; } else if (!reader.HasSpare) // MMC NAND { reader.Seek(0x2FFC000, SeekOrigin.Begin); } else // BigBlock NAND { reader.Lba = 0x3BE0000 / 0x4000; } var data = reader.ReadBytes(0x400); try { var cfg = new SmcConfig(); cfg.VerifySMCConfigChecksum(data); } catch (X360UtilsException ex) { if (ex.ErrorCode == X360UtilsException.X360UtilsErrors.BadChecksum) { throw new X360UtilsException(X360UtilsException.X360UtilsErrors.DataNotFound); } throw; } return(data); }
public string GetNandCpuKey(NANDReader reader) { byte[] key; if (!GetByteKey(reader, 0x100, out key)) // Blakcat XeLL { if (!GetByteKey(reader, 0x6d0, out key)) // Blakcat Freeboot storage (Spare type offset) { if (!GetByteKey(reader, 0x700, out key)) // Blakcat Freeboot storage (MMC type offset) { if (!GetByteKey(reader, 0x600, out key)) // xeBuild GUI Offset { if (!GetByteKey(reader, 0x95020, out key)) // Virtual Fuses { string keys; if (!GetAsciiKey(reader, 0x600, out keys)) // xeBuild GUI ASCII Method { throw new X360UtilsException(X360UtilsException.X360UtilsErrors.DataNotFound); } return(keys); } } } } } return(StringUtils.ArrayToHex(key)); }
public string GetVirtualFuses(NANDReader reader) { reader.Lba = 0x95000 / 0x4000; reader.Seek(0x95000 % 0x4000, SeekOrigin.Current); //reader.Seek(0x95000, SeekOrigin.Begin); var data = reader.ReadBytes(0x60); var tmp = new byte[] { 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xF0 }; if (!BitOperations.CompareByteArrays(ref data, ref tmp, false)) { throw new X360UtilsException(X360UtilsException.X360UtilsErrors.DataInvalid); } var ret = new StringBuilder(); for (var index = 0; index < data.Length; index++) { if (index % 0x8 == 0 || index == 0) { ret.AppendFormat("\nfuseset {0:D2}: ", index / 0x5); } ret.Append(data[index].ToString("X2")); } return(ret.ToString().Trim()); }
public FileSystemEntry[] ParseFileSystem(ref NANDReader reader, FsRootEntry fsRoot) { var ret = new List <FileSystemEntry>(); reader.Seek(fsRoot.Offset, SeekOrigin.Begin); var bitmap = new byte[0x2000]; var fsinfo = new byte[0x2000]; for (var i = 0; i < bitmap.Length / 0x200; i++) { var buf = reader.ReadBytes(0x200); Buffer.BlockCopy(buf, 0, bitmap, i * 0x200, buf.Length); buf = reader.ReadBytes(0x200); Buffer.BlockCopy(buf, 0, fsinfo, i * 0x200, buf.Length); } if (reader.MetaType == NANDSpare.MetaType.MetaType0 || reader.MetaType == NANDSpare.MetaType.MetaType1 || reader.MetaType == NANDSpare.MetaType.MetaType2 || reader.MetaType == NANDSpare.MetaType.MetaTypeNone) { for (var i = 0; i < fsinfo.Length / 0x20; i++) { var blocks = new List <long>(); var name = Encoding.ASCII.GetString(fsinfo, i * 0x20, 0x16); var start = BitOperations.Swap(BitConverter.ToUInt16(fsinfo, i * 0x20 + 0x16)); var size = BitOperations.Swap(BitConverter.ToUInt32(fsinfo, i * 0x20 + 0x18)); var timestamp = BitOperations.Swap(BitConverter.ToUInt32(fsinfo, i * 0x20 + 0x1C)); blocks.Add(start); // Always add the first block! while (true) { start = BitOperations.Swap(BitConverter.ToUInt16(bitmap, start * 2)); //if(start == 0x1FFF || start == 0x1FFE) if (start * 2 > bitmap.Length + 2) { break; } blocks.Add(start); } if (name.StartsWith("\0") || name.StartsWith("\x5")) { continue; // Ignore empty and/or deleted entries } if (blocks.Count > 0) { if (blocks[0] == 0 || size == 0) // ignore entries with no offset / size { continue; } } ret.Add(new FileSystemEntry(name.Substring(0, name.IndexOf('\0')), size, timestamp, blocks.ToArray())); } } else { throw new NotSupportedException(); } return(ret.ToArray()); }
private static long GetBaseBlockForMeta2(ref NANDReader reader) { reader.RawSeek(reader.FsRoot.Offset / 0x200 * 0x210 + 0x200, SeekOrigin.Begin); var meta = NANDSpare.GetMetaData(reader.RawReadBytes(0x10)); var reserved = 0x1E0; reserved -= meta.Meta2.FsPageCount; reserved -= meta.Meta2.FsSize0 << 2; return(reserved * 8); }
public byte[] GetKeyVault(NANDReader reader, byte[] cpukey) { var kv = GetKeyVault(reader); _crypto.DecryptKv(ref kv, cpukey); if (_crypto.VerifyKvDecrypted(ref kv, cpukey)) { return(kv); } throw new X360UtilsException(X360UtilsException.X360UtilsErrors.DataDecryptionFailed); }
public byte[] GetData(ref NANDReader reader) { var ret = new List <byte>(); var left = (int)Size; var baseBlock = reader.MetaType != NANDSpare.MetaType.MetaType2 ? 0 : GetBaseBlockForMeta2(ref reader); foreach (var offset in Blocks) { reader.Lba = (ushort)(baseBlock + offset); ret.AddRange(reader.ReadBytes(BitOperations.GetSmallest(left, 0x4000))); left -= BitOperations.GetSmallest(left, 0x4000); } return(ret.ToArray()); }
public void ExtractToFile(ref NANDReader reader, string filename) { using (var writer = new BinaryWriter(File.OpenWrite(filename))) { var left = (int)Size; var baseBlock = reader.MetaType != NANDSpare.MetaType.MetaType2 ? 0 : GetBaseBlockForMeta2(ref reader); foreach (var offset in Blocks) { reader.Lba = (ushort)(baseBlock + offset); writer.Write(reader.ReadBytes(BitOperations.GetSmallest(left, 0x4000))); left -= BitOperations.GetSmallest(left, 0x4000); } } File.SetCreationTime(filename, DateTime); File.SetLastAccessTime(filename, DateTime); File.SetLastWriteTime(filename, DateTime); }
public Bootloader(NANDReader reader, int count = 0, bool readitin = false) { Offset = (uint)(reader.Lba * 0x4000 + reader.Position % 0x4000); StartLba = reader.Lba; var header = reader.ReadBytes(0x10); Type = GetTypeFromHeader(ref header, count); Size = GetBootloaderSize(ref header); Build = GetBootloaderVersion(ref header); if (readitin) { reader.Lba = Offset / 0x4000; if (Offset % 0x4000 > 0) { reader.Seek(Offset % 0x4000, SeekOrigin.Current); } Data = new byte[Size]; var left = Size; var dOffset = 0; for (var i = 0; left > 0; i++) { var toread = (int)BitOperations.GetSmallest(0x4000, left); if (left == Size && reader.Position % 0x4000 > 0) { toread = (int)BitOperations.GetSmallest((0x4000 - (reader.Position % 0x4000)), left); } var tmp = reader.ReadBytes(toread); Buffer.BlockCopy(tmp, 0, Data, dOffset, toread); left -= (uint)toread; dOffset += toread; if (left > 0) // We want to seek to the next block! { reader.Lba = (uint)((Offset / 0x4000) + 1 + i); } } } else { reader.Lba = (Offset + Size) / 0x4000; if ((Offset + Size) % 0x4000 > 0) { reader.Seek((Offset + Size) % 0x4000, SeekOrigin.Current); } } //reader.Seek(Offset + Size, SeekOrigin.Begin); }
public byte[] GetKeyVault(NANDReader reader, bool decryptWithKeyInNand = false) { reader.Lba = 1; // Seek to the KV Block //reader.Seek(0x4000, SeekOrigin.Begin); if (!decryptWithKeyInNand) { return(reader.ReadBytes(0x4000)); } var kv = GetKeyVault(reader); var cpukey = GetNandCpuKey(reader); _crypto.DecryptKv(ref kv, cpukey); if (_crypto.VerifyKvDecrypted(ref kv, cpukey)) { return(kv); } throw new X360UtilsException(X360UtilsException.X360UtilsErrors.DataDecryptionFailed); }
public string GetLaunchIni(NANDReader reader) { if (reader.FsRoot == null) { reader.ScanForFsRootAndMobiles(); } var nandfs = new NANDFileSystem(); var fs = nandfs.ParseFileSystem(ref reader); foreach (var fileSystemEntry in fs) { if (fileSystemEntry.Filename.Equals("launch.ini", StringComparison.CurrentCultureIgnoreCase)) { return(Encoding.ASCII.GetString(fileSystemEntry.GetData(ref reader))); } } throw new X360UtilsException(X360UtilsException.X360UtilsErrors.DataNotFound, "Launch.ini"); }
public byte[] GetFcrt(NANDReader reader) { if (reader.FsRoot == null) { reader.ScanForFsRootAndMobiles(); } var nandfs = new NANDFileSystem(); var fs = nandfs.ParseFileSystem(ref reader); foreach (var fileSystemEntry in fs) { if (fileSystemEntry.Filename.Equals("fcrt.bin", StringComparison.CurrentCultureIgnoreCase)) { return(fileSystemEntry.GetData(ref reader)); } } throw new X360UtilsException(X360UtilsException.X360UtilsErrors.DataNotFound, "FCRT"); }
private static bool GetByteKey(NANDReader reader, int offset, out byte[] key) { Debug.SendDebug("Grabbing Byte Key @ 0x{0:X}", offset); reader.Lba = (uint)(offset / 0x4000); if (offset % 0x4000 > 0) { reader.Seek(offset % 0x4000, SeekOrigin.Current); } //reader.Seek(offset, SeekOrigin.Begin); key = reader.ReadBytes(0x10); try { CpukeyUtils.VerifyCpuKey(ref key); return(true); } catch (X360UtilsException ex) { Debug.SendDebug(ex.ToString()); return(false); } }
public static void TestMetaUtils(string file) { var reader = new NANDReader(file); var metaType = reader.MetaType; for (long i = 0; i < reader.RawLength; i += 0x4200) { Debug.SendDebug("Seeking to page 0 of block 0x{0:X}", i / 0x4200); reader.RawSeek(i + 0x200, SeekOrigin.Begin); var meta = GetMetaData(reader.RawReadBytes(0x10)); Main.SendInfo("Block 0x{0:X} Page 0 Information:\r\n", i / 0x4200); Main.SendInfo("LBA: 0x{0:X}\r\n", GetLba(ref meta)); Main.SendInfo("Block Type: 0x{0:X}\r\n", GetBlockType(ref meta)); Main.SendInfo("FSSize: 0x{0:X}\r\n", GetFsSize(ref meta)); Main.SendInfo("FsFreePages: 0x{0:X}\r\n", GetFsFreePages(ref meta)); Main.SendInfo("FsSequence: 0x{0:X}\r\n", GetFsSequence(ref meta)); Main.SendInfo("BadBlock Marker: 0x{0:X}\r\n", GetBadBlockMarker(ref meta)); } }
public byte[] GetSmc(NANDReader reader, bool decrypted = false) { reader.Seek(0x78, SeekOrigin.Begin); var tmp = reader.ReadBytes(4); var size = BitOperations.Swap(BitConverter.ToUInt32(tmp, 0)); reader.Seek(0x7C, SeekOrigin.Begin); tmp = reader.ReadBytes(4); reader.Seek(BitOperations.Swap(BitConverter.ToUInt32(tmp, 0)), SeekOrigin.Begin); if (!decrypted) { return(reader.ReadBytes((int)size)); } tmp = reader.ReadBytes((int)size); _crypto.DecryptSmc(ref tmp); if (!Cryptography.VerifySmcDecrypted(ref tmp)) { throw new X360UtilsException(X360UtilsException.X360UtilsErrors.DataDecryptionFailed); } return(tmp); }
public Bootloader[] GetBootLoaders(NANDReader reader, bool readToMemory = false) { var bls = new List <Bootloader>(); //reader.Seek(0x8000, SeekOrigin.Begin); reader.Lba = 2; // Seek to offset 0x8000, where the start of the bootloaders bls.Add(new Bootloader(reader, readitin: readToMemory)); try { for (var i = 1; i < 4; i++) { bls.Add(new Bootloader(reader, i, readToMemory)); } } catch (X360UtilsException ex) { if (ex.ErrorCode != X360UtilsException.X360UtilsErrors.DataInvalid) { throw; } } try { reader.Seek(0x70, SeekOrigin.Begin); var size = BitOperations.Swap(BitConverter.ToUInt32(reader.ReadBytes(4), 0)); reader.Seek(0x64, SeekOrigin.Begin); var offset = BitOperations.Swap(BitConverter.ToUInt32(reader.ReadBytes(4), 0)); reader.Lba = offset / 0x4000; if (offset % 0x4000 > 0) { reader.Seek(offset % 0x4000, SeekOrigin.Current); } //reader.Seek(offset, SeekOrigin.Begin); bls.Add(new Bootloader(reader, readitin: readToMemory)); bls.Add(new Bootloader(reader, readitin: readToMemory)); try { if (size == 0) { reader.Lba = (offset + 0x10000) / 0x4000; if ((offset + 0x10000) % 0x4000 > 0) { reader.Seek((offset + 0x10000) % 0x4000, SeekOrigin.Current); } //reader.Seek(offset + 0x10000, SeekOrigin.Begin); bls.Add(new Bootloader(reader, readitin: readToMemory)); bls.Add(new Bootloader(reader, readitin: readToMemory)); } } catch (X360UtilsException ex) { if (ex.ErrorCode != X360UtilsException.X360UtilsErrors.DataInvalid) { throw; } if (size == 0) { reader.Lba = (offset + 0x20000) / 0x4000; if ((offset + 0x20000) % 0x4000 > 0) { reader.Seek((offset + 0x20000) % 0x4000, SeekOrigin.Current); } //reader.Seek(offset + 0x20000, SeekOrigin.Begin); bls.Add(new Bootloader(reader, readitin: readToMemory)); bls.Add(new Bootloader(reader, readitin: readToMemory)); } } } catch (X360UtilsException ex) { if (ex.ErrorCode != X360UtilsException.X360UtilsErrors.DataInvalid) { throw; } } return(bls.ToArray()); }
public FileSystemEntry[] ParseFileSystem(ref NANDReader reader) { return(ParseFileSystem(ref reader, reader.FsRoot)); }
internal static MetaType DetectSpareType(NANDReader reader, bool firsttry = true) { if (!reader.HasSpare) { return(MetaType.MetaTypeNone); } if (firsttry) { reader.RawSeek(0x4400, SeekOrigin.Begin); } else { reader.RawSeek(reader.RawLength - 0x4000, SeekOrigin.Begin); } var tmp = reader.RawReadBytes(0x10); var mdata = GetMetaData(tmp); if (!CheckIsBadBlockSpare(ref tmp, MetaType.MetaType0)) { if (GetLbaRaw0(ref mdata) == 1) { return(MetaType.MetaType0); } if (GetLbaRaw1(ref mdata) == 1) { return(MetaType.MetaType1); } } if (!CheckIsBadBlockSpare(ref tmp, MetaType.MetaType2)) { if (firsttry) { reader.RawSeek(0x21200, SeekOrigin.Begin); } else if (reader.RawLength <= 0x4200000) { reader.RawSeek(reader.RawLength - 0x4000, SeekOrigin.Begin); } else { reader.RawSeek(0x4200000 - 0x4000, SeekOrigin.Begin); } tmp = reader.RawReadBytes(0x10); if (!CheckIsBadBlockSpare(ref tmp, MetaType.MetaType2)) { if (BlockIdFromSpare(ref tmp, MetaType.MetaType2) == 1) { return(MetaType.MetaType2); } } } else if (Main.VerifyVerbosityLevel(1)) { Main.SendInfo(firsttry ? "\r\nBlock 1 is bad!" : "\r\nThe last system block is bad!"); } if (firsttry) { return(DetectSpareType(reader, false)); } throw new X360UtilsException(X360UtilsException.X360UtilsErrors.UnkownMetaType); }
public byte[] GetData(ref NANDReader reader) { reader.Seek(Offset, SeekOrigin.Begin); return(reader.ReadBytes(Size)); }
public byte[] GetBlock(ref NANDReader reader) { reader.Seek(Offset, SeekOrigin.Begin); return(reader.ReadBytes(0x4000)); }