示例#1
0
        private long partitionStreamWrite(LongRef outSize, Stream inStream, Stream target, long size, DatData settingsData, NkitPartitionPatchInfo patchInfo, WiiHashStore hashes, Coordinator pc)
        {
            DatData data = settingsData;

            List <string> addedFiles = new List <string>();

            DateTime dt = DateTime.Now;

            MemorySection hdr       = MemorySection.Read(inStream, 0x440);
            long          srcPos    = hdr.Size;
            long          outPos    = 0;
            long          imageSize = 0;

            try
            {
                if (hdr.ReadString(0, 4) == "\0\0\0\0")
                {
                    long    nullsPos   = 0;
                    long    fileLength = -1;
                    LongRef gapLength  = new LongRef()
                    {
                        Value = -1
                    };
                    target.Write(hdr.Data, 0, (int)hdr.Size);
                    MemorySection sz = MemorySection.Read(inStream, 4);
                    srcPos       += 4;
                    outPos       += hdr.Size;
                    imageSize     = sz.ReadUInt32B(0) * 4L;
                    outSize.Value = NStream.HashedLenToData(imageSize);
                    JunkStream junk = new JunkStream(hdr.Read(0, 4), hdr.Read8(6), outSize.Value); //SET LENGTH FROM HEADER
                    outPos += writeGap(ref fileLength, gapLength, ref nullsPos, ref srcPos, outPos, inStream, target, junk, true, patchInfo.ScrubManager);
                }
                else
                {
                    string idVer = hdr.ReadString(0x200, 8);
                    if (idVer != "NKIT v01")
                    {
                        throw new Exception(string.Format("{0} not supported by this version", idVer));
                    }
                    bool isNkit = idVer.StartsWith("NKIT");
                    imageSize     = NStream.HashedLenToData((hdr.ReadUInt32B(0x210) * 4L));
                    outSize.Value = imageSize;
                    string junkId = hdr.ReadString(0x214, 4);

                    JunkStream junk = new JunkStream(hdr.Read(0, 4), hdr.Read8(6), imageSize); //SET LENGTH FROM HEADER

                    MemorySection fst;
                    long          mainDolAddr = hdr.ReadUInt32B(0x420);

                    //############################################################################
                    //# READ DISC START

                    MemorySection hdrToFst = MemorySection.Read(inStream, (hdr.ReadUInt32B(0x424) * 4L) - hdr.Size);
                    srcPos += hdrToFst.Size;

                    fst = MemorySection.Read(inStream, hdr.ReadUInt32B(0x428) * 4L);
                    long postFstPos = (hdr.ReadUInt32B(0x424) * 4L) + fst.Size;
                    srcPos += fst.Size;

                    hashes.WriteFlagsData(imageSize, inStream);
                    srcPos += hashes.FlagsLength;

                    patchInfo.PartitionDataHeader = hdr;
                    patchInfo.Fst = fst;

                    //############################################################################
                    //# WRITE DISC START

                    target.Write(hdr.Data, 0, (int)hdr.Size);
                    target.Write(hdrToFst.Data, 0, (int)hdrToFst.Size); //padded when read
                    target.Write(fst.Data, 0, fst.Data.Length);

                    hdrToFst = null; //let this be collected if needed

                    outPos = (hdr.ReadUInt32B(0x424) * 4L) + fst.Size;
                    long               nullsPos = outPos + 0x1c;
                    string             error;
                    List <ConvertFile> conFiles = NkitFormat.GetConvertFstFiles(inStream, size, hdr, fst, false, -1, out error);

                    if (conFiles == null)
                    {
                        if (error != null)
                        {
                            _log?.LogDetail(error);
                        }
                        ConvertFile cf = new ConvertFile(imageSize - srcPos, true) //result.ImageInfo.IsoSize
                        {
                            FstFile = new FstFile(null)
                            {
                                DataOffset = hdr.ReadUInt32B(0x424), Offset = hdr.ReadUInt32B(0x424), Length = (int)fst.Size
                            },
                        };
                        outPos += writeGap(cf, ref nullsPos, ref srcPos, outPos, inStream, target, junk, true, patchInfo.ScrubManager);
                    }
                    else
                    {
                        conFiles[0].GapLength -= hashes.FlagsLength; //fix for a few customs (no gap between the fst and the first file on the source image, but the hash mask makes it look like there is)
                        //########### FILES
                        bool firstFile = true;
                        for (int i = 0; i < conFiles.Count; i++) //read the files and write them out as goodFiles (possible order difference
                        {
                            ConvertFile f  = conFiles[i];
                            FstFile     ff = f.FstFile;

                            if (!firstFile) //fst already written
                            {
                                //Debug.WriteLine(string.Format(@"{0}>{1} : {2}>{3} : {4} : {5}/{6}", ff.DataOffset.ToString("X8"), outPos.ToString("X8"), (ff.DataOffset + ff.Length).ToString("X8"), (outPos + ff.Length).ToString("X8"), ff.Length.ToString("X8"), ff.Path, ff.Name));

                                if (srcPos < ff.DataOffset)                                  //skip any padding (not written for wii currently)
                                {
                                    inStream.Copy(ByteStream.Zeros, ff.DataOffset - srcPos); //skip any 32k align padding etc
                                    srcPos += ff.DataOffset - srcPos;
                                }

                                //write file
                                if (ff.DataOffset == mainDolAddr)
                                {
                                    hdr.WriteUInt32B(0x420, (uint)(outPos / 4L));
                                }
                                fst.WriteUInt32B(ff.OffsetInFstFile, (uint)(outPos / 4L));
                                outPos += copyFile(f, ref nullsPos, ref srcPos, outPos, inStream, target);
                            }

                            if (outPos < imageSize)
                            {
                                long gapLen = writeGap(f, ref nullsPos, ref srcPos, outPos, inStream, target, junk, i == 0 || i == conFiles.Count - 1, patchInfo.ScrubManager);
                                outPos += gapLen;
                                if (!firstFile)
                                {
                                    fst.WriteUInt32B(ff.OffsetInFstFile + 4, (uint)(ff.Length));
                                }
                            }

                            firstFile = false;
                        }
                    }
                }
                return(srcPos);
            }
            catch (Exception ex)
            {
                throw pc.SetReaderException(ex, "NkitReaderWii.Read - partitionRead");
            }
        }
示例#2
0
        public bool Unscrub(List <JunkRedumpPatch> junkPatches)
        {
            bool changed = false;
            //bool performCheck = true; //start on the assumption last was valid as it would be hassle to work out
            List <FstFile> nulls = new List <FstFile>();

            bool good = _data.IsValid(false);                                                    //forces decrypt and hash cache build and test - does not test data in blocks matchs H0 table

            Parallel.For(0, _data.UsedBlocks, bi => _unscrubValid[bi] = _data.BlockIsValid(bi)); //test data matches H0 table

            for (int bi = 0; bi < _data.UsedBlocks; bi++)
            {
                if (!_unscrubValid[bi])
                {
                    if (_junk == null)
                    {
                        _junk = new JunkStream(_partHdr.Id, _partHdr.DiscNo, _partHdr.PartitionDataSize);
                    }

                    _junk.Position = NStream.OffsetToData(this.Offset + _data.BlockDataOffset(bi), true);
                    _junk.Read(_data.Decrypted, _data.BlockDataOffset(bi), 0x7c00);
                    _data.MarkBlockUnscrubbedAndDirty(bi);
                    changed = true;
                }
            }

            if (junkPatches != null && junkPatches.Count != 0)
            {
                foreach (JunkRedumpPatch jp in junkPatches)
                {
                    if (jp.Offset >= this.DiscOffset && jp.Offset < this.DiscOffset + this.Size)
                    {
                        Array.Copy(jp.Data, 0, _data.Decrypted, jp.Offset - this.DiscOffset, jp.Data.Length);
                        _data.MarkBlockDirty((int)((jp.Offset - this.DiscOffset) / 0x8000));  //560de532
                    }
                }
            }

            if (changed)
            {
                good = _data.IsValid(true); //true as changes were made
                if (!good)
                {
                    bool zerod = false;
                    List <Tuple <long, int, FstFile> > h3Nulls = new List <Tuple <long, int, FstFile> >(_partHdr.ScrubManager.H3Nulls);

                    if (h3Nulls.Count != 0)
                    {
                        int dataLen = (int)NStream.HashedLenToData(this.Decrypted.Length);
                        foreach (Tuple <long, int, FstFile> n in h3Nulls)
                        {
                            if (n.Item1 >= this.DataOffset && n.Item1 < this.DataOffset + dataLen)
                            {
                                int idx = (int)((n.Item1 - this.DataOffset) / 0x7c00);
                                _data.MarkBlockDirty(idx);
                                int pos = (int)NStream.DataToOffset(n.Item1 - this.DataOffset, true);
                                Array.Clear(_data.Decrypted, pos, n.Item2);
                                zerod = true;
                            }
                        }
                    }
                    if (zerod)
                    {
                        good = _data.IsValid(true);
                    }
                    if (!good)
                    {
                        this.H3Errors++;
                    }
                }
            }

            return(changed);
        }
示例#3
0
        internal WiiPartitionHeaderSection(WiiDiscHeaderSection header, NStream stream, long discOffset, byte[] data, long size) : base(stream, discOffset, data, size)
        {
            _hdr        = header;
            _fileSystem = null;
            Aes         = Aes.Create();
            _sha1       = SHA1.Create();

            Aes.Padding       = PaddingMode.None;
            _dataOffset       = this.ReadUInt32B(0x2b8) * 4L;
            PartitionSize     = this.ReadUInt32B(0x2bc) * 4L;
            PartitionDataSize = NStream.HashedLenToData(PartitionSize);

            int h3Offset  = (int)this.ReadUInt32B(0x2b4) * 4;
            int tmdOffset = (int)(this.ReadUInt32B(0x2a8) * 4);

            if (h3Offset != 0)
            {
                H3Table = this.Read(h3Offset, 0x18000);
            }
            if (tmdOffset != 0)
            {
                ContentSha1 = this.Read(tmdOffset + 0x1e4 + 0x10, 20);
            }

            // Determine the common key to use.
            string issuer = Encoding.ASCII.GetString(this.Read(0x140, 64)).TrimEnd('\0');

            IsRvt    = issuer == "Root-CA00000002-XS00000006"; //Use the RVT-R key.
            IsKorean = !IsRvt && this.Read8(0x1f1) == 1;       //Use the Korean Key
            IsRvtR   = !(IsRvtH = IsRvt && PartitionSize == 0);
            if (IsRvtH)
            {
                return; //notsupported
            }
            int i = IsRvt ? 0 : IsKorean ? 1 : 2;

            byte[] lame = Convert.FromBase64String(_lame);
            byte[] l    = new byte[lame.Length / 3];
            for (int j = 0; j < l.Length; i += 3)
            {
                l[j++] = lame[i];
            }
            Aes.Key = l;

            byte[] titleKey = this.Read(0x1bf, 16);
            byte[] iv       = this.Read(0x1dc, 16);
            Array.Clear(iv, 8, 8);
            Aes.IV = iv;

            using (ICryptoTransform cryptor = Aes.CreateDecryptor())
                cryptor.TransformBlock(titleKey, 0, 16, titleKey, 0);

            this.Key = titleKey;
            Aes.Key  = this.Key;

            //decrypt scrubbed values. This is to allow the comparison of scrubbed partition data in the decrypted layer
            DecryptedScrubbed00 = new byte[16];
            DecryptedScrubbedFF = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

            Aes.IV = (byte[])DecryptedScrubbedFF.Clone(); //if properly scrubbed then the KEY is FFs too
            using (ICryptoTransform cryptor = Aes.CreateDecryptor())
                cryptor.TransformBlock(DecryptedScrubbedFF, 0, 16, DecryptedScrubbedFF, 0);

            Aes.IV = new byte[16];
            using (ICryptoTransform cryptor = Aes.CreateDecryptor())
                cryptor.TransformBlock(DecryptedScrubbed00, 0, 16, DecryptedScrubbed00, 0);

            _scrubManager = new ScrubManager(this);
        }