public override void AnalyzePortableExecutableAndPdb(BinaryAnalyzerContext context) { PEBinary target = context.PEBinary(); Pdb pdb = target.Pdb; Dictionary <string, TruncatedCompilandRecordList> vulnerabilityToModules = new Dictionary <string, TruncatedCompilandRecordList>(); TruncatedCompilandRecordList moduleList; foreach (DisposableEnumerableView <Symbol> omView in pdb.CreateObjectModuleIterator()) { Symbol om = omView.Value; ObjectModuleDetails details = om.GetObjectModuleDetails(); if (details.Language != Language.C && details.Language != Language.Cxx) { continue; } if (!details.HasDebugInfo) { continue; } foreach (DisposableEnumerableView <SourceFile> sfView in pdb.CreateSourceFileIterator(om)) { SourceFile sf = sfView.Value; string fileName = Path.GetFileName(sf.FileName); if (!_files.Contains(fileName) || sf.HashType == HashType.None) { continue; } string hash = fileName + "#" + BitConverter.ToString(sf.Hash); VulnerableDependencyDescriptor descriptor; if (_filesToVulnerabilitiesMap.TryGetValue(hash, out descriptor)) { if (!vulnerabilityToModules.TryGetValue(descriptor.Id, out moduleList)) { moduleList = vulnerabilityToModules[descriptor.Id] = new TruncatedCompilandRecordList(); } moduleList.Add(om.CreateCompilandRecordWithSuffix(hash)); } } } if (vulnerabilityToModules.Count != 0) { foreach (string id in vulnerabilityToModules.Keys) { moduleList = vulnerabilityToModules[id]; VulnerableDependencyDescriptor descriptor = (VulnerableDependencyDescriptor)context.Policy.GetProperty(VulnerableDependencies)[id]; // '{0}' was built with a version of {1} which is subject to the following issues: {2}. // To resolve this, {3}. The source files that triggered this were: {4} context.Logger.Log(this, RuleUtilities.BuildResult(ResultLevel.Error, context, null, nameof(RuleResources.BA2002_Error), context.TargetUri.GetFileName(), descriptor.Name, descriptor.VulnerabilityDescription, descriptor.Resolution, moduleList.CreateSortedObjectList())); } return; } // '{0}' does not incorporate any known vulnerable dependencies, as configured by current policy. context.Logger.Log(this, RuleUtilities.BuildResult(ResultLevel.Pass, context, null, nameof(RuleResources.BA2002_Pass), context.TargetUri.GetFileName())); }
public void Analyze(BinaryAnalyzerContext context) { PEHeader peHeader = context.PE.PEHeaders.PEHeader; Pdb pdb = context.Pdb; if (pdb == null) { context.Logger.Log(MessageKind.Fail, context, RuleUtilities.BuildCouldNotLoadPdbMessage(context)); return; } Dictionary <string, TruncatedCompilandRecordList> vulnerabilityToModules = new Dictionary <string, TruncatedCompilandRecordList>(); TruncatedCompilandRecordList moduleList; foreach (DisposableEnumerableView <Symbol> omView in pdb.CreateObjectModuleIterator()) { Symbol om = omView.Value; ObjectModuleDetails details = om.GetObjectModuleDetails(); if (details.Language != Language.C && details.Language != Language.Cxx) { continue; } if (!details.HasDebugInfo) { continue; } foreach (DisposableEnumerableView <SourceFile> sfView in pdb.CreateSourceFileIterator(om)) { SourceFile sf = sfView.Value; string fileName = Path.GetFileName(sf.FileName); if (!_files.Contains(fileName) || sf.HashType == HashType.None) { continue; } string hash = fileName + "#" + BitConverter.ToString(sf.Hash); VulnerableDependencyDescriptor descriptor; if (_filesToVulnerabilitiesMap.TryGetValue(hash, out descriptor)) { if (!vulnerabilityToModules.TryGetValue(descriptor.Id, out moduleList)) { moduleList = vulnerabilityToModules[descriptor.Id] = new TruncatedCompilandRecordList(); } moduleList.Add(om.CreateCompilandRecordWithSuffix(hash)); } } } if (vulnerabilityToModules.Count != 0) { foreach (string id in vulnerabilityToModules.Keys) { moduleList = vulnerabilityToModules[id]; VulnerableDependencyDescriptor descriptor = (VulnerableDependencyDescriptor)context.Policy.GetProperty(VulnerableDependencies)[id]; // '{0}' was built with a version of {1} which is subject to the following issues: {2}. // To resolve this, {3}. The source files that triggered this were: {4} context.Logger.Log(MessageKind.Fail, context, RuleUtilities.BuildMessage(context, RulesResources.DoNotIncorporateVulnerableBinaries_Fail, descriptor.Name, descriptor.VulnerabilityDescription, descriptor.Resolution, moduleList.ToString())); } return; } // '{0}' does not incorporate any known vulnerable dependencies, as configured by current policy. context.Logger.Log(MessageKind.Pass, context, RuleUtilities.BuildMessage(context, RulesResources.DoNotIncorporateVulnerableBinaries_Pass)); }
/// <summary> /// The library "hash". This is an XOR of the 1st 16 bytes of all source file hashes. /// </summary> public byte[] GetObjectFileHash(Pdb session) { bool hashPresent = false; byte[] res = new byte[16]; // go through all source files in the lib and XOR their hashes (if present) // NB: there are a couple of interesting cases worth considering: // 1. .h files may be used to build more than one object files in the lib // and when XOR'ed they cancel each other out; // 2. Some source files may not have hashes, in which case our results won't be totally reliable. foreach (DisposableEnumerableView<SourceFile> sfView in session.CreateSourceFileIterator(this)) { SourceFile sf = sfView.Value; if (sf.HashType != HashType.None) { byte[] hash = sf.Hash; if ((hash == null) || (hash.Length < 16)) { throw new PdbParseException("Unexpected hash length for file " + sf); } for (int j = 0; j < 16; j++) { res[j] ^= hash[j]; } hashPresent = true; } } if (!hashPresent) { return null; } return res; }
public void AnalyzeNativeBinaryAndPdb(BinaryAnalyzerContext context) { PEBinary target = context.PEBinary(); Pdb di = target.Pdb; var compilandsBinaryWithOneOrMoreInsecureFileHashes = new List <ObjectModuleDetails>(); var compilandsLibraryWithOneOrMoreInsecureFileHashes = new List <ObjectModuleDetails>(); foreach (DisposableEnumerableView <Symbol> omView in di.CreateObjectModuleIterator()) { Symbol om = omView.Value; ObjectModuleDetails omDetails = om.GetObjectModuleDetails(); if (omDetails.Language != Language.C && omDetails.Language != Language.Cxx) { continue; } if (!omDetails.HasDebugInfo) { continue; } CompilandRecord record = om.CreateCompilandRecord(); foreach (DisposableEnumerableView <SourceFile> sfView in di.CreateSourceFileIterator(om)) { SourceFile sf = sfView.Value; if (sf.HashType != HashType.SHA256) { if (!string.IsNullOrEmpty(record.Library)) { compilandsLibraryWithOneOrMoreInsecureFileHashes.Add(omDetails); } else { compilandsBinaryWithOneOrMoreInsecureFileHashes.Add(omDetails); } } // We only need to check a single source file per compiland, as the relevant // command-line options will be applied to all files in the translation unit. break; } } if (compilandsLibraryWithOneOrMoreInsecureFileHashes.Count > 0 || compilandsBinaryWithOneOrMoreInsecureFileHashes.Count > 0) { if (compilandsLibraryWithOneOrMoreInsecureFileHashes.Count > 0) { GenerateCompilandsAndLog(context, compilandsLibraryWithOneOrMoreInsecureFileHashes, FailureLevel.Warning); } if (compilandsBinaryWithOneOrMoreInsecureFileHashes.Count > 0) { GenerateCompilandsAndLog(context, compilandsBinaryWithOneOrMoreInsecureFileHashes, FailureLevel.Error); } return; } // '{0}' is a {1} binary which was compiled with a secure (SHA-256) // source code hashing algorithm. context.Logger.Log(this, RuleUtilities.BuildResult(ResultKind.Pass, context, null, nameof(RuleResources.BA2004_Pass), context.TargetUri.GetFileName(), "native")); }