public override void Analyze(BinaryAnalyzerContext context)
        {
            PEHeader peHeader = context.PE.PEHeaders.PEHeader;

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

            Pdb di = context.Pdb;

            bool noCode = !di.CreateGlobalFunctionIterator().Any() && !di.ContainsExecutableSectionContribs();

            if (noCode)
            {
                // '{0}' is a C or C++ binary that is not required to initialize the stack protection, as it does not contain executable code.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.Pass, context, null,
                                                             nameof(RuleResources.BA2013_Pass_NoCode),
                                                             context.TargetUri.GetFileName()));
                return;
            }

            bool bHasGSCheck = di.CreateGlobalFunctionIterator(
                StackProtectionUtilities.GSCheckFunctionName, NameSearchOptions.nsfCaseSensitive).Any();

            bool bHasGSInit = StackProtectionUtilities.GSInitializationFunctionNames.Any(
                functionName => di.CreateGlobalFunctionIterator(functionName,
                                                                NameSearchOptions.nsfCaseSensitive).Any());

            if (!bHasGSCheck && !bHasGSInit)
            {
                // '{0}' is a C or C++ binary that does enable the stack protection buffer
                // security feature. It is therefore not required to initialize the stack protector.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.NotApplicable, context, null,
                                                             nameof(RuleResources.BA2013_NotApplicable_FeatureNotEnabled),
                                                             context.TargetUri.GetFileName()));
                return;
            }

            if (!bHasGSInit)
            {
                // '{0}' is a C or C++ binary that does not initialize the stack protector.
                // The stack protector(/ GS) is a security feature of the compiler which
                // makes it more difficult to exploit stack buffer overflow memory
                // corruption vulnerabilities. The stack protector requires access to
                // entropy in order to be effective, which means a binary must initialize
                // a random number generator at startup, by calling __security_init_cookie()
                // as close to the binary's entry point as possible. Failing to do so will
                // result in spurious buffer overflow detections on the part of the stack
                // protector. To resolve this issue, use the default entry point provided
                // by the C runtime, which will make this call for you, or call
                // __security_init_cookie() manually in your custom entry point.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.Error, context, null,
                                                             nameof(RuleResources.BA2013_Error),
                                                             context.TargetUri.GetFileName()));
                return;
            }

            // '{0}' is a C or C++ binary built with the buffer security feature
            // that properly initializes the stack protecter. This has the
            //effect of increasing the effectiveness of the feature and reducing
            // spurious detections.
            context.Logger.Log(this,
                               RuleUtilities.BuildResult(ResultLevel.Pass, context, null,
                                                         nameof(RuleResources.BA2013_Pass),
                                                         context.TargetUri.GetFileName()));
        }
Beispiel #2
0
        public override void Analyze(BinaryAnalyzerContext context)
        {
            PEHeader peHeader = context.PE.PEHeaders.PEHeader;
            Pdb      pdb      = context.Pdb;

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

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

            foreach (DisposableEnumerableView <Symbol> functionView in pdb.CreateGlobalFunctionIterator())
            {
                Symbol function = functionView.Value;
                if (function.IsManaged)
                {
                    continue;
                }
                if (!function.IsSafeBuffers)
                {
                    continue;
                }

                string functionName = function.GetUndecoratedName();

                if (functionName == "__security_init_cookie" ||
                    context.Policy.GetProperty(ApprovedFunctionsThatDisableStackProtection).Contains(functionName))
                {
                    continue;
                }
                names.Add(functionName);
            }

            if (names.Count != 0)
            {
                string functionNames = string.Join(";", names);

                // '{0}' is a C or C++ binary built with function(s) ({1}) that disable the stack
                // protector. The stack protector (/GS) is a security feature of the compiler
                // which makes it more difficult to exploit stack buffer overflow memory
                // corruption vulnerabilities. Disabling the stack protector, even on a
                // function -by-function basis, is disallowed by SDL policy. To resolve this
                // issue, remove occurrences of __declspec(safebuffers) from your code. If the
                // additional code inserted by the stack protector has been shown in profiling
                // to cause a significant performance problem for your application, attempt to
                // move stack buffer modifications out of the hot path of execution to allow the
                // compiler to avoid inserting stack protector checks in these locations rather
                // than disabling the stack protector altogether.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.Error, context, null,
                                                             nameof(RuleResources.BA2014_Error),
                                                             context.TargetUri.GetFileName(),
                                                             functionNames));
                return;
            }

            // '{0}' is a C or C++ binary built with the stack protector buffer
            // security feature enabled which does not disable protection for
            // any individual functions (via __declspec(safebuffers), making it
            // more difficult for an attacker to exploit stack buffer overflow
            // memory corruption vulnerabilities.
            context.Logger.Log(this,
                               RuleUtilities.BuildResult(ResultLevel.Pass, context, null,
                                                         nameof(RuleResources.BA2014_Pass),
                                                         context.TargetUri.GetFileName()));
        }