private static List <uint> _MakeMiniSectorOffsetChain( _CompoundFileInfo cfi, uint startMiniSectorId) { var chain = new List <uint>(); if (!_IsRegulerSectorId(startMiniSectorId)) { return(chain); } var miniFatSoc = _MakeSectorOffsetChain( cfi, cfi.firstMiniFatSectorId ); var miniStreamSoc = _MakeSectorOffsetChain( cfi, cfi.firstMiniStreamSectorId ); var next = startMiniSectorId; do { var n = next / cfi.miniStreamCountPerSector; var m = next % cfi.miniStreamCountPerSector; var offset = miniStreamSoc[(int)n] + (m * cfi.miniStreamSize); chain.Add(offset); var a = next / cfi.fatEntryCountPerSector; var b = next % cfi.fatEntryCountPerSector; var miniFatOffset = miniFatSoc[(int)a] + (b * 4); next = _ToU32(_ReadBytes(cfi.stream, miniFatOffset, 4)); } while (_IsRegulerSectorId(next)); return(chain); }
private static byte[] _ReadUserDefinedData( _CompoundFileInfo cfi, uint entryOffset) { var eo = entryOffset; var startSectorId = _ToU32(_ReadBytes(cfi.stream, eo + 0x0074, 4)); var streamSize = _ToI64(_ReadBytes(cfi.stream, eo + 0x0078, 8)); uint sectorSize; List <uint> chain; if (streamSize >= cfi.miniStreamSizeCutoff) { sectorSize = cfi.sectorSize; chain = _MakeSectorOffsetChain(cfi, startSectorId); } else { sectorSize = cfi.miniStreamSize; chain = _MakeMiniSectorOffsetChain(cfi, startSectorId); } var bytes = new byte[streamSize]; for (var n = 0; n < chain.Count; ++n) { var srcOffset = chain[n]; var dstOffset = n * sectorSize; var count = System.Math.Min(sectorSize, streamSize - dstOffset); cfi.stream.Position = srcOffset; cfi.stream.Read(bytes, (int)dstOffset, (int)count); } return(bytes); }
private static uint _GetFirstMiniStreamSectorId(_CompoundFileInfo cfi) { var rootEntryOffset = (cfi.firstDirectorySectorId + 1) * cfi.sectorSize; return(_ToU32(_ReadBytes(cfi.stream, rootEntryOffset + 0x0074, 4))); }
private static byte[] _ReadEncryptedPackage(_CompoundFileInfo cfi) { var offset = _FindDirectoryEntryOffset(cfi, "EncryptedPackage"); if (offset == 0) { return(null); } return(_ReadUserDefinedData(cfi, offset)); }
private static _EncryptionInfo _ReadEncryptionInfo( _CompoundFileInfo cfi) { var offset = _FindDirectoryEntryOffset(cfi, "EncryptionInfo"); if (offset == 0) { return(null); } var bytes = _ReadUserDefinedData(cfi, offset); return(new _EncryptionInfo(bytes)); }
internal static bool IsEncryptedFile(Stream stream) { if (!_IsCompoundFileFormat(stream)) { return(false); } var cfi = new _CompoundFileInfo(stream); var ei = _ReadEncryptionInfo(cfi); if (ei == null) { return(false); } return(true); }
private static List <uint> _MakeDifatOffsetChain(_CompoundFileInfo cfi) { var chain = new List <uint>(); chain.Add(0x004C); var next = _ToU32(_ReadBytes(cfi.stream, 0x0044, 4)); while (_IsRegulerSectorId(next)) { var offset = (next + 1) * cfi.sectorSize; chain.Add(offset); next = _ToU32(_ReadBytes( cfi.stream, offset + (cfi.sectorSize - 4), 4 )); } return(chain); }
private static List <uint> _MakeSectorOffsetChain( _CompoundFileInfo cfi, uint startSectorId) { var chain = new List <uint>(); if (!_IsRegulerSectorId(startSectorId)) { return(chain); } var next = startSectorId; do { var offset = (next + 1) * cfi.sectorSize; chain.Add(offset); var fatOffset = _FindFatSectorOffset(cfi, next); var n = 4 * (next % cfi.fatEntryCountPerSector); next = _ToU32(_ReadBytes(cfi.stream, fatOffset + n, 4)); } while (_IsRegulerSectorId(next)); return(chain); }
private static uint _FindDirectoryEntryOffset( _CompoundFileInfo cfi, string entryName) { var startSectorId = cfi.firstDirectorySectorId; var chain = _MakeSectorOffsetChain(cfi, startSectorId); var mCount = cfi.directoryEntryCountPerSector; var deSize = _CompoundFileInfo.DirectoryEntrySize; for (uint n = 0; n < chain.Count; ++n) { for (uint m = 0; m < mCount; ++m) { var offset = chain[(int)n] + (m * deSize); var bytes = _ReadBytes(cfi.stream, offset, 64); var name = _ReadNullTerminatedUnicodeString(bytes); if (name == entryName) { return(offset); } } } return(0); }
private static uint _FindFatSectorOffset( _CompoundFileInfo cfi, uint sectorId) { var decih = _CompoundFileInfo.DifatEntryCountInHeader; var decps = cfi.difatEntryCountPerSector; var difatEntryIndex = sectorId / cfi.fatEntryCountPerSector; uint n = 0; uint m = 0; if (difatEntryIndex < decih) { m = 4 * difatEntryIndex; } else { n = 1 + ((difatEntryIndex - decih) / decps); m = 4 * ((difatEntryIndex - decih) % decps); } var pos = cfi.difatOffsetChain[(int)n] + m; var fatSectorId = _ToU32(_ReadBytes(cfi.stream, pos, 4)); return((fatSectorId + 1) * cfi.sectorSize); }
internal static IEnumerator Decrypt( Stream stream, string password, Result result) { var startTicks = DateTime.Now.Ticks; System.Func <bool> keepControl = () => { var ticks = DateTime.Now.Ticks; if (startTicks < 0) { startTicks = ticks; } if (ticks - startTicks < MaxControlTicks) { return(true); } startTicks = -1; return(false); }; if (!_IsCompoundFileFormat(stream)) { result.error = "Invalid file format."; yield break; } var cfi = new _CompoundFileInfo(stream); var ei = _ReadEncryptionInfo(cfi); if (ei == null) { result.error = "EncryptionInfo not found."; yield break; } result.error = _VerifyEncryptionInfo(ei); if (!string.IsNullOrEmpty(result.error)) { yield break; } yield return(null); var hAlg = _CreateHashAlgorithmForKey(ei); byte[] hFinalPrev = null; foreach (var h in _GenerateHFinalPrev(hAlg, ei, password)) { hFinalPrev = h; if (!keepControl()) { yield return(null); } } yield return(null); var isSuccess = _VerifyEncryptionKey(hAlg, ei, hFinalPrev); if (!isSuccess) { result.error = "Password incorrect."; yield break; } var ep = _ReadEncryptedPackage(cfi); yield return(null); var ek = _MakeDataEncryptionKey(hAlg, ei, hFinalPrev); var bytes = new byte[ep.Length - 8]; var dec = _DecryptPackage(ei, ek, ep, bytes, 0).GetEnumerator(); while (dec.MoveNext()) { if (!keepControl()) { yield return(null); } } var streamSize = _ToI64(ep, 0); System.Array.Resize(ref bytes, (int)streamSize); result.bytes = bytes; }