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));
        }
Esempio n. 3
0
        /// <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"));
        }