Beispiel #1
0
        public override int Run(AnalyzeOptions analyzeOptions)
        {
            // 0. Initialize an common logger that drives all outputs. This
            //    object drives logging for console, statistics, etc.
            using (AggregatingLogger logger = InitializeLogger(analyzeOptions))
            {
                try
                {
                    Analyze(analyzeOptions, logger);
                }
                catch (ExitApplicationException <FailureReason> ex)
                {
                    ExecutionException = ex;
                    return(FAILURE);
                }
                catch (Exception ex)
                {
                    RuntimeErrors     |= RuntimeConditions.ExceptionInEngine;
                    ExecutionException = ex;
                    return(FAILURE);
                }
            }

            return(((RuntimeErrors & RuntimeConditions.Fatal) == RuntimeConditions.NoErrors) ? SUCCESS : FAILURE);
        }
Beispiel #2
0
        private void InitializeOutputFile(AnalyzeOptions analyzeOptions, BinaryAnalyzerContext context, HashSet <string> targets)
        {
            string            filePath          = analyzeOptions.OutputFilePath;
            AggregatingLogger aggregatingLogger = (AggregatingLogger)context.Logger;

            if (!string.IsNullOrEmpty(filePath))
            {
                InvokeCatchingRelevantIOExceptions
                (
                    () => aggregatingLogger.Loggers.Add(
                        new SarifLogger(
                            analyzeOptions.OutputFilePath,
                            analyzeOptions.Verbose,
                            targets,
                            analyzeOptions.ComputeTargetsHash)),
                    (ex) =>
                {
                    LogExceptionCreatingLogFile(filePath, context, ex);
                    throw new ExitApplicationException <FailureReason>(DriverResources.UnexpectedApplicationExit, ex)
                    {
                        FailureReason = FailureReason.ExceptionCreatingLogFile
                    };
                }
                );
            }
        }
Beispiel #3
0
        internal AggregatingLogger InitializeLogger(AnalyzeOptions analyzeOptions)
        {
            var logger = new AggregatingLogger();

            logger.Loggers.Add(new ConsoleLogger(analyzeOptions.Verbose));

            if (analyzeOptions.Statistics)
            {
                logger.Loggers.Add(new StatisticsLogger());
            }

            return(logger);
        }
Beispiel #4
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));
            }
        }
Beispiel #5
0
        private void Analyze(
            IEnumerable <IBinarySkimmer> skimmers,
            IList <string> roslynAnalyzerFilePaths,
            IEnumerable <string> targets,
            AggregatingLogger logger,
            PropertyBag policy)
        {
            HashSet <string> disabledSkimmers = new HashSet <string>();

            foreach (string target in targets)
            {
                var context = AnalyzeCommand.CreateContext(logger, policy, target);

                if (context.PE.LoadException != null)
                {
                    LogExceptionLoadingTarget(context);
                    continue;
                }
                else if (!context.PE.IsPEFile)
                {
                    LogExceptionInvalidPE(context);
                    continue;
                }

                context = CreateContext(logger, policy, target);

                // Analyzing {0}...
                logger.Log(MessageKind.AnalyzingTarget, context, DriverResources.Analyzing);

                foreach (IBinarySkimmer skimmer in skimmers)
                {
                    if (disabledSkimmers.Contains(skimmer.Id))
                    {
                        continue;
                    }

                    string reasonForNotAnalyzing = null;
                    context.Rule = skimmer;

                    AnalysisApplicability applicability = AnalysisApplicability.Unknown;

                    try
                    {
                        applicability = skimmer.CanAnalyze(context, out reasonForNotAnalyzing);
                    }
                    catch (Exception ex)
                    {
                        LogUnhandledRuleExceptionAssessingTargetApplicability(disabledSkimmers, context, skimmer, ex);
                        continue;
                    }

                    switch (applicability)
                    {
                    case AnalysisApplicability.NotApplicableToSpecifiedTarget:
                    {
                        // Image '{0}' was not evaluated for check '{1}' as the analysis
                        // is not relevant based on observed binary metadata: {2}.
                        context.Logger.Log(MessageKind.NotApplicable,
                                           context,
                                           RuleUtilities.BuildTargetNotAnalyzedMessage(
                                               context.PE.FileName,
                                               context.Rule.Name,
                                               reasonForNotAnalyzing));

                        break;
                    }

                    case AnalysisApplicability.NotApplicableToAnyTargetWithoutPolicy:
                    {
                        // Check '{0}' was disabled for this run as the analysis was not
                        // configured with required policy ({1}). To resolve this,
                        // configure and provide a policy file on the BinSkim command-line
                        // using the --policy argument (recommended), or pass
                        // '--policy default' to invoke built-in settings. Invoke the
                        // BinSkim.exe 'export' command to produce an initial policy file
                        // that can be edited if required and passed back into the tool.
                        context.Logger.Log(MessageKind.ConfigurationError, context,
                                           RuleUtilities.BuildRuleDisabledDueToMissingPolicyMessage(
                                               context.Rule.Name,
                                               reasonForNotAnalyzing));
                        disabledSkimmers.Add(skimmer.Id);
                        break;
                    }

                    case AnalysisApplicability.ApplicableToSpecifiedTarget:
                    {
                        try
                        {
                            skimmer.Analyze(context);
                        }
                        catch (Exception ex)
                        {
                            LogUnhandledRuleExceptionAnalyzingTarget(disabledSkimmers, context, skimmer, ex);
                        }
                        break;
                    }
                    }
                }

                // Once we've processed all portable executable skimmers for a specific
                // target, we'll proactively let go of the data associated with this
                // analysis phase. Follow-on analyses (such as the Roslyn integration)
                // shouldn't attempt to rehydrate this data. The context implementation
                // currently raises an exception if there is an attempt to rehydrate a
                // previously nulled PE instance.
                DisposePortableExecutableContextData(context);

                // IsManagedAssembly is computed on intitializing the binary context
                // object and is still valid after disposing the PE data. The Roslyn
                // analysis is driven solely off the binary file path in the context.
                if (context.IsManagedAssembly && roslynAnalyzerFilePaths?.Count > 0)
                {
                    AnalyzeManagedAssembly(context.Uri.LocalPath, roslynAnalyzerFilePaths, context);
                }
            }
        }