public byte[] GetBytes(FileStream isoStream, long volumeOffset, long dataOffset, long blockOffset, long size, byte[] partitionKey) { byte[] value = new byte[size]; byte[] encryptedPartitionCluster; byte[] encryptedClusterDataSection; byte[] decryptedClusterDataSection; byte[] clusterIV; long bufferLocation = 0; long maxCopySize; long copySize; while (size > 0) { // get block offset info NintendoWiiOpticalDisc.WiiBlockStructure blockStructure = NintendoWiiOpticalDisc.GetWiiBlockStructureForOffset(blockOffset); // read current block //encryptedPartitionCluster = ParseFile.ParseSimpleOffset(isoStream, // volumeOffset + dataOffset + (blockStructure.BlockNumber * 0x8000), // 0x8000); if (this.CurrentDecryptedBlockNumber != blockStructure.BlockNumber) { encryptedPartitionCluster = ParseFile.ParseSimpleOffset(isoStream, volumeOffset + dataOffset + (blockStructure.BlockNumber * 0x8000), 0x8000); clusterIV = ParseFile.ParseSimpleOffset(encryptedPartitionCluster, 0x03D0, 0x10); encryptedClusterDataSection = ParseFile.ParseSimpleOffset(encryptedPartitionCluster, 0x400, 0x7C00); decryptedClusterDataSection = AESEngine.Decrypt(this.Algorithm, encryptedClusterDataSection, partitionKey, clusterIV, CipherMode.CBC, PaddingMode.Zeros); this.CurrentDecryptedBlock = decryptedClusterDataSection; this.CurrentDecryptedBlockNumber = blockStructure.BlockNumber; } // copy the decrypted data maxCopySize = 0x7C00 - blockStructure.BlockOffset; copySize = (size > maxCopySize) ? maxCopySize : size; Array.Copy(this.CurrentDecryptedBlock, blockStructure.BlockOffset, value, bufferLocation, copySize); // update counters size -= copySize; bufferLocation += copySize; blockOffset += copySize; } return(value); }
public void ExtractFile(FileStream isoStream, string destinationPath, long volumeOffset, long dataOffset, long blockOffset, long size, byte[] partitionKey) { byte[] value = new byte[0x7C00]; byte[] encryptedPartitionCluster; byte[] encryptedClusterDataSection; byte[] decryptedClusterDataSection; byte[] clusterIV; long maxCopySize; long copySize; // create destination string destintionDirectory = Path.GetDirectoryName(destinationPath); if (!Directory.Exists(destintionDirectory)) { Directory.CreateDirectory(destintionDirectory); } using (FileStream outStream = File.Open(destinationPath, FileMode.Create, FileAccess.Write)) { while (size > 0) { try { // get block offset info NintendoWiiOpticalDisc.WiiBlockStructure blockStructure = NintendoWiiOpticalDisc.GetWiiBlockStructureForOffset(blockOffset); // read current block //encryptedPartitionCluster = ParseFile.ParseSimpleOffset(isoStream, // volumeOffset + dataOffset + (blockStructure.BlockNumber * 0x8000), // 0x8000); if (this.CurrentDecryptedBlockNumber != blockStructure.BlockNumber) { encryptedPartitionCluster = ParseFile.ParseSimpleOffset(isoStream, volumeOffset + dataOffset + (blockStructure.BlockNumber * 0x8000), 0x8000); if (encryptedPartitionCluster.Length == 0) { throw new Exception(String.Format("Encrypted cluster 0x{0) has size zero. This image is probably corrupt.", blockStructure.BlockNumber.ToString("X8"))); } else { clusterIV = ParseFile.ParseSimpleOffset(encryptedPartitionCluster, 0x03D0, 0x10); encryptedClusterDataSection = ParseFile.ParseSimpleOffset(encryptedPartitionCluster, 0x400, 0x7C00); decryptedClusterDataSection = AESEngine.Decrypt(this.Algorithm, encryptedClusterDataSection, partitionKey, clusterIV, CipherMode.CBC, PaddingMode.Zeros); this.CurrentDecryptedBlock = decryptedClusterDataSection; this.CurrentDecryptedBlockNumber = blockStructure.BlockNumber; } } // copy the encrypted data maxCopySize = 0x7C00 - blockStructure.BlockOffset; copySize = (size > maxCopySize) ? maxCopySize : size; outStream.Write(this.CurrentDecryptedBlock, (int)blockStructure.BlockOffset, (int)copySize); // update counters size -= copySize; blockOffset += copySize; } catch (Exception ie) { throw ie; } } } }