예제 #1
0
        public NUSTitle loadNusTitle(NUSTitleConfig config)
        {
            NUSTitle result = new NUSTitle();

            NUSDataProvider dataProvider = getDataProvider(result, config);

            result.dataProvider = (dataProvider);

            TMD tmd = TMD.parseTMD(dataProvider.getRawTMD());

            result.TMD = (tmd);

            if (tmd == null)
            {
                //MessageBox.Show("TMD not found.");
                throw new Exception();
            }

            Ticket ticket = config.ticket;

            if (ticket == null)
            {
                ticket = Ticket.parseTicket(dataProvider.getRawTicket());
            }
            result.ticket = ticket;
            // System.out.println(ticket);

            Content fstContent = tmd.getContentByIndex(0);

            MemoryStream fstContentEncryptedStream = dataProvider.getInputStreamFromContent(fstContent, 0);

            if (fstContentEncryptedStream == null)
            {
                return(null);
            }

            byte[] fstBytes = fstContentEncryptedStream.ToArray();// StreamUtils.getBytesFromStream(fstContentEncryptedStream, (int)fstContent.getEncryptedFileSize());

            if (fstContent.isEncrypted())
            {
                AESDecryption aesDecryption = new AESDecryption(ticket.decryptedKey, new byte[0x10]);
                fstBytes = aesDecryption.decrypt(fstBytes);
            }

            Dictionary <int, Content> contents = tmd.getAllContents();

            FST fst = FST.parseFST(fstBytes, contents);

            result.FST = (fst);

            return(result);
        }
예제 #2
0
        private static Dictionary <string, WUDPartition> readPartitions(WUDInfo wudInfo, byte[] partitionTocBlock)
        {
            byte[] buffer = new byte[partitionTocBlock.Length];

            int partitionCount = (int)SwapEndianness(BitConverter.ToUInt32(partitionTocBlock, 0x1C));

            Dictionary <string, WUDPartition> partitions = new Dictionary <string, WUDPartition>();

            byte[] gamePartitionTMD    = new byte[0];
            byte[] gamePartitionTicket = new byte[0];
            byte[] gamePartitionCert   = new byte[0];

            String realGamePartitionName = "";

            // populate partition information from decrypted TOC
            for (int i = 0; i < partitionCount; i++)
            {
                int    offset = (PARTITION_TOC_OFFSET + (i * PARTITION_TOC_ENTRY_SIZE));
                byte[] partitionIdentifier = new byte[0x19];
                Array.ConstrainedCopy(partitionTocBlock, offset, partitionIdentifier, 0, 0x19);

                int j = 0;
                for (j = 0; j < partitionIdentifier.Length; j++)
                {
                    if (partitionIdentifier[j] == 0)
                    {
                        break;
                    }
                }

                byte[] partitionNameArray = new byte[j];
                Array.ConstrainedCopy(partitionIdentifier, 0, partitionNameArray, 0, j);
                String partitionName = Encoding.ASCII.GetString(partitionNameArray);

                // calculate partition offset (relative from WIIU_DECRYPTED_AREA_OFFSET) from decrypted TOC
                long tmp = SwapEndianness(BitConverter.ToUInt32(partitionTocBlock, (PARTITION_TOC_OFFSET + (i * PARTITION_TOC_ENTRY_SIZE) + 0x20)));

                long partitionOffset = ((tmp * (long)0x8000) - 0x10000);

                WUDPartition partition = new WUDPartition(partitionName, partitionOffset);

                if (partitionName.StartsWith("SI"))
                {
                    byte[] fileTableBlock = wudInfo.WUDDiscReader.readDecryptedToByteArray(Settings.WIIU_DECRYPTED_AREA_OFFSET + partitionOffset, 0, 0x8000,
                                                                                           wudInfo.titleKey, null);

                    byte[] copy = new byte[4];

                    Array.ConstrainedCopy(fileTableBlock, 0, copy, 0, 4);
                    if (!ArraysEqual(copy, PARTITION_FILE_TABLE_SIGNATURE))
                    {
                        //MessageBox.Show("FST Decrpytion failed");
                        continue;
                    }

                    //if (!Arrays.equals(Arrays.copyOfRange(fileTableBlock, 0, 4), PARTITION_FILE_TABLE_SIGNATURE))
                    //{
                    //    log.info("FST Decrpytion failed");
                    //    continue;
                    //}

                    FST fst = FST.parseFST(fileTableBlock, null);

                    byte[] rawTIK  = getFSTEntryAsByte(WUD_TICKET_FILENAME, partition, fst, wudInfo.WUDDiscReader, wudInfo.titleKey);
                    byte[] rawTMD  = getFSTEntryAsByte(WUD_TMD_FILENAME, partition, fst, wudInfo.WUDDiscReader, wudInfo.titleKey);
                    byte[] rawCert = getFSTEntryAsByte(WUD_CERT_FILENAME, partition, fst, wudInfo.WUDDiscReader, wudInfo.titleKey);

                    gamePartitionTMD    = rawTMD;
                    gamePartitionTicket = rawTIK;
                    gamePartitionCert   = rawCert;

                    // We want to use the real game partition
                    realGamePartitionName = partitionName = "GM" + Utils.ByteArrayToString(Arrays.copyOfRange(rawTIK, 0x1DC, 0x1DC + 0x08));
                }
                else if (partitionName.StartsWith(realGamePartitionName))
                {
                    wudInfo.gamePartitionName = partitionName;
                    partition = new WUDGamePartition(partitionName, partitionOffset, gamePartitionTMD, gamePartitionCert, gamePartitionTicket);
                }
                byte[]             header          = wudInfo.WUDDiscReader.readEncryptedToByteArray(partition.partitionOffset + 0x10000, 0, 0x8000);
                WUDPartitionHeader partitionHeader = WUDPartitionHeader.parseHeader(header);
                partition.partitionHeader = (partitionHeader);

                partitions.Add(partitionName, partition);
            }

            return(partitions);
        }