// Decompiled with JetBrains decompiler // Type: Microsoft.InfoCards.FileDataSource // Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 // MVID: 1D4D5564-A025-490C-AF1D-DF4FBB709D1F // Assembly location: C:\Users\Administrateur\Downloads\Virusshare-00001-msil\Virus.Win32.Expiro.w-f8f9f26e940480624825f6bddbea86e70fc4aa746c4dd8efa7d98dcb477000ed.exe using Microsoft.InfoCards.Diagnostics; using System; using System.Collections; using System.ComponentModel; using System.IO; using System.Runtime.InteropServices; using System.Security.AccessControl; using System.Security.Cryptography; using System.Security.Principal; using System.Text; using System.Threading; namespace Microsoft.InfoCards { internal class FileDataSource : DataSource { public const int ENCRYPTIONKEYBUFFERSIZE = 32; public const int ENCRYPTIONKEYBITLENGTH = 256; public const int ENCRYPTIONBLOCKBUFFERSIZE = 16; public const int ENCRYPTIONBLOCKBITLENGTH = 128; public const int ENCRYPTIONITERATIONS = 1000; public const int INITIALINDEXITEMCOUNT = 20; public const int INITIALINDEXAREASIZE = 80; public const int INITIALBLOBAREASIZE = 2048; public const int FILEVERSION = 11; private static readonly SecurityIdentifier AdministratorSid = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, (SecurityIdentifier) null); private int m_variableSignatureLength = 64; private FileInfo m_fileInfo; private FileStream m_file; private FileInfo m_shadowInfo; private FileStream m_shadow; private byte[] m_header; private IndexedDataBuffer m_data; private SecondaryIndexList m_indexes; private ReaderWriterLock m_lock; private SymmetricAlgorithm m_encAlg; private byte[] m_key; private bool m_keyProtected; private WindowsIdentity m_identity; private bool m_currentTransactionDirty; private SafeRsaProviderHandle m_provider; protected FileDataSource() : base((string) null, (string) null) { } public FileDataSource(WindowsIdentity identity, string fileName) : this(identity, fileName, Guid.NewGuid().ToString("P"), SecondaryIndexDefinition.MasterIndexes) { } public FileDataSource( WindowsIdentity identity, string fileName, string instanceId, SecondaryIndexDefinition[] indexDefinitions) : base(instanceId, fileName) { this.m_identity = identity; this.m_currentTransactionDirty = false; this.m_fileInfo = new FileInfo(fileName); this.m_shadowInfo = new FileInfo(this.m_fileInfo.FullName + ".shadow"); this.m_lock = new ReaderWriterLock(); this.m_indexes = new SecondaryIndexList(indexDefinitions); this.m_encAlg = FileDataSource.CreateEncryptionAlg(); this.SetupProvider(); } public IndexedDataBuffer Buffer { get { this.ThrowIfDisposed(); this.ThrowIfNotLoaded(); return this.m_data; } } public byte[] Header { get { this.ThrowIfDisposed(); this.ThrowIfNotLoaded(); return this.m_header; } } public SecondaryIndexList Indexes { get { this.ThrowIfDisposed(); this.ThrowIfNotLoaded(); return this.m_indexes; } } protected WindowsIdentity Identity => this.m_identity; protected internal override void OnClear() { using (new SystemIdentity(true)) { FileDataSource.ResilientDelete(this.m_fileInfo); FileDataSource.ResilientDelete(this.m_shadowInfo); } } protected internal override void OnLoad() { this.ThrowIfDisposed(); try { this.CreateDirAndFiles(); if (this.m_shadow.Length > 0L) { if (this.m_file.Length > 0L) { this.m_shadow.SetLength(0L); this.LoadFrom((Stream) this.m_file); } else { this.LoadFrom((Stream) this.m_shadow); this.FlushToShadow(); this.SwapFileWithShadow(); } } else if (this.m_file.Length > 0L) { this.LoadFrom((Stream) this.m_file); } else { this.CreateEmptyStore(); this.FlushToShadow(); this.SwapFileWithShadow(); } this.m_file.Seek(0L, SeekOrigin.Begin); } catch { this.CloseFiles(); throw; } } private void CloseFiles() { using (new SystemIdentity(false)) { if (this.m_file != null) { this.m_file.Close(); this.m_file = (FileStream) null; } if (this.m_shadow == null) return; this.m_shadow.Close(); this.m_shadow = (FileStream) null; } } protected void CreateDirAndFiles() { this.CheckReparsePoints(); if (NativeMcppMethods.PathSupportsPersistedSecurity(this.m_fileInfo.Directory.FullName)) this.ValidateDirectoryAccess(); using (new SystemIdentity(true)) { try { if (!this.m_fileInfo.Directory.Exists) { try { if (NativeMcppMethods.PathSupportsPersistedSecurity(this.m_fileInfo.Directory.FullName)) this.m_fileInfo.Directory.Create(FileDataSource.CreateSecurityDescriptor()); else this.m_fileInfo.Directory.Create(); this.m_fileInfo.Directory.Attributes |= FileAttributes.Hidden | FileAttributes.NotContentIndexed; } catch (UnauthorizedAccessException ex) { throw InfoCardTrace.ThrowHelperError((Exception) new DataAccessException(ex.Message)); } } else if (NativeMcppMethods.PathSupportsPersistedSecurity(this.m_fileInfo.Directory.FullName) && this.LogIfAclsTampered((FileSystemInfo) this.m_fileInfo.Directory)) this.m_fileInfo.Directory.SetAccessControl(FileDataSource.CreateSecurityDescriptor()); InfoCardTrace.Assert(this.m_shadowInfo.Directory.Exists, "m_shadowInfo directory should be same as main directory"); this.OpenOrCreateHelper(this.m_fileInfo, out this.m_file); this.OpenOrCreateHelper(this.m_shadowInfo, out this.m_shadow); } catch (IOException ex) { throw InfoCardTrace.ThrowHelperError((Exception) new DataAccessException(ex.Message)); } } } private void CheckReparsePoints() { using (new SystemIdentity(true)) { for (DirectoryInfo directoryInfo = this.m_fileInfo.Directory; directoryInfo != null; directoryInfo = directoryInfo.Parent) { if (directoryInfo.Exists && (directoryInfo.Attributes & FileAttributes.ReparsePoint) != (FileAttributes) 0) throw InfoCardTrace.ThrowHelperError((Exception) new DataAccessException(SR.GetString("StoreNoReparsePointAllowed"))); } if (Directory.Exists(this.m_fileInfo.FullName) && (this.m_fileInfo.Attributes & FileAttributes.ReparsePoint) != (FileAttributes) 0) throw InfoCardTrace.ThrowHelperError((Exception) new DataAccessException(SR.GetString("StoreNoReparsePointAllowed"))); } } private void ValidateDirectoryAccess() { InfoCardTrace.Assert(!WindowsIdentity.GetCurrent().IsSystem, "Should not be running as system"); IdentityReference identityReference = WindowsIdentity.GetCurrent().User.Translate(typeof (NTAccount)); bool flag = false; DirectoryInfo parent = this.m_fileInfo.Directory.Parent; if (parent.Exists) { foreach (FileSystemAccessRule accessRule in (ReadOnlyCollectionBase) parent.GetAccessControl().GetAccessRules(true, true, typeof (NTAccount))) { if (accessRule.IdentityReference == identityReference && accessRule.FileSystemRights == FileSystemRights.FullControl && accessRule.AccessControlType == AccessControlType.Allow) { flag = true; break; } } } if (!flag) throw InfoCardTrace.ThrowHelperError((Exception) new DataAccessException(SR.GetString("StoreInvalidDataFilePath"))); } private void OpenOrCreateHelper(FileInfo theFile, out FileStream fileStream) { InfoCardTrace.Assert(WindowsIdentity.GetCurrent().IsSystem, "Should be running as system"); if (!File.Exists(theFile.FullName)) { fileStream = FileDataSource.ResilientOpen(theFile, FileMode.CreateNew, FileAccess.ReadWrite); theFile.Attributes |= FileAttributes.Hidden | FileAttributes.NotContentIndexed; theFile.SetAccessControl(FileDataSource.CreateSecurityDescriptor()); } else { if (NativeMcppMethods.PathSupportsPersistedSecurity(this.m_fileInfo.Directory.FullName) && this.LogIfAclsTampered((FileSystemInfo) theFile)) { theFile.SetAccessControl(FileDataSource.CreateSecurityDescriptor()); theFile.Attributes |= FileAttributes.Hidden | FileAttributes.NotContentIndexed; } fileStream = FileDataSource.ResilientOpen(theFile, FileMode.Open, FileAccess.ReadWrite); } } protected virtual void OnSwapFileWithShadow() { using (new SystemIdentity(true)) { string fullName = this.m_fileInfo.FullName; FileDataSource.ResilientDelete(this.m_fileInfo); FileDataSource.ResilientMove(this.m_shadowInfo, this.m_fileInfo); this.m_fileInfo = new FileInfo(fullName); this.m_shadowInfo = new FileInfo(fullName + ".shadow"); } } protected internal override void OnClose() { this.ThrowIfDisposed(); if (this.m_data != null) { this.m_data.Close(); this.m_data = (IndexedDataBuffer) null; } this.m_indexes.Close(); this.CloseFiles(); this.m_provider.Dispose(); } protected internal override DataRow ReadRow(int localId, QueryDetails details) { DataRow row = (DataRow) null; if (QueryDetails.Header == (details & QueryDetails.Header)) { row = this.m_data.CreateDataRow(localId); if (QueryDetails.DataBlob == (details & QueryDetails.DataBlob)) { byte[] iv = this.AllocateIvBuffer(); this.m_data.CopyIVFromObject(localId, iv, 0); using (Stream streamForObjectData = this.m_data.GetStreamForObjectData(localId)) { using (MemoryStream output = new MemoryStream((int) streamForObjectData.Length)) { this.DecryptData(iv, streamForObjectData, (Stream) output); row.SetDataField(output.ToArray()); byte[] buffer = output.GetBuffer(); Array.Clear((Array) buffer, 0, buffer.Length); } } } if (QueryDetails.IndexData == (details & QueryDetails.IndexData)) this.m_indexes.PopulateRowIndexBuffer(row); } return row; } protected internal override bool SingleMatch(QueryParameter match, LocalIdCollection localIds) { this.ThrowIfDisposed(); this.ThrowIfNotLoaded(); if (localIds == null) throw InfoCardTrace.ThrowHelperArgumentNull(nameof (localIds)); if (match == null) throw InfoCardTrace.ThrowHelperArgumentNull(nameof (match)); if (string.IsNullOrEmpty(match.IndexName)) throw InfoCardTrace.ThrowHelperError((Exception) new ArgumentException(SR.GetString("StoreDataSourceInvalidIndexName", (object) match.IndexName), nameof (match))); bool flag = false; try { try { } finally { this.m_lock.AcquireReaderLock(0); flag = true; } return this.m_indexes.Match(match, localIds); } finally { if (flag) this.m_lock.ReleaseReaderLock(); } } protected internal override void OnBeginTransaction() { InfoCardTrace.Assert(!this.m_currentTransactionDirty, "m_currentTransactionDirty should have been set to false before beginning a transaction"); base.OnBeginTransaction(); } protected internal override void OnRollbackTransaction() { try { base.OnRollbackTransaction(); this.LoadFrom((Stream) this.m_file); } finally { this.m_currentTransactionDirty = false; } } protected internal override void OnCommitTransaction() { try { base.OnCommitTransaction(); if (!this.m_currentTransactionDirty) return; this.FlushToShadow(); this.SwapFileWithShadow(); } finally { this.m_currentTransactionDirty = false; } } protected internal override void WriteRow(DataRow row) { this.ThrowIfDisposed(); this.ThrowIfNotLoaded(); this.ThrowIfWriteLockNotHeld(); if (row == null) throw InfoCardTrace.ThrowHelperArgumentNull(nameof (row)); bool flag = false; try { try { } finally { this.m_lock.AcquireWriterLock(0); flag = true; } using (MemoryStream output = new MemoryStream()) { this.m_encAlg.GenerateIV(); byte[] iv = this.m_encAlg.IV; using (MemoryStream input = new MemoryStream(row.GetDataField())) { this.EncryptData(iv, (Stream) input, (Stream) output); int localId = this.m_data.WriteObject(row.LocalId, iv, output.ToArray(), row.ObjectType, row.LastChange, row.GlobalId); this.m_indexes.SetValuesForId(localId, row.IndexBuffer, true); row.SourceId = this.SourceId; row.InstanceId = this.InstanceId; row.LocalId = localId; } } } finally { if (flag) this.m_lock.ReleaseWriterLock(); } this.m_currentTransactionDirty = true; } protected internal override void RemoveObject(int id) { if ((uint) id > (uint) (this.m_data.Index.Length / 4 - 1)) throw InfoCardTrace.ThrowHelperError((Exception) new ArgumentOutOfRangeException(nameof (id), (object) id, SR.GetString("StoreDataSourceIdOutOfRange"))); bool flag = false; try { try { } finally { this.m_lock.AcquireWriterLock(0); flag = true; } this.m_data.RemoveObject(id); this.m_indexes.RemoveAllValuesForId(id); } finally { if (flag) this.m_lock.ReleaseWriterLock(); } this.m_currentTransactionDirty = true; } private void ProtectKey() { if (this.m_keyProtected) throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreKeyAlreadyProtected"))); ProtectedMemory.Protect(this.m_key, MemoryProtectionScope.SameProcess); this.m_keyProtected = true; } private void UnprotectKey() { if (!this.m_keyProtected) throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreKeyNotAlreadyProtected"))); ProtectedMemory.Unprotect(this.m_key, MemoryProtectionScope.SameProcess); this.m_keyProtected = false; } private unsafe void DecryptData(byte[] iv, Stream input, Stream output) { InfoCardTrace.Assert(input is MemoryStream, "Invalid stream type"); if (iv == null || iv.Length == 0) throw InfoCardTrace.ThrowHelperArgumentNull(nameof (iv)); if (input == null) throw InfoCardTrace.ThrowHelperArgumentNull(nameof (input)); if (output == null) throw InfoCardTrace.ThrowHelperArgumentNull(nameof (output)); using (SafeCryptoKey safeCryptoKey = new SafeCryptoKey(this.m_provider, this.m_key, iv)) { byte[] buffer = new byte[input.Length]; input.Seek(0L, SeekOrigin.Begin); input.Read(buffer, 0, (int) input.Length); uint length = (uint) buffer.Length; fixed (byte* data = &buffer[0]) { if (!NativeMethods.CryptDecrypt(safeCryptoKey.Handle, IntPtr.Zero, 1U, 0U, (IntPtr) (void*) data, ref length)) { Exception e = (Exception) new Win32Exception(Marshal.GetLastWin32Error()); Array.Clear((Array) buffer, 0, buffer.Length); InfoCardTrace.TraceAndLogException(e); throw InfoCardTrace.ThrowHelperError(e); } } output.Write(buffer, 0, (int) length); } } private unsafe void EncryptData(byte[] iv, Stream input, Stream output) { if (iv == null || iv.Length == 0) throw InfoCardTrace.ThrowHelperArgumentNull(nameof (iv)); if (input == null) throw InfoCardTrace.ThrowHelperArgumentNull(nameof (input)); if (output == null) throw InfoCardTrace.ThrowHelperArgumentNull(nameof (output)); using (SafeCryptoKey safeCryptoKey = new SafeCryptoKey(this.m_provider, this.m_key, iv)) { byte[] buffer = new byte[input.Length + (long) this.m_key.Length]; input.Seek(0L, SeekOrigin.Begin); input.Read(buffer, 0, (int) input.Length); uint length = (uint) input.Length; fixed (byte* data = &buffer[0]) { if (!NativeMethods.CryptEncrypt(safeCryptoKey.Handle, IntPtr.Zero, 1U, 0U, (IntPtr) (void*) data, ref length, (uint) buffer.Length)) { Exception e = (Exception) new Win32Exception(Marshal.GetLastWin32Error()); InfoCardTrace.TraceAndLogException(e); throw InfoCardTrace.ThrowHelperError(e); } } output.Write(buffer, 0, (int) length); } } private unsafe void CreateEmptyStore() { this.m_data = new IndexedDataBuffer(new byte[80], new byte[2048], 0, (DataSource) this); this.m_encAlg.GenerateKey(); this.m_key = new byte[this.m_encAlg.Key.Length]; Array.Copy((Array) this.m_encAlg.Key, 0, (Array) this.m_key, 0, this.m_encAlg.Key.Length); this.m_encAlg.GenerateKey(); this.m_keyProtected = false; this.ProtectKey(); this.m_header = new byte[this.GetTotalHeaderSize()]; fixed (byte* numPtr = &this.m_header[this.GetOffsetToEncryptedFileHeader()]) ((EncryptedFileStoreHeader*) numPtr)->Version = 11U; this.EncryptAndSaveDPAPIKeyToHeader(); } private void FlushToShadow() => this.FlushToStream((Stream) this.m_shadow); private int GetTotalHeaderSize() => sizeof (EncryptedFileStoreHeader) + this.GetTotalSignatureSize(); private int GetOffsetToEncryptedFileHeader() => this.m_variableSignatureLength + 4; private int GetTotalSignatureSize() => this.GetOffsetToEncryptedFileHeader(); private long GetRequiredFileSize() { long num = Convert.ToInt64(this.GetTotalHeaderSize()) + Convert.ToInt64(this.m_data.DataLength) + Convert.ToInt64(this.m_data.Index.Length + 4); foreach (string key in (IEnumerable) this.m_indexes.InnerIndexes.Keys) { byte[] buffer = ((SecondaryIndex) this.m_indexes.InnerIndexes[(object) key]).GetBuffer(); num += Convert.ToInt64(8 + buffer.Length); } return num + num / 20L; } private unsafe void FlushToStream(Stream stream) { if (stream == null) throw InfoCardTrace.ThrowHelperArgumentNull(nameof (stream)); stream.SetLength(this.GetRequiredFileSize()); BinaryWriter binaryWriter1 = new BinaryWriter(stream); this.m_encAlg.GenerateIV(); byte[] iv = this.m_encAlg.IV; int dataLength = this.m_data.DataLength; stream.Seek((long) this.GetTotalHeaderSize(), SeekOrigin.Begin); binaryWriter1.Write(iv); long position = stream.Position; using (BinaryWriter binaryWriter2 = new BinaryWriter((Stream) new MemoryStream())) { binaryWriter2.Write(this.m_data.Index.Length / 4); binaryWriter2.Write(this.m_data.Index); binaryWriter2.Write(this.m_indexes.Count); foreach (string key in (IEnumerable) this.m_indexes.InnerIndexes.Keys) { SecondaryIndex innerIndex = (SecondaryIndex) this.m_indexes.InnerIndexes[(object) key]; int lastIndex = innerIndex.LastIndex; binaryWriter2.Write(lastIndex); int initialSize = SecondaryIndexDefinition.GetByName(key).InitialSize; if (lastIndex + 1 < initialSize) { binaryWriter2.Write(initialSize); InfoCardTrace.Assert(initialSize * sizeof (SecondaryIndexItem) <= innerIndex.GetBuffer().Length, "Buffer length is at least min capacity"); binaryWriter2.Write(innerIndex.GetBuffer(), 0, initialSize * sizeof (SecondaryIndexItem)); } else { binaryWriter2.Write(lastIndex + 1); binaryWriter2.Write(innerIndex.GetBuffer(), 0, (lastIndex + 1) * sizeof (SecondaryIndexItem)); } } binaryWriter2.Flush(); binaryWriter2.Seek(0, SeekOrigin.Begin); this.EncryptData(iv, binaryWriter2.BaseStream, binaryWriter1.BaseStream); } int int32 = Convert.ToInt32(stream.Position - position); int num = int32 + this.m_data.DataLength + this.GetTotalHeaderSize() + iv.Length; binaryWriter1.Write(this.m_data.Data, 0, this.m_data.DataLength); stream.Seek(0L, SeekOrigin.Begin); binaryWriter1.Flush(); fixed (byte* numPtr = &this.m_header[this.GetOffsetToEncryptedFileHeader()]) { ((EncryptedFileStoreHeader*) numPtr)->DataSize = dataLength; ((EncryptedFileStoreHeader*) numPtr)->Version = 11U; ((EncryptedFileStoreHeader*) numPtr)->Size = num; ((EncryptedFileStoreHeader*) numPtr)->IndexSize = int32; } binaryWriter1.Write(this.m_header); stream.SetLength(Convert.ToInt64(num)); binaryWriter1.Flush(); this.SignStream(stream); } private unsafe void SignStream(Stream input) { long offset = input != null ? input.Position : throw InfoCardTrace.ThrowHelperArgumentNull(nameof (input)); this.m_encAlg.GenerateIV(); byte[] sourceArray = this.SignDigest(this.m_encAlg.IV, this.CreateStreamDigest(input)); byte[] numArray = new byte[this.GetTotalSignatureSize()]; fixed (byte* numPtr = &numArray[0]) ((SignatureHeader*) numPtr)->SignatureSize = this.m_variableSignatureLength; Array.Copy((Array) sourceArray, 0, (Array) numArray, 4, sourceArray.Length); input.Seek(0L, SeekOrigin.Begin); input.Write(numArray, 0, numArray.Length); InfoCardTrace.Assert(this.m_variableSignatureLength >= sourceArray.Length, "Generated signature should be less than signature length"); input.Seek(offset, SeekOrigin.Begin); } private byte[] CreateStreamDigest(Stream input) { input.Seek((long) this.GetOffsetToEncryptedFileHeader(), SeekOrigin.Begin); byte[] data = new byte[Convert.ToInt32((input.Length / 4096L + 1L) * (long) HashUtility.HashBufferLength)]; int dataIndex = 0; byte[] numArray = new byte[4096]; int dataToHashSize; do { dataToHashSize = input.Read(numArray, 0, numArray.Length); if (dataToHashSize > 0) { HashUtility.SetHashValue(data, dataIndex, numArray, 0, dataToHashSize); dataIndex += HashUtility.HashBufferLength; } } while (dataToHashSize == numArray.Length); return data; } private byte[] SignDigest(byte[] iv, byte[] digest) { byte[] destinationArray = new byte[this.m_variableSignatureLength]; using (MemoryStream input = new MemoryStream(digest)) { using (MemoryStream output = new MemoryStream(digest.Length)) { this.EncryptData(iv, (Stream) input, (Stream) output); Array.Copy((Array) output.GetBuffer(), Convert.ToInt32(output.Position - 1L) - iv.Length, (Array) destinationArray, 0, iv.Length); Array.Copy((Array) iv, 0, (Array) destinationArray, iv.Length, iv.Length); return destinationArray; } } } private void ValidateSignature(Stream input) { long offset = input != null ? input.Position : throw InfoCardTrace.ThrowHelperArgumentNull(nameof (input)); byte[] buffer = new byte[this.m_variableSignatureLength]; byte[] numArray1 = this.AllocateIvBuffer(); input.Seek(20L, SeekOrigin.Begin); input.Read(numArray1, 0, numArray1.Length); byte[] numArray2 = this.SignDigest(numArray1, this.CreateStreamDigest(input)); input.Seek(4L, SeekOrigin.Begin); input.Read(buffer, 0, buffer.Length); for (int index = 0; index < buffer.Length; ++index) { if ((int) buffer[index] != (int) numArray2[index]) throw InfoCardTrace.ThrowHelperError((Exception) new CorruptStoreException(SR.GetString("StoreSignatureNotValid"))); } input.Seek(offset, SeekOrigin.Begin); } protected unsafe void LoadFrom(Stream stream) { if (stream == null) throw InfoCardTrace.ThrowHelperArgumentNull(nameof (stream)); stream.Seek(0L, SeekOrigin.Begin); BinaryReader binaryReader1 = (BinaryReader) new InfoCardBinaryReader(stream); this.m_header = new byte[this.GetTotalHeaderSize()]; binaryReader1.Read(this.m_header, 0, this.m_header.Length); fixed (byte* numPtr1 = &this.m_header[this.GetOffsetToEncryptedFileHeader()]) { if (11U != ((EncryptedFileStoreHeader*) numPtr1)->Version) { CorruptStoreException e = new CorruptStoreException(SR.GetString("StoreVersionNotSupported", (object) ((EncryptedFileStoreHeader*) numPtr1)->Version)); InfoCardTrace.TraceAndLogException((Exception) e); throw InfoCardTrace.ThrowHelperError((Exception) e); } // ISSUE: __unpin statement __unpin(numPtr1); fixed (byte* numPtr2 = &this.m_header[0]) { if (this.m_variableSignatureLength != ((SignatureHeader*) numPtr2)->SignatureSize) throw InfoCardTrace.ThrowHelperError((Exception) new CorruptStoreException(SR.GetString("StoreSignatureNotValid"))); } this.ObtainDataKeyFromHeader(); this.ValidateSignature(stream); fixed (byte* numPtr3 = &this.m_header[this.GetOffsetToEncryptedFileHeader()]) { byte[] numArray = this.AllocateIvBuffer(); byte[] masterIndex; using (MemoryStream output = new MemoryStream()) { binaryReader1.Read(numArray, 0, numArray.Length); byte[] buffer1 = binaryReader1.ReadBytes(((EncryptedFileStoreHeader*) numPtr3)->IndexSize); using (MemoryStream input = new MemoryStream(buffer1)) { this.DecryptData(numArray, (Stream) input, (Stream) output); Array.Clear((Array) buffer1, 0, buffer1.Length); } output.Seek(0L, SeekOrigin.Begin); BinaryReader binaryReader2 = (BinaryReader) new InfoCardBinaryReader((Stream) output); int num1 = binaryReader2.ReadInt32(); InfoCardTrace.Assert(num1 > 0, "MasterIndexCount Invalid"); masterIndex = binaryReader2.ReadBytes(num1 * 4); InfoCardTrace.Assert((uint) binaryReader2.ReadInt32() <= (uint) this.m_indexes.Count, "SecondaryIndexCount Invalid"); foreach (string key in (IEnumerable) this.m_indexes.InnerIndexes.Keys) { int lastIndex = binaryReader2.ReadInt32(); int num2 = binaryReader2.ReadInt32(); byte[] buffer2 = new byte[Utility.CalculateIncreaseByPercent(num2 * sizeof (SecondaryIndexItem), sizeof (SecondaryIndexItem), SecondaryIndexDefinition.GetByName(key).GrowthFactor)]; binaryReader2.Read(buffer2, 0, num2 * sizeof (SecondaryIndexItem)); this.m_indexes.SetBuffer(key, buffer2, lastIndex); } } using (MemoryStream memoryStream = new MemoryStream(Utility.CalculateIncreaseByPercent(Convert.ToInt32(binaryReader1.BaseStream.Length - binaryReader1.BaseStream.Position), 1, 5))) { byte[] buffer3 = new byte[256]; int num = 0; int count; do { count = binaryReader1.Read(buffer3, 0, buffer3.Length); memoryStream.Write(buffer3, 0, count); num += count; } while (count == buffer3.Length); byte[] buffer4 = memoryStream.GetBuffer(); if (num == 0) buffer4 = new byte[2048]; this.m_data = new IndexedDataBuffer(masterIndex, buffer4, ((EncryptedFileStoreHeader*) numPtr3)->DataSize, (DataSource) this); } } } } protected virtual void SwapFileWithShadow() { this.CloseFiles(); this.OnSwapFileWithShadow(); try { this.CreateDirAndFiles(); } catch { this.CloseFiles(); throw; } } private unsafe void EncryptAndSaveDPAPIKeyToHeader() { DataBlob dataBlob1 = new DataBlob(); DataBlob dataBlob2 = new DataBlob(); byte[] numArray = new byte[32 + HashUtility.HashBufferLength]; this.UnprotectKey(); try { Array.Copy((Array) this.m_key, 0, (Array) numArray, 0, 32); HashUtility.SetHashValue(numArray, 32, this.m_key, 0, 32); fixed (byte* numPtr1 = &numArray[0]) { DataBlob dataBlob3; dataBlob3.pbData = new IntPtr((void*) numPtr1); dataBlob3.cbData = numArray.Length; try { if (!NativeMethods.CryptProtectData(new IntPtr((void*) &dataBlob3), (string) null, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 65, new IntPtr((void*) &dataBlob1))) throw InfoCardTrace.ThrowHelperError((Exception) new Win32Exception(Marshal.GetLastWin32Error(), SR.GetString("StoreCryptProtectDataFailed"))); using (new SystemIdentity(true)) { if (!NativeMethods.CryptProtectData(new IntPtr((void*) &dataBlob1), (string) null, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 65, new IntPtr((void*) &dataBlob2))) throw InfoCardTrace.ThrowHelperError((Exception) new Win32Exception(Marshal.GetLastWin32Error(), SR.GetString("StoreCryptProtectDataAsSystemFailed"))); } InfoCardTrace.Assert(dataBlob2.cbData <= 512, "The size of the encrypted data is larger than EncryptedKeyBlockSize"); fixed (byte* numPtr2 = &this.m_header[this.GetOffsetToEncryptedFileHeader()]) { ((EncryptedFileStoreHeader*) numPtr2)->KeyBlock.KeyType = 0; ((EncryptedFileStoreHeader*) numPtr2)->KeyBlock.EncryptedKeySize = dataBlob2.cbData; byte* numPtr3 = &((EncryptedFileStoreHeader*) numPtr2)->KeyBlock.EncryptedKey; for (int index = 0; index < dataBlob2.cbData; ++index) numPtr3[index] = *(byte*) ((IntPtr) dataBlob2.pbData.ToPointer() + index); if (dataBlob2.cbData >= 512) return; Utility.ClearUnsafeMemory(new IntPtr((void*) (numPtr3 + dataBlob2.cbData)), 512 - dataBlob2.cbData); } } finally { Exception e = (Exception) null; if (IntPtr.Zero != dataBlob1.pbData) { Utility.ClearUnsafeMemory(dataBlob1.pbData, dataBlob1.cbData); if (IntPtr.Zero != NativeMethods.LocalFree(dataBlob1.pbData)) e = (Exception) new Win32Exception(Marshal.GetLastWin32Error()); } if (IntPtr.Zero != dataBlob2.pbData) { Utility.ClearUnsafeMemory(dataBlob2.pbData, dataBlob2.cbData); if (IntPtr.Zero != NativeMethods.LocalFree(dataBlob2.pbData)) e = (Exception) new Win32Exception(Marshal.GetLastWin32Error()); } if (e != null) throw InfoCardTrace.ThrowHelperError(e); } } } finally { this.ProtectKey(); Array.Clear((Array) numArray, 0, numArray.Length); } } private void ObtainDataKeyFromHeader() { try { this.m_key = this.TryObtainDataKeyFromDPAPI() ?? throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreUnableToGetStoreKeyFromDPAPI"))); this.m_keyProtected = false; this.ProtectKey(); } catch (Exception ex) { if (!InfoCardTrace.IsFatal(ex)) throw InfoCardTrace.ThrowHelperError((Exception) new InvalidStoreProtectionKeyException()); throw; } } private unsafe byte[] TryObtainDataKeyFromDPAPI() { DataBlob dataBlob1 = new DataBlob(); DataBlob dataBlob2 = new DataBlob(); fixed (byte* numPtr = &this.m_header[this.GetOffsetToEncryptedFileHeader()]) { if (((EncryptedFileStoreHeader*) numPtr)->KeyBlock.KeyType != 0) throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreFileNotProtectedWithDPAPI"))); byte[] dataKeyFromDpapi = (byte[]) null; DataBlob dataBlob3; dataBlob3.pbData = new IntPtr((void*) &((EncryptedFileStoreHeader*) numPtr)->KeyBlock.EncryptedKey); dataBlob3.cbData = ((EncryptedFileStoreHeader*) numPtr)->KeyBlock.EncryptedKeySize; try { using (new SystemIdentity(true)) { if (!NativeMethods.CryptUnprotectData(new IntPtr((void*) &dataBlob3), (StringBuilder) null, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 1, new IntPtr((void*) &dataBlob2))) throw InfoCardTrace.ThrowHelperError((Exception) new Win32Exception(Marshal.GetLastWin32Error(), SR.GetString("StoreCryptUnprotectDataAsSystemFailed"))); } if (!NativeMethods.CryptUnprotectData(new IntPtr((void*) &dataBlob2), (StringBuilder) null, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 1, new IntPtr((void*) &dataBlob1))) throw InfoCardTrace.ThrowHelperError((Exception) new Win32Exception(Marshal.GetLastWin32Error(), SR.GetString("StoreCryptUnprotectDataFailed"))); InfoCardTrace.Assert(dataBlob1.cbData == 32 + HashUtility.HashBufferLength, "The data size returned by CryptUnprotectData is invalid or corrupt."); dataKeyFromDpapi = new byte[32]; Marshal.Copy(dataBlob1.pbData, dataKeyFromDpapi, 0, 32); byte[] data = new byte[HashUtility.HashBufferLength]; HashUtility.SetHashValue(data, 0, dataKeyFromDpapi, 0, 32); for (int index = 0; index < data.Length; ++index) { if ((int) data[index] != (int) *(byte*) ((IntPtr) dataBlob1.pbData.ToPointer() + (32 + index))) throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreDecryptedKeyIsNotValid"))); } return dataKeyFromDpapi; } catch { if (dataKeyFromDpapi != null) Array.Clear((Array) dataKeyFromDpapi, 0, dataKeyFromDpapi.Length); throw; } finally { if (IntPtr.Zero != dataBlob2.pbData) { Utility.ClearUnsafeMemory(dataBlob2.pbData, dataBlob2.cbData); NativeMethods.LocalFree(dataBlob2.pbData); } if (IntPtr.Zero != dataBlob1.pbData) { Utility.ClearUnsafeMemory(dataBlob1.pbData, dataBlob1.cbData); NativeMethods.LocalFree(dataBlob1.pbData); } } } } private bool LogIfAclsTampered(FileSystemInfo fileSysInfo) { bool condition = true; try { FileSystemSecurity accessControl; if (fileSysInfo is DirectoryInfo) { accessControl = (FileSystemSecurity) ((DirectoryInfo) fileSysInfo).GetAccessControl(AccessControlSections.Access | AccessControlSections.Owner); } else { InfoCardTrace.Assert(fileSysInfo is FileInfo, "Only fileinfo possible"); accessControl = (FileSystemSecurity) ((FileInfo) fileSysInfo).GetAccessControl(AccessControlSections.Access | AccessControlSections.Owner); } condition = this.LogIfAclsTamperedHelper(accessControl); } catch (UnauthorizedAccessException ex) { InfoCardTrace.Assert(condition, "ACL must have been tampered with"); } if (condition) InfoCardTrace.TraceAndLogException((Exception) new DataAccessException(SR.GetString("StoreAclsTamperedWith"))); return condition; } private bool LogIfAclsTamperedHelper(FileSystemSecurity fs) { if (SystemIdentity.LsaIdentityReference != fs.GetOwner(typeof (SecurityIdentifier))) return true; AuthorizationRuleCollection accessRules = fs.GetAccessRules(true, true, typeof (SecurityIdentifier)); bool flag = fs is DirectorySecurity; foreach (FileSystemAccessRule systemAccessRule in (ReadOnlyCollectionBase) accessRules) { if ((!(SystemIdentity.LsaIdentityReference == systemAccessRule.IdentityReference) || FileSystemRights.FullControl != systemAccessRule.FileSystemRights || systemAccessRule.AccessControlType != AccessControlType.Allow) && (!flag || !((IdentityReference) FileDataSource.AdministratorSid == systemAccessRule.IdentityReference) || systemAccessRule.AccessControlType != AccessControlType.Allow || (FileSystemRights.ReadData | FileSystemRights.DeleteSubdirectoriesAndFiles | FileSystemRights.Synchronize) != systemAccessRule.FileSystemRights)) return true; } return false; } private static T CreateSecurityDescriptor() where T : FileSystemSecurity, new() { T securityDescriptor = new T(); securityDescriptor.SetOwner(SystemIdentity.LsaIdentityReference); foreach (FileSystemAccessRule accessRule in (ReadOnlyCollectionBase) securityDescriptor.GetAccessRules(true, true, typeof (SecurityIdentifier))) securityDescriptor.RemoveAccessRuleAll(accessRule); securityDescriptor.AddAccessRule(new FileSystemAccessRule(SystemIdentity.LsaIdentityReference, FileSystemRights.FullControl, InheritanceFlags.None, PropagationFlags.None, AccessControlType.Allow)); if ((object) securityDescriptor is DirectorySecurity) securityDescriptor.AddAccessRule(new FileSystemAccessRule((IdentityReference) FileDataSource.AdministratorSid, FileSystemRights.ReadData | FileSystemRights.DeleteSubdirectoriesAndFiles, AccessControlType.Allow)); securityDescriptor.SetAccessRuleProtection(true, false); return securityDescriptor; } private void SetupProvider() => this.m_provider = SafeRsaProviderHandle.Construct(); private byte[] AllocateIvBuffer() { InfoCardTrace.Assert(16 == this.m_encAlg.IV.Length, "Must be equal"); InfoCardTrace.Assert(16 == this.m_encAlg.IV.Length, "Must be equal"); return new byte[this.m_encAlg.IV.Length]; } private static void ResilientDelete(FileInfo toDelete) { int millisecondsTimeout = 10; bool flag = true; Exception inner = (Exception) null; do { if (!flag) { Thread.Sleep(millisecondsTimeout); millisecondsTimeout *= 2; } try { toDelete.Delete(); flag = true; } catch (IOException ex) { inner = (Exception) ex; flag = false; } } while (!flag && millisecondsTimeout <= 500); if (!flag) throw InfoCardTrace.ThrowHelperError((Exception) new DataAccessException(SR.GetString("StoreFileInUse"), inner)); } private static void ResilientMove(FileInfo fileFrom, FileInfo fileTo) { int millisecondsTimeout = 10; bool flag = true; do { if (!flag) { Thread.Sleep(millisecondsTimeout); millisecondsTimeout *= 2; } try { fileFrom.MoveTo(fileTo.FullName); flag = true; } catch (IOException ex) { flag = false; } } while (!flag && millisecondsTimeout <= 500); if (flag) return; InfoCardTrace.FailFast(SR.GetString("StoreFileInUse")); } private static FileStream ResilientOpen( FileInfo toOpen, FileMode mode, FileAccess access) { int millisecondsTimeout = 10; bool flag = true; Exception inner = (Exception) null; FileStream fileStream = (FileStream) null; do { if (!flag) { Thread.Sleep(millisecondsTimeout); millisecondsTimeout *= 2; } try { fileStream = toOpen.Open(mode, access, FileShare.None); flag = true; } catch (IOException ex) { inner = (Exception) ex; flag = false; } } while (!flag && millisecondsTimeout <= 500); if (!flag) throw InfoCardTrace.ThrowHelperError((Exception) new DataAccessException(SR.GetString("StoreFileInUse"), inner)); return fileStream; } internal static SymmetricAlgorithm CreateEncryptionAlg() { RijndaelManaged encryptionAlg = new RijndaelManaged(); encryptionAlg.Mode = CipherMode.CBC; encryptionAlg.KeySize = 256; encryptionAlg.BlockSize = 128; return (SymmetricAlgorithm) encryptionAlg; } } }