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); }
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 }; } ); } }
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); }
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)); } }
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); } } }