private int PrivPatchFakeSigning(ref byte[] esModule) { FireDebug("Patching Fakesigning..."); int num = 0; byte[] second1 = new byte[4] { 32, 7, 35, 162 }; byte[] second2 = new byte[4] { 32, 7, 75, 11 }; for (int firstIndex = 0; firstIndex < esModule.Length - 4; ++firstIndex) { FireProgress((firstIndex + 1) * 100 / esModule.Length); if (Shared.CompareByteArrays(esModule, firstIndex, second1, 0, 4) || Shared.CompareByteArrays(esModule, firstIndex, second2, 0, 4)) { FireDebug(" Patching at Offset: 0x{0}", (object)firstIndex.ToString("x8").ToUpper()); esModule[firstIndex + 1] = 0; firstIndex += 4; ++num; } } FireDebug("Patching Fakesigning Finished... (Patches applied: {0})", (object)num); return(num); }
private int PrivPatchEsIdentify(ref byte[] esModule) { FireDebug("Patching ES_Identify..."); int num = 0; byte[] second = new byte[4] { 40, 3, 209, 35 }; for (int firstIndex = 0; firstIndex < esModule.Length - 4; ++firstIndex) { FireProgress((firstIndex + 1) * 100 / esModule.Length); if (Shared.CompareByteArrays(esModule, firstIndex, second, 0, 4)) { FireDebug(" Patching at Offset: 0x{0}", (object)firstIndex.ToString("x8").ToUpper()); esModule[firstIndex + 2] = 0; esModule[firstIndex + 3] = 0; firstIndex += 4; ++num; } } FireDebug("Patching ES_Identify Finished... (Patches applied: {0})", (object)num); return(num); }
private int patchFakeSigning(ref byte[] esModule) { fireDebug("Patching Fakesigning..."); int patchCount = 0; byte[] oldHashCheck = { 0x20, 0x07, 0x23, 0xA2 }; byte[] newHashCheck = { 0x20, 0x07, 0x4B, 0x0B }; for (int i = 0; i < esModule.Length - 4; i++) { fireProgress((i + 1) * 100 / esModule.Length); if (Shared.CompareByteArrays(esModule, i, oldHashCheck, 0, 4) || Shared.CompareByteArrays(esModule, i, newHashCheck, 0, 4)) { fireDebug(" Patching at Offset: 0x{0}", i.ToString("x8").ToUpper()); esModule[i + 1] = 0x00; i += 4; patchCount++; } } fireDebug("Patching Fakesigning Finished... (Patches applied: {0})", patchCount); return(patchCount); }
private int PrivPatchVP(ref byte[] esModule) { FireDebug("Patching VP..."); int num = 0; byte[] second = new byte[4] { 210, 1, 78, 86 }; for (int firstIndex = 0; firstIndex < esModule.Length - 4; ++firstIndex) { FireProgress((firstIndex + 1) * 100 / esModule.Length); if (Shared.CompareByteArrays(esModule, firstIndex, second, 0, 4)) { FireDebug(" Patching for VP at Offset: 0x{0}", (object)firstIndex.ToString("x8").ToUpper()); esModule[firstIndex] = 224; firstIndex += 4; ++num; } } FireDebug("Patching VP Finished... (Patches applied: {0})", (object)num); return(num); }
private int PrivPatchNandPermissions(ref byte[] esModule) { FireDebug("Patching NAND Permissions..."); int num = 0; byte[] second = new byte[6] { 66, 139, 208, 1, 37, 102 }; for (int firstIndex = 0; firstIndex < esModule.Length - 6; ++firstIndex) { FireProgress((firstIndex + 1) * 100 / esModule.Length); if (Shared.CompareByteArrays(esModule, firstIndex, second, 0, 6)) { FireDebug(" Patching at Offset: 0x{0}", (object)firstIndex.ToString("x8").ToUpper()); esModule[firstIndex + 2] = 224; firstIndex += 6; ++num; } } FireDebug("Patching NAND Permissions Finished... (Patches applied: {0})", (object)num); return(num); }
public void Read(Stream input) { BinaryReader reader = new BinaryReader(input); if (!Shared.CompareByteArrays(magic, reader.ReadBytes(4))) { throw new Exception("This is not a valid BNS audfo file!"); } size = Shared.Swap(reader.ReadUInt32()); data = reader.ReadBytes((int)size - 8); }
private bool IsCertCp(byte[] part) { if (part.Length < 768) { return(false); } if (part.Length > 768) { Array.Resize <byte>(ref part, 768); } return(part[388] == 67 && part[389] == 80 && Shared.CompareByteArrays(sha.ComputeHash(part), Shared.HexStringToByteArray("6824D6DA4C25184F0D6DAF6EDB9C0FC57522A41C"))); }
private bool IsCertCa(byte[] part) { if (part.Length < 1024) { return(false); } if (part.Length > 1024) { Array.Resize <byte>(ref part, 1024); } return(part[644] == 67 && part[645] == 65 && Shared.CompareByteArrays(sha.ComputeHash(part), Shared.HexStringToByteArray("5B7D3EE28706AD8DA2CBD5A6B75C15D0F9B6F318"))); }
private bool IsCertXs(byte[] part) { if (part.Length < 768) { return(false); } if (part.Length > 768) { Array.Resize <byte>(ref part, 768); } return(part[388] == 88 && part[389] == 83 && Shared.CompareByteArrays(sha.ComputeHash(part), Shared.HexStringToByteArray("09787045037121477824BC6A3E5E076156573F8A"))); }
private int patchAll(ref byte[] esModule) { fireDebug("Patching Fakesigning, ES_Identify and NAND Permissions..."); int patchCount = 0; byte[] oldHashCheck = { 0x20, 0x07, 0x23, 0xA2 }; byte[] newHashCheck = { 0x20, 0x07, 0x4B, 0x0B }; byte[] identifyCheck = { 0x28, 0x03, 0xD1, 0x23 }; byte[] permissionTable = { 0x42, 0x8B, 0xD0, 0x01, 0x25, 0x66 }; for (int i = 0; i < esModule.Length - 6; i++) { fireProgress((i + 1) * 100 / esModule.Length); if (Shared.CompareByteArrays(esModule, i, oldHashCheck, 0, 4) || Shared.CompareByteArrays(esModule, i, newHashCheck, 0, 4)) { fireDebug(" Patching Fakesigning at Offset: 0x{0}", i.ToString("x8").ToUpper()); esModule[i + 1] = 0x00; i += 4; patchCount++; } else if (Shared.CompareByteArrays(esModule, i, identifyCheck, 0, 4)) { fireDebug(" Patching ES_Identify at Offset: 0x{0}", i.ToString("x8").ToUpper()); esModule[i + 2] = 0x00; esModule[i + 3] = 0x00; i += 4; patchCount++; } else if (Shared.CompareByteArrays(esModule, i, permissionTable, 0, 6)) { fireDebug(" Patching NAND Permissions at Offset: 0x{0}", i.ToString("x8").ToUpper()); esModule[i + 2] = 0xE0; i += 6; patchCount++; } } fireDebug("Patching Fakesigning, ES_Identify and NAND Permissions Finished... (Patches applied: {0})", patchCount); return(patchCount); }
public void Read(Stream input) { BinaryReader reader = new BinaryReader(input); if (!Shared.CompareByteArrays(magic, reader.ReadBytes(4))) { reader.BaseStream.Seek(28, SeekOrigin.Current); if (!Shared.CompareByteArrays(magic, reader.ReadBytes(4))) { throw new Exception("This is not a valid BNS audfo file!"); } } flags = Shared.Swap(reader.ReadUInt32()); fileSize = Shared.Swap(reader.ReadUInt32()); size = Shared.Swap(reader.ReadUInt16()); chunkCount = Shared.Swap(reader.ReadUInt16()); infoOffset = Shared.Swap(reader.ReadUInt32()); infoLength = Shared.Swap(reader.ReadUInt32()); dataOffset = Shared.Swap(reader.ReadUInt32()); dataLength = Shared.Swap(reader.ReadUInt32()); }
private int patchNandPermissions(ref byte[] esModule) { fireDebug("Patching NAND Permissions..."); int patchCount = 0; byte[] permissionTable = { 0x42, 0x8B, 0xD0, 0x01, 0x25, 0x66 }; for (int i = 0; i < esModule.Length - 6; i++) { fireProgress((i + 1) * 100 / esModule.Length); if (Shared.CompareByteArrays(esModule, i, permissionTable, 0, 6)) { fireDebug(" Patching at Offset: 0x{0}", i.ToString("x8").ToUpper()); esModule[i + 2] = 0xE0; i += 6; patchCount++; } } fireDebug("Patching NAND Permissions Finished... (Patches applied: {0})", patchCount); return(patchCount); }
private int patchEsIdentify(ref byte[] esModule) { fireDebug("Patching ES_Identify..."); int patchCount = 0; byte[] identifyCheck = { 0x28, 0x03, 0xD1, 0x23 }; for (int i = 0; i < esModule.Length - 4; i++) { fireProgress((i + 1) * 100 / esModule.Length); if (Shared.CompareByteArrays(esModule, i, identifyCheck, 0, 4)) { fireDebug(" Patching at Offset: 0x{0}", i.ToString("x8").ToUpper()); esModule[i + 2] = 0x00; esModule[i + 3] = 0x00; i += 4; patchCount++; } } fireDebug("Patching ES_Identify Finished... (Patches applied: {0})", patchCount); return(patchCount); }
private bool isCertCp(byte[] part) { if (part.Length < 0x300) { return(false); } else if (part.Length > 0x300) { Array.Resize(ref part, 0x300); } if (part[0x184] == 'C' && part[0x185] == 'P') { byte[] newHash = sha.ComputeHash(part); byte[] oldHash = Shared.HexStringToByteArray(certCpHash); if (Shared.CompareByteArrays(newHash, oldHash)) { return(true); } } return(false); }
private void downloadTitle(string titleId, string titleVersion, string outputDir, StoreType[] storeTypes) { fireDebug("Downloading Title {0} v{1}...", titleId, (string.IsNullOrEmpty(titleVersion)) ? "[Latest]" : titleVersion); if (storeTypes.Length < 1) { fireDebug(" No store types were defined..."); throw new Exception("You must at least define one store type!"); } string titleUrl = string.Format("{0}{1}/", nusUrl, titleId); bool storeEncrypted = false; bool storeDecrypted = false; bool storeWad = false; fireProgress(0); foreach (StoreType st in storeTypes) { switch (st) { case StoreType.DecryptedContent: fireDebug(" -> Storing Decrypted Content..."); storeDecrypted = true; break; case StoreType.EncryptedContent: fireDebug(" -> Storing Encrypted Content..."); storeEncrypted = true; break; case StoreType.WAD: fireDebug(" -> Storing WAD..."); storeWad = true; break; case StoreType.All: fireDebug(" -> Storing Decrypted Content..."); fireDebug(" -> Storing Encrypted Content..."); fireDebug(" -> Storing WAD..."); storeDecrypted = true; storeEncrypted = true; storeWad = true; break; } } fireDebug(" Checking for Internet connection..."); if (!CheckInet()) { fireDebug(" Connection not found..."); throw new Exception("You're not connected to the internet!"); } if (outputDir[outputDir.Length - 1] != Path.DirectorySeparatorChar) { outputDir += Path.DirectorySeparatorChar; } if (!Directory.Exists(outputDir)) { Directory.CreateDirectory(outputDir); } string tmdFile = "tmd" + (string.IsNullOrEmpty(titleVersion) ? string.Empty : string.Format(".{0}", titleVersion)); //Download TMD fireDebug(" Downloading TMD..."); try { wcNus.DownloadFile(titleUrl + tmdFile, outputDir + tmdFile); } catch (Exception ex) { fireDebug(" Downloading TMD Failed..."); throw new Exception("Downloading TMD Failed:\n" + ex.Message); } fireProgress(5); //Download cetk fireDebug(" Downloading Ticket..."); try { wcNus.DownloadFile(titleUrl + "cetk", outputDir + "cetk"); } catch (Exception ex) { if (!continueWithoutTicket || !storeEncrypted) { fireDebug(" Downloading Ticket Failed..."); throw new Exception("Downloading Ticket Failed:\n" + ex.Message); } storeDecrypted = false; storeWad = false; } fireProgress(10); //Parse TMD and Ticket fireDebug(" Parsing TMD..."); TMD tmd = TMD.Load(outputDir + tmdFile); if (string.IsNullOrEmpty(titleVersion)) { fireDebug(" -> Title Version: {0}", tmd.TitleVersion); } fireDebug(" -> {0} Contents", tmd.NumOfContents); fireDebug(" Parsing Ticket..."); Ticket tik = Ticket.Load(outputDir + "cetk"); string[] encryptedContents = new string[tmd.NumOfContents]; //Download Content for (int i = 0; i < tmd.NumOfContents; i++) { fireDebug(" Downloading Content #{0} of {1}... ({2} bytes)", i + 1, tmd.NumOfContents, tmd.Contents[i].Size); fireProgress(((i + 1) * 60 / tmd.NumOfContents) + 10); if (useLocalFiles && File.Exists(outputDir + tmd.Contents[i].ContentID.ToString("x8"))) { fireDebug(" Using Local File, Skipping..."); continue; } try { wcNus.DownloadFile(titleUrl + tmd.Contents[i].ContentID.ToString("x8"), outputDir + tmd.Contents[i].ContentID.ToString("x8")); encryptedContents[i] = tmd.Contents[i].ContentID.ToString("x8"); } catch (Exception ex) { fireDebug(" Downloading Content #{0} of {1} failed...", i + 1, tmd.NumOfContents); throw new Exception("Downloading Content Failed:\n" + ex.Message); } } //Decrypt Content if (storeDecrypted || storeWad) { SHA1 s = SHA1.Create(); for (int i = 0; i < tmd.NumOfContents; i++) { fireDebug(" Decrypting Content #{0} of {1}...", i + 1, tmd.NumOfContents); fireProgress(((i + 1) * 20 / tmd.NumOfContents) + 75); //Decrypt Content byte[] decryptedContent = decryptContent(File.ReadAllBytes(outputDir + tmd.Contents[i].ContentID.ToString("x8")), i, tik, tmd); Array.Resize(ref decryptedContent, (int)tmd.Contents[i].Size); //Check SHA1 byte[] newSha = s.ComputeHash(decryptedContent); if (!Shared.CompareByteArrays(newSha, tmd.Contents[i].Hash)) { fireDebug(@"/!\ /!\ /!\ Hashes do not match /!\ /!\ /!\"); throw new Exception(string.Format("Content #{0}: Hashes do not match!", i)); } //Write Decrypted Content File.WriteAllBytes(outputDir + tmd.Contents[i].ContentID.ToString("x8") + ".app", decryptedContent); } s.Clear(); } //Pack Wad if (storeWad) { fireDebug(" Building Certificate Chain..."); CertificateChain cert = CertificateChain.FromTikTmd(outputDir + "cetk", outputDir + tmdFile); byte[][] contents = new byte[tmd.NumOfContents][]; for (int i = 0; i < tmd.NumOfContents; i++) { contents[i] = File.ReadAllBytes(outputDir + tmd.Contents[i].ContentID.ToString("x8") + ".app"); } fireDebug(" Creating WAD..."); WAD wad = WAD.Create(cert, tik, tmd, contents); wad.Save(outputDir + tmd.TitleID.ToString("x16") + "v" + tmd.TitleVersion.ToString() + ".wad"); } //Delete not wanted files if (!storeEncrypted) { fireDebug(" Deleting Encrypted Contents..."); for (int i = 0; i < encryptedContents.Length; i++) { if (File.Exists(outputDir + encryptedContents[i])) { File.Delete(outputDir + encryptedContents[i]); } } } if (storeWad && !storeDecrypted) { fireDebug(" Deleting Decrypted Contents..."); for (int i = 0; i < encryptedContents.Length; i++) { if (File.Exists(outputDir + encryptedContents[i] + ".app")) { File.Delete(outputDir + encryptedContents[i] + ".app"); } } } if (!storeDecrypted && !storeEncrypted) { fireDebug(" Deleting TMD and Ticket..."); File.Delete(outputDir + tmdFile); File.Delete(outputDir + "cetk"); } fireDebug("Downloading Title {0} v{1} Finished...", titleId, (string.IsNullOrEmpty(titleVersion)) ? "[Latest]" : titleVersion); fireProgress(100); }
private void downloadTitle(string titleId, string titleVersion, string outputDir, string wadName, StoreType[] storeTypes) { fireDebug("Downloading Title {0} v{1}...", titleId, (string.IsNullOrEmpty(titleVersion)) ? "[Latest]" : titleVersion); if (storeTypes.Length < 1) { fireDebug(" No store types were defined..."); throw new Exception("You must at least define one store type!"); } string titleUrl = string.Format("{0}{1}/", nusUrl, titleId); bool storeEncrypted = false; bool storeDecrypted = false; bool storeWad = false; fireProgress(0); foreach (StoreType st in storeTypes) { switch (st) { case StoreType.DecryptedContent: fireDebug(" [=] Storing Decrypted Content..."); storeDecrypted = true; break; case StoreType.EncryptedContent: fireDebug(" [=] Storing Encrypted Content..."); storeEncrypted = true; break; case StoreType.WAD: fireDebug(" [=] Storing WAD..."); storeWad = true; break; case StoreType.All: fireDebug(" [=] Storing Decrypted Content..."); fireDebug(" [=] Storing Encrypted Content..."); fireDebug(" [=] Storing WAD..."); storeDecrypted = true; storeEncrypted = true; storeWad = true; break; case StoreType.Empty: break; } } /* * fireDebug(" - Checking for Internet connection..."); * if (!CheckInet()) * { fireDebug(" + Connection not found..."); throw new Exception("You're not connected to the internet!"); } */ if (!Directory.Exists(outputDir)) { Directory.CreateDirectory(outputDir); } if (!Directory.Exists(Path.Combine(outputDir, titleId))) { Directory.CreateDirectory(Path.Combine(outputDir, titleId)); } outputDir = Path.Combine(outputDir, titleId); string tmdFile = "tmd" + (string.IsNullOrEmpty(titleVersion) ? string.Empty : string.Format(".{0}", titleVersion)); //Download TMD fireDebug(" - Downloading TMD..."); TMD tmd; byte[] tmdFileWithCerts; try { tmdFileWithCerts = wcNus.DownloadData(titleUrl + tmdFile); tmd = TMD.Load(tmdFileWithCerts); } catch (Exception ex) { fireDebug(" + Downloading TMD Failed..."); throw new Exception("Downloading TMD Failed:\n" + ex.Message); } //Parse TMD fireDebug(" - Parsing TMD..."); if (string.IsNullOrEmpty(titleVersion)) { fireDebug(" + Title Version: {0}", tmd.TitleVersion); } fireDebug(" + {0} Contents", tmd.NumOfContents); if (!Directory.Exists(Path.Combine(outputDir, tmd.TitleVersion.ToString()))) { Directory.CreateDirectory(Path.Combine(outputDir, tmd.TitleVersion.ToString())); } outputDir = Path.Combine(outputDir, tmd.TitleVersion.ToString()); this.titleversion = tmd.TitleVersion; File.WriteAllBytes(Path.Combine(outputDir, tmdFile), tmd.ToByteArray()); fireProgress(5); //Download cetk fireDebug(" - Downloading Ticket..."); try { wcNus.DownloadFile(Path.Combine(titleUrl, "cetk"), Path.Combine(outputDir, "cetk")); } catch (Exception ex) { if (!continueWithoutTicket || !storeEncrypted) { fireDebug(" + Downloading Ticket Failed..."); throw new Exception("Downloading Ticket Failed:\n" + ex.Message); } if (!(File.Exists(Path.Combine(outputDir, "cetk")))) { storeDecrypted = false; storeWad = false; } } fireProgress(10); // Parse Ticket Ticket tik = new Ticket(); if (File.Exists(Path.Combine(outputDir, "cetk"))) { fireDebug(" + Parsing Ticket..."); tik = Ticket.Load(Path.Combine(outputDir, "cetk")); // DSi ticket? Must make sure to use DSi Key :D if (nusUrl == DSI_NUS_URL) { tik.DSiTicket = true; } } else { fireDebug(" + Ticket Unavailable..."); } string[] encryptedContents = new string[tmd.NumOfContents]; //Download Content for (int i = 0; i < tmd.NumOfContents; i++) { fireDebug(" - Downloading Content #{0} of {1}... ({2} bytes)", i + 1, tmd.NumOfContents, tmd.Contents[i].Size); fireProgress(((i + 1) * 60 / tmd.NumOfContents) + 10); if (useLocalFiles && File.Exists(Path.Combine(outputDir, tmd.Contents[i].ContentID.ToString("x8")))) { fireDebug(" + Using Local File, Skipping..."); continue; } try { wcNus.DownloadFile(titleUrl + tmd.Contents[i].ContentID.ToString("x8"), Path.Combine(outputDir, tmd.Contents[i].ContentID.ToString("x8"))); encryptedContents[i] = tmd.Contents[i].ContentID.ToString("x8"); } catch (Exception ex) { fireDebug(" - Downloading Content #{0} of {1} failed...", i + 1, tmd.NumOfContents); throw new Exception("Downloading Content Failed:\n" + ex.Message); } } //Decrypt Content if (storeDecrypted || storeWad) { SHA1 s = SHA1.Create(); for (int i = 0; i < tmd.NumOfContents; i++) { fireDebug(" - Decrypting Content #{0} of {1}...", i + 1, tmd.NumOfContents); fireProgress(((i + 1) * 20 / tmd.NumOfContents) + 75); //Decrypt Content byte[] decryptedContent = decryptContent(File.ReadAllBytes(Path.Combine(outputDir, tmd.Contents[i].ContentID.ToString("x8"))), i, tik, tmd); Array.Resize(ref decryptedContent, (int)tmd.Contents[i].Size); //Check SHA1 byte[] newSha = s.ComputeHash(decryptedContent); if (!Shared.CompareByteArrays(newSha, tmd.Contents[i].Hash)) { fireDebug(@" + Hashes do not match! (Invalid Output)"); //throw new Exception(string.Format("Content #{0}: Hashes do not match!", i)); } //Write Decrypted Content File.WriteAllBytes(Path.Combine(outputDir, (tmd.Contents[i].ContentID.ToString("x8") + ".app")), decryptedContent); } s.Clear(); } //Pack Wad if (storeWad) { fireDebug(" - Building Certificate Chain..."); CertificateChain cert = CertificateChain.FromTikTmd(Path.Combine(outputDir, "cetk"), tmdFileWithCerts); byte[][] contents = new byte[tmd.NumOfContents][]; for (int i = 0; i < tmd.NumOfContents; i++) { contents[i] = File.ReadAllBytes(Path.Combine(outputDir, (tmd.Contents[i].ContentID.ToString("x8") + ".app"))); } fireDebug(" - Creating WAD..."); WAD wad = WAD.Create(cert, tik, tmd, contents); wad.RemoveFooter(); wadName = wadName.Replace("[v]", "v" + this.TitleVersion.ToString()); // fix by madri2 if (Path.DirectorySeparatorChar.ToString() != "/" && Path.AltDirectorySeparatorChar.ToString() != "/") { wadName = wadName.Replace("/", ""); } if (wadName.Contains(Path.DirectorySeparatorChar.ToString()) || wadName.Contains(Path.AltDirectorySeparatorChar.ToString())) { wad.Save(wadName); } else { wad.Save(Path.Combine(outputDir, wadName)); } } //Delete not wanted files if (!storeEncrypted) { fireDebug(" - Deleting Encrypted Contents..."); for (int i = 0; i < encryptedContents.Length; i++) { if (File.Exists(Path.Combine(outputDir, encryptedContents[i]))) { File.Delete(Path.Combine(outputDir, encryptedContents[i])); } } } if (storeWad && !storeDecrypted) { fireDebug(" - Deleting Decrypted Contents..."); for (int i = 0; i < encryptedContents.Length; i++) { if (File.Exists(Path.Combine(outputDir, (encryptedContents[i] + ".app")))) { File.Delete(Path.Combine(outputDir, (encryptedContents[i] + ".app"))); } } } if (!storeDecrypted && !storeEncrypted) { fireDebug(" - Deleting TMD and Ticket..."); File.Delete(Path.Combine(outputDir, tmdFile)); File.Delete(Path.Combine(outputDir, "cetk")); } fireDebug("Downloading Title {0} v{1} Finished...", titleId, tmd.TitleVersion /*(string.IsNullOrEmpty(titleVersion)) ? "[Latest]" : titleVersion*/); fireProgress(100); }
private byte[] downloadSingleContent(string titleId, string titleVersion, string contentId) { uint cId = uint.Parse(contentId, System.Globalization.NumberStyles.HexNumber); contentId = cId.ToString("x8"); fireDebug("Downloading Content (Content ID: {0}) of Title {1} v{2}...", contentId, titleId, (string.IsNullOrEmpty(titleVersion)) ? "[Latest]" : titleVersion); fireDebug(" Checking for Internet connection..."); if (!CheckInet()) { fireDebug(" Connection not found..."); throw new Exception("You're not connected to the internet!"); } fireProgress(0); string tmdFile = "tmd" + (string.IsNullOrEmpty(titleVersion) ? string.Empty : string.Format(".{0}", titleVersion)); string titleUrl = string.Format("{0}{1}/", nusUrl, titleId); string contentIdString = string.Empty; int cIndex = 0; //Download TMD fireDebug(" Downloading TMD..."); byte[] tmdArray = wcNus.DownloadData(titleUrl + tmdFile); fireDebug(" Parsing TMD..."); TMD tmd = TMD.Load(tmdArray); fireProgress(20); //Search for Content ID in TMD fireDebug(" Looking for Content ID {0} in TMD...", contentId); bool foundContentId = false; for (int i = 0; i < tmd.Contents.Length; i++) { if (tmd.Contents[i].ContentID == cId) { fireDebug(" Content ID {0} found in TMD...", contentId); foundContentId = true; contentIdString = tmd.Contents[i].ContentID.ToString("x8"); cIndex = i; break; } } if (!foundContentId) { fireDebug(" Content ID {0} wasn't found in TMD...", contentId); throw new Exception("Content ID wasn't found in the TMD!"); } //Download Ticket fireDebug(" Downloading Ticket..."); byte[] tikArray = wcNus.DownloadData(titleUrl + "cetk"); fireDebug(" Parsing Ticket..."); Ticket tik = Ticket.Load(tikArray); fireProgress(40); //Download and Decrypt Content fireDebug(" Downloading Content... ({0} bytes)", tmd.Contents[cIndex].Size); byte[] encryptedContent = wcNus.DownloadData(titleUrl + contentIdString); fireProgress(80); fireDebug(" Decrypting Content..."); byte[] decryptedContent = decryptContent(encryptedContent, cIndex, tik, tmd); Array.Resize(ref decryptedContent, (int)tmd.Contents[cIndex].Size); //Check SHA1 SHA1 s = SHA1.Create(); byte[] newSha = s.ComputeHash(decryptedContent); if (!Shared.CompareByteArrays(newSha, tmd.Contents[cIndex].Hash)) { fireDebug(@"/!\ /!\ /!\ Hashes do not match /!\ /!\ /!\"); throw new Exception("Hashes do not match!"); } fireProgress(100); fireDebug("Downloading Content (Content ID: {0}) of Title {1} v{2} Finished...", contentId, titleId, (string.IsNullOrEmpty(titleVersion)) ? "[Latest]" : titleVersion); return(decryptedContent); }
private void parseHeader(Stream headerStream) { headerStream.Seek(0, SeekOrigin.Begin); byte[] tmp = new byte[4]; if (!isShortImet) { headerStream.Read(additionalPadding, 0, additionalPadding.Length); } headerStream.Read(padding, 0, padding.Length); headerStream.Read(tmp, 0, 4); if (Shared.Swap(BitConverter.ToUInt32(tmp, 0)) != imetMagic) { throw new Exception("Invalid Magic!"); } headerStream.Read(tmp, 0, 4); if (Shared.Swap(BitConverter.ToUInt32(tmp, 0)) != sizeOfHeader) { throw new Exception("Invalid Header Size!"); } headerStream.Read(tmp, 0, 4); unknown = Shared.Swap(BitConverter.ToUInt32(tmp, 0)); headerStream.Read(tmp, 0, 4); iconSize = Shared.Swap(BitConverter.ToUInt32(tmp, 0)); headerStream.Read(tmp, 0, 4); bannerSize = Shared.Swap(BitConverter.ToUInt32(tmp, 0)); headerStream.Read(tmp, 0, 4); soundSize = Shared.Swap(BitConverter.ToUInt32(tmp, 0)); headerStream.Read(tmp, 0, 4); flags = Shared.Swap(BitConverter.ToUInt32(tmp, 0)); headerStream.Read(japaneseTitle, 0, japaneseTitle.Length); headerStream.Read(englishTitle, 0, englishTitle.Length); headerStream.Read(germanTitle, 0, germanTitle.Length); headerStream.Read(frenchTitle, 0, frenchTitle.Length); headerStream.Read(spanishTitle, 0, spanishTitle.Length); headerStream.Read(italianTitle, 0, italianTitle.Length); headerStream.Read(dutchTitle, 0, dutchTitle.Length); headerStream.Read(unknownTitle1, 0, unknownTitle1.Length); headerStream.Read(unknownTitle2, 0, unknownTitle2.Length); headerStream.Read(koreanTitle, 0, koreanTitle.Length); headerStream.Read(padding2, 0, padding2.Length); headerStream.Read(hash, 0, hash.Length); headerStream.Seek(-16, SeekOrigin.Current); headerStream.Write(new byte[16], 0, 16); byte[] temp = new byte[headerStream.Length]; headerStream.Seek(0, SeekOrigin.Begin); headerStream.Read(temp, 0, temp.Length); MD5 m = MD5.Create(); byte[] newHash = m.ComputeHash(temp, (isShortImet) ? 0 : 0x40, 0x600); m.Clear(); hashesMatch = Shared.CompareByteArrays(newHash, hash); }
private void parseU8(Stream u8File) { fireDebug("Pasing U8 File..."); u8Header = new U8_Header(); rootNode = new U8_Node(); u8Nodes = new List <U8_Node>(); stringTable = new List <string>(); data = new List <byte[]>(); fireDebug(" Detecting Header..."); headerType = Headers.DetectHeader(u8File); Headers.HeaderType tempType = headerType; fireDebug(" -> {0}", headerType.ToString()); if (headerType == Headers.HeaderType.IMD5) { fireDebug(" Reading IMD5 Header..."); header = Headers.IMD5.Load(u8File); byte[] file = new byte[u8File.Length]; u8File.Read(file, 0, file.Length); MD5 m = MD5.Create(); byte[] newHash = m.ComputeHash(file, (int)headerType, (int)u8File.Length - (int)headerType); m.Clear(); if (!Shared.CompareByteArrays(newHash, ((Headers.IMD5)header).Hash)) { fireDebug(@"/!\ /!\ /!\ Hashes do not match /!\ /!\ /!\"); fireWarning(string.Format("Hashes of IMD5 header and file do not match! The content might be corrupted!")); } } else if (headerType == Headers.HeaderType.IMET || headerType == Headers.HeaderType.ShortIMET) { fireDebug(" Reading IMET Header..."); header = Headers.IMET.Load(u8File); if (!((Headers.IMET)header).HashesMatch) { fireDebug(@"/!\ /!\ /!\ Hashes do not match /!\ /!\ /!\"); fireWarning(string.Format("The hash stored in the IMET header doesn't match the headers hash! The header and/or file might be corrupted!")); } } fireDebug(" Checking for Lz77 Compression..."); if (Lz77.IsLz77Compressed(u8File)) { fireDebug(" -> Lz77 Compression Found..."); fireDebug(" Decompressing U8 Data..."); Lz77 l = new Lz77(); Stream decompressedFile = l.Decompress(u8File); tempType = Headers.DetectHeader(decompressedFile); u8File = decompressedFile; lz77 = true; } u8File.Seek((int)tempType, SeekOrigin.Begin); byte[] temp = new byte[4]; //Read U8 Header fireDebug(" Reading U8 Header: Magic... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); u8File.Read(temp, 0, 4); if (Shared.Swap(BitConverter.ToUInt32(temp, 0)) != u8Header.U8Magic) { fireDebug(" -> Invalid Magic!"); throw new Exception("U8 Header: Invalid Magic!"); } fireDebug(" Reading U8 Header: Offset to Rootnode... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); u8File.Read(temp, 0, 4); if (Shared.Swap(BitConverter.ToUInt32(temp, 0)) != u8Header.OffsetToRootNode) { fireDebug(" -> Invalid Offset to Rootnode"); throw new Exception("U8 Header: Invalid Offset to Rootnode!"); } fireDebug(" Reading U8 Header: Header Size... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); u8File.Read(temp, 0, 4); u8Header.HeaderSize = Shared.Swap(BitConverter.ToUInt32(temp, 0)); fireDebug(" Reading U8 Header: Offset to Data... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); u8File.Read(temp, 0, 4); u8Header.OffsetToData = Shared.Swap(BitConverter.ToUInt32(temp, 0)); u8File.Seek(16, SeekOrigin.Current); //Read Rootnode fireDebug(" Reading Rootnode... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); u8File.Read(temp, 0, 4); rootNode.Type = (U8_NodeType)Shared.Swap(BitConverter.ToUInt16(temp, 0)); rootNode.OffsetToName = Shared.Swap(BitConverter.ToUInt16(temp, 2)); u8File.Read(temp, 0, 4); rootNode.OffsetToData = Shared.Swap(BitConverter.ToUInt32(temp, 0)); u8File.Read(temp, 0, 4); rootNode.SizeOfData = Shared.Swap(BitConverter.ToUInt32(temp, 0)); int stringTablePosition = (int)((int)tempType + u8Header.OffsetToRootNode + rootNode.SizeOfData * 12); int nodePosition = (int)u8File.Position; //Read Nodes for (int i = 0; i < rootNode.SizeOfData - 1; i++) { fireDebug(" Reading Node #{1} of {2}... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper(), i + 1, rootNode.SizeOfData - 1); fireProgress((int)((i + 1) * 100 / (rootNode.SizeOfData - 1))); U8_Node tempNode = new U8_Node(); string tempName = string.Empty; byte[] tempData = new byte[0]; //Read Node Entry u8File.Seek(nodePosition, SeekOrigin.Begin); fireDebug(" -> Reading Node Entry... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); u8File.Read(temp, 0, 4); tempNode.Type = (U8_NodeType)Shared.Swap(BitConverter.ToUInt16(temp, 0)); tempNode.OffsetToName = Shared.Swap(BitConverter.ToUInt16(temp, 2)); u8File.Read(temp, 0, 4); tempNode.OffsetToData = Shared.Swap(BitConverter.ToUInt32(temp, 0)); u8File.Read(temp, 0, 4); tempNode.SizeOfData = Shared.Swap(BitConverter.ToUInt32(temp, 0)); nodePosition = (int)u8File.Position; fireDebug(" -> {0}", tempNode.Type.ToString()); //Read Node Name u8File.Seek(stringTablePosition + tempNode.OffsetToName, SeekOrigin.Begin); fireDebug(" -> Reading Node Name... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); for (;;) { char tempChar = (char)u8File.ReadByte(); if (tempChar == 0x00) { break; } tempName += tempChar; if (tempName.Length > 255) { break; } } fireDebug(" -> {0}", tempName); //Read Node Data if (tempNode.Type == U8_NodeType.File) { u8File.Seek((int)tempType + tempNode.OffsetToData, SeekOrigin.Begin); fireDebug(" -> Reading Node Data (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); tempData = new byte[tempNode.SizeOfData]; u8File.Read(tempData, 0, tempData.Length); } if (tempName.ToLower() == "icon.bin") { iconSize = getRealSize(tempData); } else if (tempName.ToLower() == "banner.bin") { bannerSize = getRealSize(tempData); } else if (tempName.ToLower() == "sound.bin") { soundSize = getRealSize(tempData); } u8Nodes.Add(tempNode); stringTable.Add(tempName); data.Add(tempData); } fireDebug("Pasing U8 File Finished..."); }
private int PrivPatchAll(ref byte[] esModule) { FireDebug("Patching Fakesigning, ES_Identify, NAND Permissions and VP ..."); int num = 0; byte[] second1 = new byte[4] { 32, 7, 35, 162 }; byte[] second2 = new byte[4] { 32, 7, 75, 11 }; byte[] second3 = new byte[4] { 40, 3, 209, 35 }; byte[] second4 = new byte[6] { 66, 139, 208, 1, 37, 102 }; byte[] second5 = new byte[4] { 210, 1, 78, 86 }; for (int firstIndex = 0; firstIndex < esModule.Length - 6; ++firstIndex) { FireProgress((firstIndex + 1) * 100 / esModule.Length); if (Shared.CompareByteArrays(esModule, firstIndex, second1, 0, 4) || Shared.CompareByteArrays(esModule, firstIndex, second2, 0, 4)) { FireDebug(" Patching Fakesigning at Offset: 0x{0}", (object)firstIndex.ToString("x8").ToUpper()); esModule[firstIndex + 1] = 0; firstIndex += 4; ++num; } else if (Shared.CompareByteArrays(esModule, firstIndex, second3, 0, 4)) { FireDebug(" Patching ES_Identify at Offset: 0x{0}", (object)firstIndex.ToString("x8").ToUpper()); esModule[firstIndex + 2] = 0; esModule[firstIndex + 3] = 0; firstIndex += 4; ++num; } else if (Shared.CompareByteArrays(esModule, firstIndex, second4, 0, 6)) { FireDebug(" Patching NAND Permissions at Offset: 0x{0}", (object)firstIndex.ToString("x8").ToUpper()); esModule[firstIndex + 2] = 224; firstIndex += 6; ++num; } else if (Shared.CompareByteArrays(esModule, firstIndex, second5, 0, 4)) { FireDebug(" Patching VP at Offset: 0x{0}", (object)firstIndex.ToString("x8").ToUpper()); esModule[firstIndex] = 224; firstIndex += 4; ++num; } } FireDebug("Patching Fakesigning, ES_Identify, NAND Permissions and VP Finished... (Patches applied: {0})", (object)num); return(num); }
public void Read(Stream input) { BinaryReader reader = new BinaryReader(input); if (!Shared.CompareByteArrays(magic, reader.ReadBytes(4))) { throw new Exception("This is not a valid BNS audfo file!"); } size = Shared.Swap(reader.ReadUInt32()); codec = reader.ReadByte(); hasLoop = reader.ReadByte(); channelCount = reader.ReadByte(); zero = reader.ReadByte(); sampleRate = Shared.Swap(reader.ReadUInt16()); pad0 = Shared.Swap(reader.ReadUInt16()); loopStart = Shared.Swap(reader.ReadUInt32()); loopEnd = Shared.Swap(reader.ReadUInt32()); offsetToChannelStart = Shared.Swap(reader.ReadUInt32()); pad1 = Shared.Swap(reader.ReadUInt32()); channel1StartOffset = Shared.Swap(reader.ReadUInt32()); channel2StartOffset = Shared.Swap(reader.ReadUInt32()); channel1Start = Shared.Swap(reader.ReadUInt32()); coefficients1Offset = Shared.Swap(reader.ReadUInt32()); if (channelCount == 2) { pad2 = Shared.Swap(reader.ReadUInt32()); channel2Start = Shared.Swap(reader.ReadUInt32()); coefficients2Offset = Shared.Swap(reader.ReadUInt32()); pad3 = Shared.Swap(reader.ReadUInt32()); for (int i = 0; i < 16; i++) { coefficients1[i] = (short)Shared.Swap(reader.ReadUInt16()); } channel1Gain = Shared.Swap(reader.ReadUInt16()); channel1PredictiveScale = Shared.Swap(reader.ReadUInt16()); channel1PreviousValue = Shared.Swap(reader.ReadUInt16()); channel1NextPreviousValue = Shared.Swap(reader.ReadUInt16()); channel1LoopPredictiveScale = Shared.Swap(reader.ReadUInt16()); channel1LoopPreviousValue = Shared.Swap(reader.ReadUInt16()); channel1LoopNextPreviousValue = Shared.Swap(reader.ReadUInt16()); channel1LoopPadding = Shared.Swap(reader.ReadUInt16()); for (int i = 0; i < 16; i++) { coefficients2[i] = (short)Shared.Swap(reader.ReadUInt16()); } channel2Gain = Shared.Swap(reader.ReadUInt16()); channel2PredictiveScale = Shared.Swap(reader.ReadUInt16()); channel2PreviousValue = Shared.Swap(reader.ReadUInt16()); channel2NextPreviousValue = Shared.Swap(reader.ReadUInt16()); channel2LoopPredictiveScale = Shared.Swap(reader.ReadUInt16()); channel2LoopPreviousValue = Shared.Swap(reader.ReadUInt16()); channel2LoopNextPreviousValue = Shared.Swap(reader.ReadUInt16()); channel2LoopPadding = Shared.Swap(reader.ReadUInt16()); } else if (channelCount == 1) { for (int i = 0; i < 16; i++) { coefficients1[i] = (short)Shared.Swap(reader.ReadUInt16()); } channel1Gain = Shared.Swap(reader.ReadUInt16()); channel1PredictiveScale = Shared.Swap(reader.ReadUInt16()); channel1PreviousValue = Shared.Swap(reader.ReadUInt16()); channel1NextPreviousValue = Shared.Swap(reader.ReadUInt16()); channel1LoopPredictiveScale = Shared.Swap(reader.ReadUInt16()); channel1LoopPreviousValue = Shared.Swap(reader.ReadUInt16()); channel1LoopNextPreviousValue = Shared.Swap(reader.ReadUInt16()); channel1LoopPadding = Shared.Swap(reader.ReadUInt16()); } }