Ejemplo n.º 1
0
        public override void Analyze(BinaryAnalyzerContext context)
        {
            // Uses Windows Certificate Interop
            BinaryParsers.PlatformSpecificHelpers.ThrowIfNotOnWindows();
            PEBinary target = context.PEBinary();

            Native.WINTRUST_DATA winTrustData;
            string algorithmName, filePath;

            filePath = target.PE.FileName;

            winTrustData = new Native.WINTRUST_DATA();

            if (InvokeVerifyAction(context, filePath, out winTrustData, out algorithmName))
            {
                // '{0}' appears to be signed securely by a trusted publisher with no
                // verification or time stamp errors. Revocation checking was performed
                // on the entire certificate chain, excluding the root certificate.
                // The following digitial signature algorithms were detected: {1}
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultKind.Pass, context, null,
                                                             nameof(RuleResources.BA2022_Pass),
                                                             context.TargetUri.GetFileName(),
                                                             algorithmName));
            }
        }
        private void AnalyzeManagedAssemblyAndPdb(BinaryAnalyzerContext context)
        {
            PEBinary target = context.PEBinary();
            Pdb      di     = target.Pdb;

            if (target.PE.ManagedPdbSourceFileChecksumAlgorithm(di.FileType) != ChecksumAlgorithmType.Sha256)
            {
                // '{0}' is a managed binary compiled with an insecure (SHA-1) source code hashing algorithm.
                // SHA-1 is subject to collision attacks and its use can compromise supply chain integrity.
                // Pass '-checksumalgorithm:SHA256' on the csc.exe command-line or populate the project
                // <ChecksumAlgorithm> property with 'SHA256' to enable secure source code hashing.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultKind.Fail, context, null,
                                                             nameof(RuleResources.BA2004_Error_Managed),
                                                             context.TargetUri.GetFileName()));
                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(),
                                                         "managed"));
        }
        public override AnalysisApplicability CanAnalyzePE(PEBinary target, PropertiesDictionary policy, out string reasonForNotAnalyzing)
        {
            PE portableExecutable        = target.PE;
            AnalysisApplicability result = AnalysisApplicability.NotApplicableToSpecifiedTarget;

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

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

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

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

            reasonForNotAnalyzing = null;
            return(AnalysisApplicability.ApplicableToSpecifiedTarget);
        }
Ejemplo n.º 4
0
        public override void Analyze(BinaryAnalyzerContext context)
        {
            PEBinary target = context.PEBinary();
            PE       pe     = target.PE;

            // Analysis may return one or more failures, each of which uses a format
            // string stored in the MessageResourceNames array above to produce a result.
            // By convention, we recapitulate that format string when we return the
            // associated result, to document the specific failure or pass condition.

            if (!this.IsSecure(target))
            {
                // '{0}' is not secure for some reaons.
                // To resolve this issue, pass /beEvenMoreSecure on both the compiler
                // and linker command lines. Binaries also require the
                // /beSecure option in order to enable the enhanced setting.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(FailureLevel.Error, context, null,
                                                             nameof(RuleResources.BAXXXX_Error),
                                                             context.TargetUri.GetFileName()));
                return;
            }

            // '{0}' enables /beEvenMoreSecure on both the compiler and linker
            // command-lines, preventing a broad range of conditions that
            // bad actors can use to engage in their malignant, unfortunately
            // often-profitable foolishness.
            context.Logger.Log(this,
                               RuleUtilities.BuildResult(ResultKind.Pass, context, null,
                                                         nameof(RuleResources.BAXXXX_Pass),
                                                         context.TargetUri.GetFileName()));
        }
        public sealed override void Analyze(BinaryAnalyzerContext context)
        {
            // Uses PDB Parsing.
            BinaryParsers.PlatformSpecificHelpers.ThrowIfNotOnWindows();
            PEBinary target = context.PEBinary();

            if (!string.IsNullOrEmpty(target.Pdb?.LoadTrace))
            {
                LogPdbLoadTrace(
                    context,
                    pdbLoadSucceeded: true,
                    target.Pdb.LoadTrace);

                // Set the trace to null so that we only emit it once.
                target.Pdb.LoadTrace = null;
            }

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

            this.AnalyzePortableExecutableAndPdb(context);
        }
        public override AnalysisApplicability CanAnalyzePE(PEBinary target, PropertiesDictionary policy, out string reasonForNotAnalyzing)
        {
            PE portableExecutable        = target.PE;
            AnalysisApplicability result = AnalysisApplicability.NotApplicableToSpecifiedTarget;

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

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

            reasonForNotAnalyzing = MetadataConditions.ImageIsNativeUniversalWindowsPlatformBinary;
            if (portableExecutable.IsNativeUniversalWindowsPlatform)
            {
                return(result);
            }

            reasonForNotAnalyzing = null;
            return(AnalysisApplicability.ApplicableToSpecifiedTarget);
        }
Ejemplo n.º 7
0
        public override AnalysisApplicability CanAnalyzePE(PEBinary target, Sarif.PropertiesDictionary policy, out string reasonForNotAnalyzing)
        {
            PE portableExecutable        = target.PE;
            AnalysisApplicability result = AnalysisApplicability.NotApplicableToSpecifiedTarget;

            reasonForNotAnalyzing = MetadataConditions.ImageIsNot64BitBinary;
            if (portableExecutable.PEHeaders.PEHeader.Magic != PEMagic.PE32Plus)
            {
                return(result);
            }

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

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

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

            reasonForNotAnalyzing = null;
            return(AnalysisApplicability.ApplicableToSpecifiedTarget);
        }
Ejemplo n.º 8
0
        public override void Analyze(BinaryAnalyzerContext context)
        {
            PEBinary target   = context.PEBinary();
            PEHeader peHeader = target.PE.PEHeaders.PEHeader;

            if ((peHeader.DllCharacteristics & DllCharacteristics.NxCompatible /*IMAGE_DLLCHARACTERISTICS_NX_COMPAT*/) == 0)
            {
                // '{0}' is not marked NX compatible. The NXCompat bit, also known as "Data Execution Prevention"
                // (DEP) or "Execute Disable" (XD), is a processor feature that allows a program to mark a piece
                // of memory as non - executable. This helps mitigate memory corruption vulnerabilities by
                // preventing an attacker from supplying direct shellcode in their exploit, because the exploit
                // comes in the form of input data to the exploited program on a data segment, rather than on an
                // executable code segment. To resolve this issue, ensure that your tool chain is configured to mark
                //your binaries as NX compatible, e.g. by passing / NXCOMPAT to the C / C++ linker.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultLevel.Error, context, null,
                                                             nameof(RuleResources.BA2016_Error),
                                                             context.TargetUri.GetFileName()));
                return;
            }

            // '{0}' is marked as NX compatible.
            context.Logger.Log(this,
                               RuleUtilities.BuildResult(ResultLevel.Pass, context, null,
                                                         nameof(RuleResources.BA2016_Pass),
                                                         context.TargetUri.GetFileName()));
        }
Ejemplo n.º 9
0
        public override AnalysisApplicability CanAnalyzePE(PEBinary target, Sarif.PropertiesDictionary policy, out string reasonForNotAnalyzing)
        {
            PE portableExecutable        = target.PE;
            AnalysisApplicability result = AnalysisApplicability.NotApplicableToSpecifiedTarget;

            reasonForNotAnalyzing = MetadataConditions.ImageIsNot32BitBinary;
            if (portableExecutable.Machine != Machine.I386)
            {
                return(result);
            }

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

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

            reasonForNotAnalyzing = null;
            return(AnalysisApplicability.ApplicableToSpecifiedTarget);
        }
Ejemplo n.º 10
0
        public override void Analyze(BinaryAnalyzerContext context)
        {
            PEBinary target   = context.PEBinary();
            PEHeader peHeader = target.PE.PEHeaders.PEHeader;

            ulong imageBase = peHeader.ImageBase;

            if (imageBase <= 0xFFFFFFFF)
            {
                // '{0}' is a 64-bit image with a preferred base address below the 4GB boundary.
                // Having a preferred base address below this boundary triggers a compatibility
                // mode in Address Space Layout Randomization (ASLR) on recent versions of
                // Windows that reduces the number of locations to which ASLR may relocate the
                // binary. This reduces the effectiveness of ASLR at mitigating memory corruption
                // vulnerabilities. To resolve this issue, either use the default preferred base
                // address by removing any uses of /baseaddress from compiler command lines, or
                // /BASE from linker command lines (recommended), or configure your program to
                // start at a base address above 4GB when compiled for 64 bit platforms (by
                // changing the constant passed to /baseaddress / /BASE). Note that if you choose
                // to continue using a custom preferred base address, you will need to make this
                // modification only for 64-bit builds, as base addresses above 4GB are not valid
                // for 32-bit binaries.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(FailureLevel.Error, context, null,
                                                             nameof(RuleResources.BA2001_Error),
                                                             context.TargetUri.GetFileName()));
                return;
            }

            // '{0}' is marked as NX compatible.
            context.Logger.Log(this,
                               RuleUtilities.BuildResult(ResultKind.Pass, context, null,
                                                         nameof(RuleResources.BA2001_Pass),
                                                         context.TargetUri.GetFileName()));
        }
        public override AnalysisApplicability CanAnalyzePE(PEBinary target, Sarif.PropertiesDictionary policy, out string reasonForNotAnalyzing)
        {
            PE portableExecutable        = target.PE;
            AnalysisApplicability result = AnalysisApplicability.NotApplicableToSpecifiedTarget;

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

            reasonForNotAnalyzing = MetadataConditions.ImageLikelyLoads32BitProcess;
            if (portableExecutable.PEHeaders.PEHeader.Magic != PEMagic.PE32Plus)
            {
                // If the image's magic bytes are 'PE32', it is either a 32 bit binary (rule does not apply), or it is a managed binary compiled as AnyCpu.
                // If it's an AnyCPU managed binary, we need to do a bit more checking--if it has 'Prefers32Bit'/'Requires32Bit' flagged, it will probably
                // load as a 32 bit process.  If it doesn't, we're likely to load in a 64 bit process space on a 64 bit arch & want to ensure HighEntropyVA is enabled.
                if (!portableExecutable.IsManaged ||
                    portableExecutable.IsManaged && portableExecutable.PEHeaders.CorHeader.Flags.HasFlag(CorFlags.Requires32Bit))
                {
                    return(result);
                }
            }

            reasonForNotAnalyzing = MetadataConditions.ImageIsNotExe;
            if (!portableExecutable.PEHeaders.IsExe)
            {
                return(result);
            }

            reasonForNotAnalyzing = null;
            return(AnalysisApplicability.ApplicableToSpecifiedTarget);
        }
        private bool Validate32BitImage(BinaryAnalyzerContext context)
        {
            PEBinary    target       = context.PEBinary();
            PEHeader    peHeader     = target.PE.PEHeaders.PEHeader;
            SafePointer sp           = new SafePointer(target.PE.ImageBytes, peHeader.LoadConfigTableDirectory.RelativeVirtualAddress);
            SafePointer loadConfigVA = target.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 target.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;

            SafePointer boundsCheck = fileCookiePtr + 4;

            if (!CookieOffsetValid(context, boundsCheck))
            {
                return(false);
            }

            UInt32 cookie = BitConverter.ToUInt32(fileCookiePtr.GetBytes(4), 0);

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

            return(true);
        }
        public override AnalysisApplicability CanAnalyzePE(PEBinary target, Sarif.PropertiesDictionary policy, out string reasonForNotAnalyzing)
        {
            PE portableExecutable        = target.PE;
            AnalysisApplicability result = AnalysisApplicability.NotApplicableToSpecifiedTarget;

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

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

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

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

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

            Version minimumRequiredLinkerVersion = policy.GetProperty(MinimumRequiredLinkerVersion);

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

                return(result);
            }

            reasonForNotAnalyzing = MetadataConditions.ImageIsWixBinary;
            if (portableExecutable.IsWixBinary)
            {
                return(result);
            }

            reasonForNotAnalyzing = null;
            return(AnalysisApplicability.ApplicableToSpecifiedTarget);
        }
Ejemplo n.º 14
0
        public static bool IsPE(this BinaryAnalyzerContext target)
        {
            PEBinary ret = target.Binary as PEBinary;

            if (ret == null)
            {
                return(false);
            }
            return(true);
        }
        public override void Analyze(BinaryAnalyzerContext context)
        {
            PEBinary target = context.PEBinary();

            string         executableImportSection = null;
            PEHeader       peHeader    = target.PE.PEHeaders.PEHeader;
            DirectoryEntry importTable = peHeader.ImportTableDirectory;

            if (importTable.RelativeVirtualAddress != 0 && target.PE.PEHeaders.SectionHeaders != null)
            {
                int importSize = peHeader.ImportTableDirectory.Size;
                foreach (SectionHeader sectionHeader in target.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(FailureLevel.Error, context, null,
                                                             nameof(RuleResources.BA2010_Error),
                                                             context.TargetUri.GetFileName()));
                return;
            }

            // '{0}' does not have an imports section that is marked as executable.
            context.Logger.Log(this,
                               RuleUtilities.BuildResult(ResultKind.Pass, context, null,
                                                         nameof(RuleResources.BA2010_Pass),
                                                         context.TargetUri.GetFileName()));
        }
Ejemplo n.º 16
0
        public static PEBinary PEBinary(this BinaryAnalyzerContext target)
        {
            PEBinary ret = target.Binary as PEBinary;

            if (ret == null)
            {
                // Attempted to cast a binary target to a '{0}', but was unable to.  This indicates a programmer error in rules evaluating that sort of target.
                throw new InvalidOperationException(string.Format(SdkResources.IllegalBinaryCast, "PEBinary"));
            }
            return(ret);
        }
        private bool EnablesControlFlowGuard(PEBinary target)
        {
            PEHeader peHeader = target.PE.PEHeaders.PEHeader;

            if (((uint)peHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_CONTROLFLOWGUARD) == 0)
            {
                return(false);
            }

            var loadConfigRVA = new SafePointer(target.PE.ImageBytes, peHeader.LoadConfigTableDirectory.RelativeVirtualAddress);

            if (loadConfigRVA.Address == 0)
            {
                return(false);
            }

            SafePointer loadConfigVA = target.PE.RVA2VA(loadConfigRVA);

            if (target.PE.Is64Bit)
            {
                var loadConfig = new ImageLoadConfigDirectory64(peHeader, loadConfigVA);

                int   imageDirectorySize          = (int)loadConfig.GetField(ImageLoadConfigDirectory32.Fields.Size);
                ulong guardCFCheckFunctionPointer = (ulong)loadConfig.GetField(ImageLoadConfigDirectory64.Fields.GuardCFCheckFunctionPointer);
                ulong guardCFFunctionTable        = (ulong)loadConfig.GetField(ImageLoadConfigDirectory64.Fields.GuardCFFunctionTable);
                uint  guardFlags = (uint)loadConfig.GetField(ImageLoadConfigDirectory64.Fields.GuardFlags);

                if (imageDirectorySize >= IMAGE_LOAD_CONFIG_MINIMUM_SIZE_64 &&
                    guardCFCheckFunctionPointer != 0 &&
                    guardCFFunctionTable != 0 &&
                    (guardFlags & IMAGE_GUARD_CF_CHECKS) == IMAGE_GUARD_CF_CHECKS)
                {
                    return(true);
                }
            }
            else
            {
                var loadConfig = new ImageLoadConfigDirectory32(peHeader, loadConfigVA);

                int  imageDirectorySize          = (int)loadConfig.GetField(ImageLoadConfigDirectory32.Fields.Size);
                uint guardCFCheckFunctionPointer = (uint)loadConfig.GetField(ImageLoadConfigDirectory32.Fields.GuardCFCheckFunctionPointer);
                uint guardCFFunctionTable        = (uint)loadConfig.GetField(ImageLoadConfigDirectory32.Fields.GuardCFFunctionTable);
                uint guardFlags = (uint)loadConfig.GetField(ImageLoadConfigDirectory32.Fields.GuardFlags);

                if (imageDirectorySize >= IMAGE_LOAD_CONFIG_MINIMUM_SIZE_32 &&
                    guardCFCheckFunctionPointer != 0 &&
                    guardCFFunctionTable != 0 &&
                    (guardFlags & IMAGE_GUARD_CF_CHECKS) == IMAGE_GUARD_CF_CHECKS)
                {
                    return(true);
                }
            }
            return(false);
        }
Ejemplo n.º 18
0
        public override void Analyze(BinaryAnalyzerContext context)
        {
            PEBinary target = context.PEBinary();

            var sectionHeaders = target.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(ResultKind.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(FailureLevel.Error, context, null,
                                                         nameof(RuleResources.BA2019_Error),
                                                         context.TargetUri.GetFileName(),
                                                         badSectionsText));
        }
Ejemplo n.º 19
0
 public override AnalysisApplicability CanAnalyze(BinaryAnalyzerContext context, out string reasonForNotAnalyzing)
 {
     if (context.IsPE())
     {
         PEBinary target = context.PEBinary();
         return(this.CanAnalyzePE(target, context.Policy, out reasonForNotAnalyzing));
     }
     else
     {
         reasonForNotAnalyzing = MetadataConditions.ImageIsNotPE;
         return(AnalysisApplicability.NotApplicableToSpecifiedTarget);
     }
 }
Ejemplo n.º 20
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()));
        }
Ejemplo n.º 21
0
        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 override AnalysisApplicability CanAnalyzePE(PEBinary target, Sarif.PropertiesDictionary policy, out string reasonForNotAnalyzing)
        {
            PE portableExecutable        = target.PE;
            AnalysisApplicability result = AnalysisApplicability.NotApplicableToSpecifiedTarget;

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

            reasonForNotAnalyzing = null;
            return(AnalysisApplicability.ApplicableToSpecifiedTarget);
        }
        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);
        }
Ejemplo n.º 24
0
 // We may want to consider changing this to an extension/plugin model rather than a hardcoded list of supported binary parsers.
 // However, for now this will do.
 public static IBinary GetBinaryFromFile(Uri uri)
 {
     if (PEBinary.CanLoadBinary(uri))
     {
         return(new PEBinary(uri));
     }
     else if (ELFBinary.CanLoadBinary(uri))
     {
         return(new ELFBinary(uri));
     }
     else
     {
         return(null);
     }
 }
Ejemplo n.º 25
0
 // We may want to consider changing this to an extension/plugin model rather than a hardcoded list of supported binary parsers.
 // However, for now this will do.
 public static IBinary GetBinaryFromFile(Uri uri, string symbolPath = null, string localSymbolDirectories = null)
 {
     if (PEBinary.CanLoadBinary(uri))
     {
         return(new PEBinary(uri, symbolPath, localSymbolDirectories));
     }
     else if (ELFBinary.CanLoadBinary(uri))
     {
         return(new ELFBinary(uri));
     }
     else
     {
         return(null);
     }
 }
        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()));
        }
Ejemplo n.º 27
0
        internal static AnalysisApplicability CommonCanAnalyze(PEBinary target, out string reasonForNotAnalyzing)
        {
            PE portableExecutable        = target.PE;
            AnalysisApplicability result = AnalysisApplicability.NotApplicableToSpecifiedTarget;

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

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

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

            // .NET native compiled binaries are not fully /GS enabled. This is
            // considered reasonable, as the binaries themselves consist strictly
            // of cross-compiled MSIL. The supporting native libraries for these
            // applications exists in a separate (/GS enabled) native dll. We exclude
            // the native bootstrap exe from this check, as this loader should enforce
            // relevant security settings.
            reasonForNotAnalyzing = MetadataConditions.ImageIsDotNetNativeBinary;
            if (portableExecutable.IsDotNetNative && !portableExecutable.IsDotNetNativeBootstrapExe)
            {
                return(result);
            }

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

            reasonForNotAnalyzing = null;
            return(AnalysisApplicability.ApplicableToSpecifiedTarget);
        }
        private bool CookieOffsetValid(BinaryAnalyzerContext context, SafePointer boundsCheck)
        {
            if (boundsCheck.IsValid)
            {
                return(true);
            }

            PEBinary target = context.PEBinary();

            if (target.PE.IsPacked)
            {
                LogInvalidCookieOffsetForKnownPackedFile(context);
            }
            else
            {
                LogInvalidCookieOffset(context);
            }
            return(false);
        }
Ejemplo n.º 29
0
        public override AnalysisApplicability CanAnalyzePE(PEBinary target, Sarif.PropertiesDictionary policy, out string reasonForNotAnalyzing)
        {
            PE portableExecutable        = target.PE;
            AnalysisApplicability result = AnalysisApplicability.NotApplicableToSpecifiedTarget;

            // Review the range of metadata conditions and return NotApplicableToSpecifiedTarget
            // from this method for all cases where a binary is detected that is not valid to scan.
            //
            reasonForNotAnalyzing = MetadataConditions.ImageIsResourceOnlyBinary;
            if (portableExecutable.IsResourceOnly)
            {
                return(result);
            }

            // Here's an example of parameterizing a rule from input XML. In this example,
            // we enforce that the linker is of a minimal version, otherwise the scan will
            // not occur (because the toolset producing the binary is not sufficiently
            // current to enable the security mitigation).
            //
            Version minimumRequiredLinkerVersion = policy.GetProperty(MinimumRequiredLinkerVersion);

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

                return(result);
            }

            // If we get to this location, we've determined the binary is valid to analyze.
            // We clear the 'reasonForNotAnalyzing' output variable and return
            // ApplicableToSpecifiedTarget.
            //
            reasonForNotAnalyzing = null;
            return(AnalysisApplicability.ApplicableToSpecifiedTarget);
        }
        public override void Analyze(BinaryAnalyzerContext context)
        {
            PEBinary target = context.PEBinary();
            PE       pe     = target.PE;

            if (pe.IsKernelMode &&
                (pe.FileVersion.FileMajorPart < 10 || pe.FileVersion.FileBuildPart < 15000) &&
                pe.FileVersion.FileBuildPart < 15000)
            {
                // '{0}' is a kernel mode portable executable compiled for a
                // version of Windows that does not support the control flow
                // guard feature for kernel mode binaries.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultKind.NotApplicable, context, null,
                                                             nameof(RuleResources.BA2008_NotApplicable_UnsupportedKernelModeVersion),
                                                             context.TargetUri.GetFileName()));
            }

            if (!this.EnablesControlFlowGuard(target))
            {
                // '{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(FailureLevel.Error, context, null,
                                                             nameof(RuleResources.BA2008_Error),
                                                             context.TargetUri.GetFileName()));
                return;
            }

            // '{0}' enables the control flow guard mitigation.
            context.Logger.Log(this,
                               RuleUtilities.BuildResult(ResultKind.Pass, context, null,
                                                         nameof(RuleResources.BA2008_Pass),
                                                         context.TargetUri.GetFileName()));
        }