/// <summary>Initialize the package via header info /// <param name="xHeaderIO">Stream to header information</param> /// <param name="xDataPath">Path of data files, null if you want to want to load header only</param> /// </summary> public SVODPackage(DJsIO xHeaderIO, string xDataPath) { xActive = true; if (xDataPath != null && xDataPath != "") { xDataPath = xDataPath.Replace('\\', '/'); if (xDataPath[xDataPath.Length - 1] == '/') { xDataPath = xDataPath.Substring(0, xDataPath.Length - 1); } } new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(System.DLLIdentify.PrivilegeCheck)).Start(System.Threading.Thread.CurrentThread); IO = xHeaderIO; xHeaderIO.Position = 0; xHeaderIO.IsBigEndian = true; uint xBuff = xHeaderIO.ReadUInt32(); if (!Enum.IsDefined(typeof(PackageMagic), xBuff) || (PackageMagic)xBuff == PackageMagic.Unknown) { return; } xHeaderIO.Position = 0x379; if (xHeaderIO.ReadByte() != 0x24 && xHeaderIO.ReadByte() != 5 && xHeaderIO.ReadByte() != 5 && xHeaderIO.ReadByte() != 0x11) { return; } xHeaderData = new HeaderData(xHeaderIO, (PackageMagic)xBuff); xHeaderIO.Position = 0x391; xIsShifted = (((xHeaderIO.ReadByte() >> 6) & 1) == 1); xBlockCount = xHeaderIO.ReadUInt24(); if (xIsShifted) { xDeviation = xHeaderIO.ReadUInt32(false); } if (xDataPath == null || xDataPath == "") { xActive = false; return; } try { xDataFiles = new DJsIO[(int)xHeaderData.DataFileCount]; } catch { throw SVODExcepts.Unknown; } if (xDataFiles.Length > 9999 || xDataFiles.Length == 0) { throw SVODExcepts.Count; } for (uint i = 0; i < xDataFiles.Length; i++) { xDataFiles[i] = new DJsIO(xDataPath + SVODFuncs.formatstring((uint)i), DJFileMode.Open, true); if (!xDataFiles[i].Accessed) { throw SVODExcepts.Access; } } xActive = false; }
/// <summary> /// Loads data /// </summary> /// <param name="xDataPath"></param> /// <returns></returns> public bool LoadData(string xDataPath) { if (!ActiveCheck()) { return(false); } DJsIO[] xnewdats = null; try { xnewdats = new DJsIO[xHeaderData.DataFileCount]; for (uint i = 0; i < xHeaderData.DataFileCount; i++) { xnewdats[i] = new DJsIO(xDataPath + SVODFuncs.formatstring((uint)i), DJFileMode.Open, true); if (!xnewdats[i].Accessed) { throw SVODExcepts.Access; } } } catch { if (xnewdats != null) { foreach (DJsIO x in xnewdats) { if (x != null) { x.Close(); } } } return(xActive = false); } if (dataloaded || xDataFiles != null) { foreach (DJsIO x in xDataFiles) { x.Close(); } xDataFiles = null; } xDataFiles = xnewdats; return(!(xActive = false)); }
long GenerateDataOffset(uint xBlock) { return(SVODFuncs.GenerateDataOffset(xBlock)); }
long GenerateHashOffset(uint xBlock, byte xTree) { return(SVODFuncs.GenerateHashOffset(xBlock, xTree)); }
/// <summary> /// Builds the package /// </summary> /// <param name="xParams"></param> /// <param name="ContentType"></param> /// <returns></returns> public bool Create(RSAParams xParams, PackageType ContentType) { if (BaseImage == null) { throw new Exception("No image"); } if (!xParams.Valid) { throw CryptoExcepts.ParamError; } if (ContentType != PackageType.HDDInstalledGame && ContentType != PackageType.OriginalXboxGame && ContentType != PackageType.GamesOnDemand && ContentType != PackageType.SocialTitle) { return(false); } if (xActive) { return(false); } xActive = true; DJsIO x = null; DJsIO h = null; try { string outlocale = OutLocation.Replace('\\', '/'); if (outlocale[outlocale.Length - 1] == '/') { outlocale = outlocale.Substring(0, outlocale.Length - 1); } outlocale += '/' + ((uint)ContentType).ToString("X8"); string DataFolder = outlocale + "/" + xHeader.TitleID.ToString("X8") + ".data"; if (!VariousFunctions.xCheckDirectory(OutLocation)) { throw IOExcepts.CreateError; } if (!VariousFunctions.xCheckDirectory(DataFolder)) { throw IOExcepts.CreateError; } uint xBlockCount = 0; uint xDataFileCount = 0; long xDataLength = 0; BaseImage.xIO.Position = BaseImage.baseoffset; while (BaseImage.xIO.Position < BaseImage.xIO.Length) { if ((xBlockCount % Constants.SVODBL[1]) == 0) { if (x != null) { for (int i = 0; i < 0xCB; i++) { x.Position = SVODFuncs.GenerateHashOffset((uint)(i * Constants.SVODBL[0]), 0); byte[] Data1 = SHA1Quick.ComputeHash(x.ReadBytes(0x1000)); x.Position = SVODFuncs.GenerateHashOffset((uint)(i * Constants.SVODBL[0]), 1); x.Write(Data1); } x.Flush(); xDataLength += x.Length; x.Close(); } x = new DJsIO(DataFolder + SVODFuncs.formatstring(xDataFileCount), DJFileMode.Create, true); xDataFileCount++; } x.Position = SVODFuncs.GenerateDataOffset(xBlockCount); byte[] Data = BaseImage.xIO.ReadBytes(0x1000); x.Write(Data); x.Position = SVODFuncs.GenerateHashOffset(xBlockCount, 0); x.Write(SHA1Quick.ComputeHash(Data)); xBlockCount++; } if (xBlockCount == 0) { x.Close(); return(xActive = false); } x.Flush(); xDataLength += x.Length; int lvlct = (int)((((xBlockCount % Constants.SVODBL[1]) - 1) / Constants.SVODBL[0]) + 1); for (int i = 0; i < lvlct; i++) { x.Position = SVODFuncs.GenerateHashOffset((uint)(i * Constants.SVODBL[0]), 0); byte[] Data1 = SHA1Quick.ComputeHash(x.ReadBytes(0x1000)); x.Position = SVODFuncs.GenerateHashOffset((uint)(i * Constants.SVODBL[0]), 1); x.Write(Data1); } x.Flush(); x.Close(); byte[] Hash = null; for (int i = (int)(xDataFileCount - 1); i >= 0; i--) { x = new DJsIO(DataFolder + SVODFuncs.formatstring((uint)i), DJFileMode.Open, true); if (Hash != null) { x.Position = 0xFF0; x.Write(Hash); x.Flush(); } x.Position = 0; Hash = SHA1Quick.ComputeHash(x.ReadBytes(0x1000)); } xHeader.DataFileSize = xDataLength; xHeader.DataFileCount = xDataFileCount; xHeader.xThisType = ContentType; h = new DJsIO(outlocale + "/" + xHeader.TitleID.ToString("X8"), DJFileMode.Create, true); xHeader.Write(ref h); h.SetLength(0xB000); h.Position = 0x340; h.Write((uint)0xAD0E); h.Position = 0x379; h.Write(new byte[] { 0x24, 5, 5, 0x11 }); h.Write(Hash); h.Write((byte)((Deviation == 0) ? 0 : 0x40)); h.WriteUInt24(xBlockCount); h.Write(Deviation, false); h.Position = 0x344; byte[] xHash = SHA1Quick.ComputeHash(h.ReadBytes((int)(h.Length - 0x344))); h.Position = 0x32C; h.Write(xHash); h.Flush(); h.Position = 0x22C; xHash = SHA1Quick.ComputeHash(h.ReadBytes(0x118)); h.Position = 4; if (xParams.Type == PackageMagic.CON) { h.Write(xParams.Certificate); h.Write(ScrambleMethods.StockScramble(RSAQuick.SignatureGenerate(xParams.RSAKeys, xHash), true)); } else { h.Write(ScrambleMethods.DevScramble(RSAQuick.SignatureGenerate(xParams.RSAKeys, xHash))); h.Write(new byte[0x128]); } h.IsBigEndian = true; h.Position = 0; h.Write(((uint)xParams.Type)); xHeader.xMagic = xParams.Type; h.Flush(); h.Close(); return(!(xActive = false)); } catch { if (x != null) { x.Close(); } if (h != null) { h.Close(); } return(xActive = false); } }