public sealed override AnalysisApplicability CanAnalyze(BinaryAnalyzerContext context, out string reasonForNotAnalyzing)
 {
     if (context.IsELF())
     {
         ELFBinary target = context.ELFBinary();
         return(this.CanAnalyzeElf(target, context.Policy, out reasonForNotAnalyzing));
     }
     else
     {
         reasonForNotAnalyzing = MetadataConditions.ImageIsNotElf;
         return(AnalysisApplicability.NotApplicableToSpecifiedTarget);
     }
 }
Beispiel #2
0
        public void LoadCompilerDataFromConfig_ParsesAndCachesAsExpected()
        {
            var context = new BinaryAnalyzerContext();

            context.Policy = new PropertiesDictionary();

            AddFakeConfigTestData(context.Policy);

            Dictionary <MachineFamily, CompilerVersionToMitigation[]> result = EnableSpectreMitigations.LoadCompilerDataFromConfig(context.Policy);

            ValidateResultFromFakeTestData(result[MachineFamily.X86]);
            result.Should().ContainKeys(new MachineFamily[] { MachineFamily.X86, MachineFamily.Arm });
        }
Beispiel #3
0
        public override void Analyze(BinaryAnalyzerContext context)
        {
            var sectionHeaders = context.PE.PEHeaders.SectionHeaders;

            List <string> badSections = new List <string>();

            if (sectionHeaders != null)
            {
                foreach (SectionHeader sectionHeader in sectionHeaders)
                {
                    SectionCharacteristics wsFlags = SectionCharacteristics.MemWrite | SectionCharacteristics.MemShared;

                    if ((sectionHeader.SectionCharacteristics & wsFlags) == wsFlags) // IMAGE_SCN_MEM_WRITE & IMAGE_SCN_MEM_SHARED
                    {
                        badSections.Add(sectionHeader.Name);
                    }
                }
            }

            if (badSections.Count == 0)
            {
                // Image '{0}' contains no data or code sections marked as both shared and writable.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.Pass, context, null,
                                                             nameof(RuleResources.BA2019_Pass),
                                                             context.TargetUri.GetFileName()));
                return;
            }

            string badSectionsText = String.Join(";", badSections);

            // '{0}' contains PE section(s) ({1}) that are both writable and executable.
            // Writable and executable memory segments make it easier for an attacker
            // to exploit memory corruption vulnerabilities, because it may provide an
            // attacker executable location(s) to inject shellcode. To resolve this
            // issue, configure your tools to not emit memory sections that are writable
            // and executable. For example, look for uses of /SECTION on the linker
            // command line for C and C++ programs, or #pragma section in C and C++
            // source code, which mark a section with both attributes. Enabling
            // incremental linking via the /INCREMENTAL argument (the default for
            // Microsoft Visual Studio debug build) can also result in a writable and
            // executable section named 'textbss'. For this case, disable incremental
            // linking (or analyze an alternate build configuration that disables this
            // feature) to resolve the problem.
            context.Logger.Log(this,
                               RuleUtilities.BuildResult(ResultLevel.Error, context, null,
                                                         nameof(RuleResources.BA2019_Error),
                                                         context.TargetUri.GetFileName(),
                                                         badSectionsText));
        }
        public override AnalysisApplicability CanAnalyze(BinaryAnalyzerContext context, out string reasonForNotAnalyzing)
        {
            PE portableExecutable        = context.PE;
            AnalysisApplicability result = AnalysisApplicability.NotApplicableToSpecifiedTarget;

            reasonForNotAnalyzing = MetadataConditions.ImageIsResourceOnlyBinary;
            if (portableExecutable.IsResourceOnly)
            {
                return(result);
            }

            reasonForNotAnalyzing = MetadataConditions.ImageIsILOnlyManagedAssembly;
            if (portableExecutable.IsILOnly)
            {
                return(result);
            }

            reasonForNotAnalyzing = MetadataConditions.ImageIsMixedModeBinary;
            if (portableExecutable.IsMixedMode)
            {
                return(result);
            }

            reasonForNotAnalyzing = MetadataConditions.ImageIsKernelModeAndNot64Bit_CfgUnsupported;
            if (portableExecutable.IsKernelMode && !portableExecutable.Is64Bit)
            {
                return(result);
            }

            reasonForNotAnalyzing = MetadataConditions.ImageIsBootBinary;
            if (portableExecutable.IsBoot)
            {
                return(result);
            }

            Version minimumRequiredLinkerVersion = context.Policy.GetProperty(MinimumRequiredLinkerVersion);

            if (portableExecutable.LinkerVersion < minimumRequiredLinkerVersion)
            {
                reasonForNotAnalyzing = string.Format(
                    MetadataConditions.ImageCompiledWithOutdatedTools,
                    portableExecutable.LinkerVersion,
                    minimumRequiredLinkerVersion);

                return(result);
            }

            reasonForNotAnalyzing = null;
            return(AnalysisApplicability.ApplicableToSpecifiedTarget);
        }
Beispiel #5
0
        private BinaryAnalyzerContext CreateContext(TestMessageLogger logger, PropertyBag policy, string target)
        {
            var context = new BinaryAnalyzerContext();

            context.Logger = logger;
            context.Policy = policy;

            if (target != null)
            {
                context.TargetUri = new Uri(target);
            }

            return(context);
        }
Beispiel #6
0
        internal static BinaryAnalyzerContext CreateContext(IMessageLogger <BinaryAnalyzerContext> logger, PropertyBag policy, string filePath = null)
        {
            var context = new BinaryAnalyzerContext();

            context.Logger = logger;
            context.Policy = policy;

            if (filePath != null)
            {
                context.Uri = new Uri(filePath);
            }

            return(context);
        }
Beispiel #7
0
        public override void Analyze(BinaryAnalyzerContext context)
        {
            // Throw a platform unsupported exception--FileVersionInfo does not behave "correctly" on Linux.
            BinaryParsers.PlatformSpecificHelpers.ThrowIfNotOnWindows();

            PEBinary target = context.PEBinary();

            string fileName = Path.GetFileName(target.PE.FileName);

            Version minimumVersion;

            if (context.Policy.GetProperty(VulnerableBinaries).TryGetValue(fileName, out minimumVersion))
            {
                FileVersionInfo fvi              = FileVersionInfo.GetVersionInfo(Path.GetFullPath(target.PE.FileName));
                string          rawVersion       = fvi.FileVersion ?? string.Empty;
                Match           sanitizedVersion = s_versionRegex.Match(rawVersion);
                if (!sanitizedVersion.Success)
                {
                    // Version information for '{0}' could not be parsed. The binary therefore could not be verified not to be an obsolete binary that is known to be vulnerable to one or more security problems.
                    context.Logger.Log(this,
                                       RuleUtilities.BuildResult(ResultLevel.Error, context, null,
                                                                 nameof(RuleResources.BA2005_Error_CouldNotParseVersion),
                                                                 context.TargetUri.GetFileName()));
                    return;
                }

                var actualVersion = new Version(sanitizedVersion.Value);
                if (actualVersion < minimumVersion)
                {
                    // '{0}' appears to be an obsolete library (version {1}) for which there are one
                    // or more known security vulnerabilities. To resolve this issue, obtain a version
                    //of {0} that is version {2} or greater. If this binary is not in fact {0},
                    // ignore this warning.
                    context.Logger.Log(this,
                                       RuleUtilities.BuildResult(ResultLevel.Error, context, null,
                                                                 nameof(RuleResources.BA2005_Error),
                                                                 context.TargetUri.GetFileName(),
                                                                 sanitizedVersion.Value,
                                                                 minimumVersion.ToString()));
                    return;
                }
            }

            // '{0}' is not known to be an obsolete binary that is
            //vulnerable to one or more security problems.
            context.Logger.Log(this,
                               RuleUtilities.BuildResult(ResultLevel.Pass, context, null,
                                                         nameof(RuleResources.BA2005_Pass),
                                                         context.TargetUri.GetFileName()));
        }
        public override void AnalyzePortableExecutableAndPdb(BinaryAnalyzerContext context)
        {
            PEBinary target = context.PEBinary();
            Pdb      pdb    = target.Pdb;

            if (PrintHeader)
            {
                Console.WriteLine("Target,Compiler Name,Compiler BackEnd Version,Compiler FrontEnd Version,Language,Module Name,Module Library,Hash,Error");
                PrintHeader = false;
            }

            if (pdb == null)
            {
                Console.Write(context.TargetUri.LocalPath + ",");
                Console.WriteLine($",,,,,,{context?.Hashes?.Sha256},{target.PdbParseException.Message}");
                return;
            }

            var records = new Dictionary <string, ObjectModuleDetails>();

            foreach (DisposableEnumerableView <Symbol> omView in pdb.CreateObjectModuleIterator())
            {
                Symbol om = omView.Value;
                ObjectModuleDetails omDetails = om.GetObjectModuleDetails();

                string record =
                    omDetails.CompilerName?.Replace(",", "_").Trim() + "," +
                    omDetails.CompilerBackEndVersion + "," +
                    omDetails.CompilerFrontEndVersion + "," +
                    omDetails.Language;

                if (!records.TryGetValue(record, out ObjectModuleDetails value))
                {
                    records[record] = omDetails;
                }
            }

            foreach (KeyValuePair <string, ObjectModuleDetails> kv in records)
            {
                string compilerData           = kv.Key;
                ObjectModuleDetails omDetails = kv.Value;

                Console.Write(context.TargetUri.LocalPath + ",");
                Console.Write(compilerData + ",");
                Console.Write(omDetails.Name?.Replace(",", "_") + ",");
                Console.Write(omDetails.Library?.Replace(",", ";") + ",");
                Console.Write($"{context?.Hashes?.Sha256},");
                Console.WriteLine();
            }
        }
        public sealed override void Analyze(BinaryAnalyzerContext context)
        {
            // Uses PDB Parsing.
            BinaryParsers.PlatformSpecificHelpers.ThrowIfNotOnWindows();
            PEBinary target = context.PEBinary();

            if (target.Pdb == null)
            {
                Errors.LogExceptionLoadingPdb(context, target.PdbParseException);
                return;
            }

            AnalyzePortableExecutableAndPdb(context);
        }
Beispiel #10
0
        public void GetNextCompilerVersionUp_WithSpectreMitigations_WorksAsExpected(string firstVersionStr, ExtendedMachine machine, string expectedVersionStr)
        {
            Version actualVersion = new Version(firstVersionStr);

            var context = new BinaryAnalyzerContext();

            context.Policy = new PropertiesDictionary();

            AddFakeConfigTestData(context.Policy);

            Version nextUp = EnableSpectreMitigations.GetClosestCompilerVersionWithSpectreMitigations(context, machine, actualVersion);

            nextUp.ShouldBeEquivalentTo(new Version(expectedVersionStr));
        }
        public override AnalysisApplicability CanAnalyze(BinaryAnalyzerContext context, out string reasonForNotAnalyzing)
        {
            PE portableExecutable        = context.PE;
            AnalysisApplicability result = AnalysisApplicability.NotApplicableToSpecifiedTarget;

            reasonForNotAnalyzing = MetadataConditions.ImageIsKernelModeBinary;
            if (portableExecutable.IsKernelMode)
            {
                return(result);
            }

            reasonForNotAnalyzing = null;
            return(AnalysisApplicability.ApplicableToSpecifiedTarget);
        }
        public override AnalysisApplicability CanAnalyze(BinaryAnalyzerContext context, out string reasonForNotAnalyzing)
        {
            // Checks for missing policy should always be evaluated as the last action, so that
            // we do not raise an error in cases where the analysis would not otherwise be applied.

            // Missing required configuration: 'vulnerable binary name and version metadata'
            reasonForNotAnalyzing = RuleResources.BA2005_MissingRequiredConfiguration;
            if (context.Policy == null)
            {
                return(AnalysisApplicability.NotApplicableDueToMissingConfiguration);
            }

            return(AnalysisApplicability.ApplicableToSpecifiedTarget);
        }
Beispiel #13
0
        private void LogExceptionLoadingRoslynAnalyzer(string analyzerFilePath, BinaryAnalyzerContext context, Exception ex)
        {
            context.Rule = ErrorRules.InvalidConfiguration;

            // An exception was raised attempting to load Roslyn analyzer '{0}'. Exception information:
            // {1}
            context.Logger.Log(MessageKind.ConfigurationError,
                               context,
                               string.Format(DriverResources.UnhandledExceptionLoadingRoslynAnalyzer,
                                             analyzerFilePath,
                                             context.PE.LoadException.ToString()));

            RuntimeErrors |= RuntimeConditions.ExceptionLoadingRoslynAnalyzer;
        }
        public override void Analyze(BinaryAnalyzerContext context)
        {
            string         executableImportSection = null;
            PEHeader       peHeader    = context.PE.PEHeaders.PEHeader;
            DirectoryEntry importTable = peHeader.ImportTableDirectory;

            if (importTable.RelativeVirtualAddress != 0 && context.PE.PEHeaders.SectionHeaders != null)
            {
                int importSize = peHeader.ImportTableDirectory.Size;
                foreach (SectionHeader sectionHeader in context.PE.PEHeaders.SectionHeaders)
                {
                    SectionCharacteristics memExecute = SectionCharacteristics.MemExecute;
                    if ((sectionHeader.SectionCharacteristics & memExecute) == 0)
                    {
                        continue;
                    }

                    int size    = sectionHeader.SizeOfRawData;
                    int address = sectionHeader.VirtualAddress;

                    if ((address <= importTable.RelativeVirtualAddress) &&
                        (address + size >= importTable.RelativeVirtualAddress + importTable.Size))
                    {
                        // Our import section is in a writable section - bad
                        executableImportSection = sectionHeader.Name;
                        break;
                    }
                }
            }

            if (executableImportSection != null)
            {
                // '{0}' has the imports section marked executable. Because the loader will always mark
                // the imports section as writable, it is important to mark this section as non-executable,
                // so that an attacker cannot place shellcode here. To resolve this issue, ensure that your
                //program does not mark the imports section as executable. Look for uses of /SECTION or
                // /MERGE on the linker command line, or #pragma segment in source code, which change the
                // imports section to be executable, or which merge the ".rdata" segment into an executable
                // section.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.Error, context, null,
                                                             nameof(RuleResources.BA2010_Error)));
                return;
            }

            // '{0}' does not have an imports section that is marked as executable.
            context.Logger.Log(this,
                               RuleUtilities.BuildResult(ResultLevel.Pass, context, null,
                                                         nameof(RuleResources.BA2010_Pass)));
        }
Beispiel #15
0
        private void LogExceptionInvalidPE(BinaryAnalyzerContext context)
        {
            context.Rule = ErrorRules.InvalidPE;

            // Image '{0}' was not analyzed as the it does not
            // appear to be a valid portable executable.
            context.Logger.Log(MessageKind.NotApplicable,
                               context,
                               string.Format(
                                   SdkResources.TargetNotAnalyzed_NotAPortableExecutable,
                                   context.Uri.LocalPath));

            DisposePortableExecutableContextData(context);
            RuntimeErrors |= RuntimeConditions.OneOrMoreTargetsNotPortableExecutables;
        }
Beispiel #16
0
        private void LogExceptionLoadingTarget(BinaryAnalyzerContext context)
        {
            context.Rule = ErrorRules.InvalidConfiguration;

            // An exception was raised attempting to load analysis target '{0}'. Exception information:
            // {1}
            context.Logger.Log(MessageKind.ConfigurationError,
                               context,
                               string.Format(DriverResources.ExceptionLoadingAnalysisTarget,
                                             context.PE.FileName,
                                             context.PE.LoadException.ToString()));

            DisposePortableExecutableContextData(context);
            RuntimeErrors |= RuntimeConditions.ExceptionLoadingTargetFile;
        }
Beispiel #17
0
        private BinaryAnalyzerContext CreateContext(TestMessageLogger logger, PropertiesDictionary policy, string target)
        {
            var context = new BinaryAnalyzerContext
            {
                Logger = logger,
                Policy = policy
            };

            if (target != null)
            {
                context.TargetUri = new Uri(target);
            }

            return(context);
        }
        private bool Validate32BitImage(BinaryAnalyzerContext context)
        {
            PEHeader    peHeader     = context.PE.PEHeaders.PEHeader;
            SafePointer sp           = new SafePointer(context.PE.ImageBytes, peHeader.LoadConfigTableDirectory.RelativeVirtualAddress);
            SafePointer loadConfigVA = context.PE.RVA2VA(sp);
            ImageLoadConfigDirectory32 loadConfig = new ImageLoadConfigDirectory32(peHeader, loadConfigVA);

            UInt32 cookieVA    = (UInt32)loadConfig.GetField(ImageLoadConfigDirectory32.Fields.SecurityCookie);
            UInt32 baseAddress = (UInt32)peHeader.ImageBase;

            // we need to find the offset in the file based on the cookie's VA
            UInt32        sectionSize, sectionVA = 0;
            SectionHeader ish = new SectionHeader();
            bool          foundCookieSection = false;

            foreach (SectionHeader t in context.PE.PEHeaders.SectionHeaders)
            {
                sectionVA   = (UInt32)t.VirtualAddress + baseAddress;
                sectionSize = (UInt32)t.VirtualSize;
                if ((cookieVA >= sectionVA) &&
                    (cookieVA < sectionVA + sectionSize))
                {
                    ish = t;
                    foundCookieSection = true;
                    break;
                }
            }

            if (!foundCookieSection)
            {
                LogCouldNotLocateCookie(context);
                return(false);
            }

            UInt64      fileCookieOffset = (cookieVA - baseAddress) - (sectionVA - baseAddress) + (UInt32)ish.PointerToRawData;
            SafePointer fileCookiePtr    = loadConfigVA;

            fileCookiePtr.Address = (int)fileCookieOffset;
            UInt32 cookie = BitConverter.ToUInt32(fileCookiePtr.GetBytes(8), 0);

            if (!StackProtectionUtilities.DefaultCookiesX86.Contains(cookie) && context.PE.Machine == Machine.I386)
            {
                LogFailure(context, cookie.ToString("x"));
                return(false);
            }

            return(true);
        }
        public override void Analyze(BinaryAnalyzerContext context)
        {
            PEBinary target   = context.PEBinary();
            PEHeader peHeader = target.PE.PEHeaders.PEHeader;

            if (peHeader.LoadConfigTableDirectory.RelativeVirtualAddress == 0)
            {
                // LOAD_CONFIG block absent. This can occur in 2 cases:
                // 1. The user has C or C++ code linked with a linker older than Dev11 (VS2010)
                // 2. The code is not C or C++ code at all.
                //
                // In the first case we expect CompilerVersionCheck to fire on this code. In the
                // second case we don't want to warn because the code is likely safe;
                // e.g. .NET ngen'd images fall into this bucket.

                //'{0}' is  C or C++binary that does not contain a load config table, which
                // indicates either that it was compiled and linked with a version of the
                // compiler that precedes stack protection features or is a binary (such as
                // an ngen'ed assembly) that is not subject to relevant security issues.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.Pass, context, null,
                                                             nameof(RuleResources.BA2012_Pass_NoLoadConfig),
                                                             context.TargetUri.GetFileName()));
                return;
            }

            if (target.PE.Is64Bit)
            {
                if (!Validate64BitImage(context))
                {
                    return;
                }
            }
            else if (!Validate32BitImage(context))
            {
                return;
            }

            // '{0}' is a C or C++ binary built with the buffer security feature
            // that properly preserves the stack protecter cookie. This has the
            // effect of enabling a significant increase in entropy provided by
            // the operating system over that produced by the C runtime start-up
            // code.
            context.Logger.Log(this,
                               RuleUtilities.BuildResult(ResultLevel.Pass, context, null,
                                                         nameof(RuleResources.BA2012_Pass),
                                                         context.TargetUri.GetFileName()));
        }
Beispiel #20
0
        public override AnalysisApplicability CanAnalyze(BinaryAnalyzerContext context, out string reasonForNotAnalyzing)
        {
            AnalysisApplicability applicability = StackProtectionUtilities.CommonCanAnalyze(context, out reasonForNotAnalyzing);

            // Checks for missing policy should always be evaluated as the last action, so that
            // we do not raise an error in cases where the analysis would not otherwise be applied.
            if (applicability == AnalysisApplicability.ApplicableToSpecifiedTarget)
            {
                reasonForNotAnalyzing = RuleResources.BA2005_MissingRequiredConfiguration;
                if (context.Policy == null)
                {
                    return(AnalysisApplicability.NotApplicableDueToMissingConfiguration);
                }
            }
            return(applicability);
        }
Beispiel #21
0
        public void GetClosestCompilerVersionWithSpectreMitigations_UnsupportedOnMachine()
        {
            BinaryAnalyzerContext context = new BinaryAnalyzerContext();

            context.Policy = new PropertiesDictionary();
            PropertiesDictionary BA2024Config       = new PropertiesDictionary();
            PropertiesDictionary mitigatedCompilers = new PropertiesDictionary();
            PropertiesDictionary fakeX86Data        = GenerateMachineFamilyData();

            mitigatedCompilers.Add(MachineFamily.X86.ToString(), fakeX86Data);

            BA2024Config.Add("MitigatedCompilers", mitigatedCompilers);
            context.Policy.Add("BA2024.EnableSpectreMitigations.Options", BA2024Config);

            Assert.Null(EnableSpectreMitigations.GetClosestCompilerVersionWithSpectreMitigations(context, ExtendedMachine.Arm, new Version(1, 0, 100, 5)));
        }
        public AnalysisApplicability CanAnalyze(BinaryAnalyzerContext context, out string reasonForNotAnalyzing)
        {
            AnalysisApplicability applicability = StackProtectionUtilities.CommonCanAnalyze(context, out reasonForNotAnalyzing);

            // Checks for missing policy should always be evaluated as the last action, so that
            // we do not raise an error in cases where the analysis would not otherise be applied.
            if (applicability == AnalysisApplicability.ApplicableToSpecifiedTarget)
            {
                reasonForNotAnalyzing = RulesResources.DoNotShipVulnerabilities_MissingPolicy_InternalError;
                if (context.Policy == null)
                {
                    return(AnalysisApplicability.NotApplicableToAnyTargetWithoutPolicy);
                }
            }
            return(applicability);
        }
Beispiel #23
0
        private void LogUnhandledExceptionInitializingRule(BinaryAnalyzerContext context, IBinarySkimmer skimmer, Exception ex)
        {
            string ruleName = context.Rule.Name;

            // An unhandled exception was encountered initializing check '{0}', which
            // has been disabled for the remainder of the analysis. Exception information:
            // {1}
            context.Rule = ErrorRules.UnhandledRuleException;
            context.Logger.Log(MessageKind.InternalError,
                               context,
                               string.Format(DriverResources.UnhandledExceptionInitializingRule,
                                             ruleName,
                                             ex.ToString()));

            RuntimeErrors |= RuntimeConditions.ExceptionInSkimmerInitialize;
        }
Beispiel #24
0
        public override void Analyze(BinaryAnalyzerContext context)
        {
            var sectionHeaders = context.PE.PEHeaders.SectionHeaders;

            List <string> badSections = new List <string>();

            if (sectionHeaders != null)
            {
                foreach (SectionHeader sectionHeader in sectionHeaders)
                {
                    SectionCharacteristics wsFlags = SectionCharacteristics.MemWrite | SectionCharacteristics.MemShared;

                    if ((sectionHeader.SectionCharacteristics & wsFlags) == wsFlags) // IMAGE_SCN_MEM_WRITE & IMAGE_SCN_MEM_SHARED
                    {
                        badSections.Add(sectionHeader.Name);
                    }
                }
            }

            if (badSections.Count == 0)
            {
                // Image '{0}' contains no data or code sections marked as both shared and writable.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.Pass, context, null,
                                                             nameof(RuleResources.BA2019_Pass),
                                                             context.TargetUri.GetFileName()));
                return;
            }

            string badSectionsText = String.Join(";", badSections);

            // {0} contains one or more code or data sections ({1}) which are marked as both
            // shared and writable. Because these sections are shared across processes, this
            // condition might permit a process with low privilege to mutate memory in a higher
            // privilege process. If you do not actually require that the section be both
            // writable and shared, remove one or both of these attributes (by modifying your
            // .DEF file, the appropriate linker /section switch arguments, etc.). If you are
            // required to share common data across processes (for IPC or other purposes) use
            // CreateFileMapping with proper security attributes or an actual IPC mechanism
            // instead (COM, named pipes, LPC, etc.).
            context.Logger.Log(this,
                               RuleUtilities.BuildResult(ResultLevel.Error, context, null,
                                                         nameof(RuleResources.BA2019_Error),
                                                         context.TargetUri.GetFileName(),
                                                         badSectionsText));
        }
        public void Analyze(BinaryAnalyzerContext context)
        {
            // '{0} does not contain a load configuration table, indicating that it does not enable the control flow guard mitigation.PEHeader peHeader = context.PE.PEHeaders.PEHeader;

            if (!EnablesControlFlowGuard(context))
            {
                context.Logger.Log(MessageKind.Fail, context,
                                   RuleUtilities.BuildMessage(context,
                                                              RulesResources.EnableControlFlowGuard_Fail));
                return;
            }

            // '{0}' enables the control flow guard mitigation.
            context.Logger.Log(MessageKind.Pass, context,
                               RuleUtilities.BuildMessage(context,
                                                          RulesResources.EnableControlFlowGuard_Pass));
        }
Beispiel #26
0
        private bool CookieOffsetValid(BinaryAnalyzerContext context, SafePointer boundsCheck)
        {
            if (boundsCheck.IsValid)
            {
                return(true);
            }

            if (context.PE.IsPacked)
            {
                LogInvalidCookieOffsetForKnownPackedFile(context);
            }
            else
            {
                LogInvalidCookieOffset(context);
            }
            return(false);
        }
Beispiel #27
0
        private void Analyze(AnalyzeOptions analyzeOptions, AggregatingLogger logger)
        {
            // 1. Scrape the analyzer options for settings that alter
            //    behaviors of binary parsers (such as settings for
            //    symbols resolution).
            InitializeParsersFromOptions(analyzeOptions);

            // 2. Produce a comprehensive set of analysis targets
            HashSet <string> targets = CreateTargetsSet(analyzeOptions);

            // 3. Proactively validate that we can locate and
            //    access all analysis targets. Helper will return
            //    a list that potentially filters out files which
            //    did not exist, could not be accessed, etc.
            targets = ValidateTargetsExist(logger, targets);

            // 4. Create our policy, which will be shared across
            //    all context objects that are created during analysis
            PropertyBag policy = CreatePolicyFromOptions(analyzeOptions);

            // 5. Create short-lived context object to pass to
            //    skimmers during initialization. The logger and
            //    policy objects are common to all context instances
            //    and will be passed on again for analysis.
            BinaryAnalyzerContext context = CreateContext(logger, policy);

            // 6. Initialize report file, if configured.
            InitializeOutputFile(analyzeOptions, context, targets);

            // 7. Instantiate skimmers.
            HashSet <IBinarySkimmer> skimmers = CreateSkimmers(logger);

            // 8. Initialize skimmers. Initialize occurs a single time only.
            skimmers = InitializeSkimmers(skimmers, context);

            // 9. Run all PE- and MSIL-based analysis
            Analyze(skimmers, analyzeOptions.RoslynAnalyzerFilePaths, targets, logger, policy);

            // 10. For test purposes, raise an unhandled exception if indicated
            if (RaiseUnhandledExceptionInDriverCode)
            {
                throw new InvalidOperationException(nameof(AnalyzeCommand));
            }
        }
        public override AnalysisApplicability CanAnalyze(BinaryAnalyzerContext context, out string reasonForNotAnalyzing)
        {
            PE portableExecutable        = context.PE;
            AnalysisApplicability result = AnalysisApplicability.NotApplicableToSpecifiedTarget;

            reasonForNotAnalyzing = MetadataConditions.ImageIs64BitBinary;
            if (context.PE.PEHeaders.PEHeader.Magic == PEMagic.PE32Plus)
            {
                return(result);
            }

            reasonForNotAnalyzing = MetadataConditions.ImageIsKernelModeBinary;
            if (portableExecutable.IsKernelMode)
            {
                return(result);
            }

            reasonForNotAnalyzing = MetadataConditions.ImageIsXBoxBinary;
            if (portableExecutable.IsXBox)
            {
                return(result);
            }

            reasonForNotAnalyzing = MetadataConditions.ImageIsResourceOnlyBinary;
            if (portableExecutable.IsResourceOnly)
            {
                return(result);
            }

            reasonForNotAnalyzing = MetadataConditions.ImageIsPreVersion7WindowsCEBinary;
            if (OSVersions.IsWindowsCEPriorToV7(portableExecutable))
            {
                return(result);
            }

            reasonForNotAnalyzing = MetadataConditions.ImageIsBootBinary;
            if (portableExecutable.IsBoot)
            {
                return(result);
            }

            reasonForNotAnalyzing = null;
            return(AnalysisApplicability.ApplicableToSpecifiedTarget);
        }
Beispiel #29
0
        public override void Analyze(BinaryAnalyzerContext context)
        {
            if (!EnablesControlFlowGuard(context))
            {
                // '{0}' does not enable the control flow guard (CFG) mitigation.
                // To resolve this issue, pass /GUARD:CF on both the compiler
                // and linker command lines. Binaries also require the
                // /DYNAMICBASE linker option in order to enable CFG.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.Error, context, null,
                                                             nameof(RuleResources.BA2008_Error)));
                return;
            }

            // '{0}' enables the control flow guard mitigation.
            context.Logger.Log(this,
                               RuleUtilities.BuildResult(ResultLevel.Pass, context, null,
                                                         nameof(RuleResources.BA2008_Pass)));
        }
Beispiel #30
0
        public void Analyze(BinaryAnalyzerContext context)
        {
            string fileName = Path.GetFileName(context.PE.FileName);

            Version minimumVersion;

            if (context.Policy.GetProperty(VulnerableBinaries).TryGetValue(fileName, out minimumVersion))
            {
                FileVersionInfo fvi              = FileVersionInfo.GetVersionInfo(Path.GetFullPath(context.PE.FileName));
                string          rawVersion       = fvi.FileVersion;
                Match           sanitizedVersion = s_versionRegex.Match(rawVersion);
                if (!sanitizedVersion.Success)
                {
                    // Version information for '{0}' could not be parsed. The binary therefore could not be verified not to be an obsolete binary that is known to be vulnerable to one or more security problems.
                    context.Logger.Log(MessageKind.Fail, context,
                                       RuleUtilities.BuildMessage(context,
                                                                  RulesResources.DoNotShipVulnerableBinaries_CouldNotParseVersion_Fail));
                    return;
                }

                var actualVersion = new Version(sanitizedVersion.Value);
                if (actualVersion < minimumVersion)
                {
                    // '{0}' appears to be an obsolete library (version {1}) for which there are one
                    // or more known security vulnerabilities. To resolve this issue, obtain a version
                    //of {0} that is newer than version {2}. If this binary is not in fact {0},
                    // ignore this warning.

                    context.Logger.Log(MessageKind.Fail, context,
                                       RuleUtilities.BuildMessage(context,
                                                                  RulesResources.DoNotShipVulnerableBinaries_CouldNotParseVersion_Fail,
                                                                  minimumVersion.ToString()));
                    return;
                }
            }

            // '{0}' is not known to be an obsolete binary that is
            //vulnerable to one or more security problems.
            context.Logger.Log(MessageKind.Pass, context,
                               RuleUtilities.BuildMessage(context,
                                                          RulesResources.DoNotShipVulnerableBinaries_Pass));
        }