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

            CoffHeader      coffHeader      = context.PE.PEHeaders.CoffHeader;
            Characteristics characteristics = coffHeader.Characteristics;


            bool highEntropyVA = ((int)dllCharacteristics & 0x0020 /*IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA*/) == 0x0020;

            //  /LARGEADDRESSAWARE is necessary for HIGH_ENTROPY_VA to have effect
            bool largeAddressAware = (characteristics & Characteristics.LargeAddressAware /*IMAGE_FILE_LARGE_ADDRESS_AWARE*/) == Characteristics.LargeAddressAware;

            if (!highEntropyVA && !largeAddressAware)
            {
                // '{0}' does not declare itself as high entropy ASLR compatible. High entropy allows
                // Address Space Layout Randomization to be more effective in mitigating memory
                // corruption vulnerabilities. To resolve this issue, configure your tool chain to
                // mark the program high entropy compatible; e.g. by supplying /HIGHENTROPYVA as well
                // as /LARGEADDRESSAWARE to the C or C++ linker command line.
                context.Logger.Log(MessageKind.Fail, context,
                                   RuleUtilities.BuildMessage(context,
                                                              RulesResources.EnableHighEntropyVirtualAddresses_NeitherHighEntropyVANorLargeAddressAware_FAIL));
                return;
            }

            if (!highEntropyVA)
            {
                // '{0}' does not declare itself as high entropy ASLR compatible. High entropy allows
                // Address Space Layout Randomization to be more effective in mitigating memory
                // corruption vulnerabilities. To resolve this issue, configure your tool chain to
                // mark the program high entropy compatible; e.g. by supplying /HIGHENTROPYVA to the
                // C or C++ linker command line. (This image was determined to have been properly
                // compiled as /LARGEADDRESSAWARE.)
                context.Logger.Log(MessageKind.Fail, context,
                                   RuleUtilities.BuildMessage(context,
                                                              RulesResources.EnableHighEntropyVirtualAddresses_NoHighEntropyVA_FAIL));
                return;
            }

            if (!largeAddressAware)
            {
                // '{0}' does not declare itself as high entropy ASLR compatible. High entropy allows
                // Address Space Layout Randomization to be more effective in mitigating memory
                // corruption vulnerabilities. To resolve this issue, configure your tool chain to
                // mark the program high entropy compatible by supplying /LARGEADDRESSAWARE to the C
                // or C++ linker command line. (This image was determined to have been properly
                // compiled as /HIGHENTROPYVA.)
                context.Logger.Log(MessageKind.Fail, context,
                                   RuleUtilities.BuildMessage(context,
                                                              RulesResources.EnableHighEntropyVirtualAddresses_NoLargeAddressAware_FAIL));
                return;
            }

            //'{0}' is high entropy ASLR compatible.
            context.Logger.Log(MessageKind.Pass, context,
                               RuleUtilities.BuildMessage(context,
                                                          RulesResources.EnableHighEntropyVirtualAddresses_Pass));
        }
Example #2
0
        internal void Read(PeReader rdr)
        {
            rdr.SetPosition(0);
            if (t == PeFileType.Image)
            {
                dos = new DOSHeader(this);
                dos.Read(rdr);

                rdr.SetPosition(dos.PEHeaderOffset);
                sign = rdr.ReadBytes(4);

                pe = new PEHeader(this);
                pe.Read(rdr);

                op = new OptionalHeader(this);
                op.Read(rdr);

                sects = new SectionHeaders(this);
                sects.Read(rdr);

                certs = new CertificateDirectory(op.DataDirectories[DataDirectoryType.Certificate]);
                certs.Load(rdr, op.DataDirectories[DataDirectoryType.Certificate].Address.Value);
            }
            else if (t == PeFileType.Object)
            {
                pe = new PEHeader(this);
                pe.Read(rdr);

                sects = new SectionHeaders(this);
                sects.Read(rdr);
            }
        }
Example #3
0
        /// <summary>
        ///     Identifies if the specified executable is a Microsoft Portable Executable
        /// </summary>
        /// <returns><c>true</c> if the specified executable is a Microsoft Portable Executable, <c>false</c> otherwise.</returns>
        /// <param name="stream">Stream containing the executable.</param>
        public static bool Identify(FileStream stream)
        {
            FileStream baseStream     = stream;
            MZ         baseExecutable = new MZ(baseStream);

            if (!baseExecutable.Recognized)
            {
                return(false);
            }

            if (baseExecutable.Header.new_offset >= baseStream.Length)
            {
                return(false);
            }

            baseStream.Seek(baseExecutable.Header.new_offset, SeekOrigin.Begin);
            byte[] buffer = new byte[Marshal.SizeOf(typeof(PEHeader))];
            baseStream.Read(buffer, 0, buffer.Length);
            IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);

            Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
            PEHeader header = (PEHeader)Marshal.PtrToStructure(hdrPtr, typeof(PEHeader));

            Marshal.FreeHGlobal(hdrPtr);
            return(header.signature == SIGNATURE);
        }
Example #4
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()));
        }
Example #5
0
        private CLRHeader ReadCLRHeader(BinaryReader assemblyReader, PEHeader peHeader)
        {
            var clrDirectoryHeader = peHeader.Directories[(int)DataDirectoryName.CLRHeader];
            var clrDirectoryData   = ReadVirtualDirectory(assemblyReader, clrDirectoryHeader, peHeader.Sections);

            using (var reader = new BinaryReader(new MemoryStream(clrDirectoryData)))
            {
                var a = new CLRHeader
                {
                    HeaderSize               = reader.ReadUInt32(),
                    MajorRuntimeVersion      = reader.ReadUInt16(),
                    MinorRuntimeVersion      = reader.ReadUInt16(),
                    MetaDataDirectoryAddress = reader.ReadUInt32(),
                    MetaDataDirectorySize    = reader.ReadUInt32(),
                    Flags                          = reader.ReadUInt32(),
                    EntryPointToken                = reader.ReadUInt32(),
                    ResourcesDirectoryAddress      = reader.ReadUInt32(),
                    ResourcesDirectorySize         = reader.ReadUInt32(),
                    StrongNameSignatureAddress     = reader.ReadUInt32(),
                    StrongNameSignatureSize        = reader.ReadUInt32(),
                    CodeManagerTableAddress        = reader.ReadUInt32(),
                    CodeManagerTableSize           = reader.ReadUInt32(),
                    VTableFixupsAddress            = reader.ReadUInt32(),
                    VTableFixupsSize               = reader.ReadUInt32(),
                    ExportAddressTableJumpsAddress = reader.ReadUInt32(),
                    ExportAddressTableJumpsSize    = reader.ReadUInt32(),
                    ManagedNativeHeaderAddress     = reader.ReadUInt32(),
                    ManagedNativeHeaderSize        = reader.ReadUInt32()
                };
                return(a);
            }
        }
        public override void Analyze(BinaryAnalyzerContext context)
        {
            PEHeader peHeader = context.PE.PEHeaders.PEHeader;

            UInt64 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(ResultKind.Error, context, null,
                                                             nameof(RuleResources.BA2001_Fail)));
                return;
            }

            // '{0}' is marked as NX compatible.
            context.Logger.Log(this,
                               RuleUtilities.BuildResult(ResultKind.Pass, context, null,
                                                         nameof(RuleResources.BA2001_Pass)));
        }
        public override void Analyze(BinaryAnalyzerContext context)
        {
            PEHeader peHeader = context.PE.PEHeaders.PEHeader;

            // TODO: do we really require this check? What is the proposed fix to this issue?
            if (peHeader.SectionAlignment < PAGE_SIZE)
            {
                // '{0}' has a section alignment ({1}) that is less than page size ({2}).
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultKind.Error, context, null,
                                                             nameof(RuleResources.BA2021_Fail),
                                                             context.PE.FileName,
                                                             "0x" + peHeader.SectionAlignment.ToString("x"),
                                                             "0x" + PAGE_SIZE.ToString("x")));
                return;
            }

            var sectionHeaders = context.PE.PEHeaders.SectionHeaders;

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

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

                    if ((sectionHeader.SectionCharacteristics & wxFlags) == wxFlags)
                    {
                        badSections.Add(sectionHeader.Name);
                    }
                }
            }

            if (badSections.Count == 0)
            {
                // '{0}' contains no data or code sections marked as both shared and executable.
                context.Logger.Log(this,
                                   RuleUtilities.BuildResult(ResultKind.Pass, context, null,
                                                             nameof(RuleResources.BA2021_Pass)));
                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 give an attacker
            // executable location(s) to inject shellcode. To resolve this
            // issue, configure your toolchain 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.
            context.Logger.Log(this,
                               RuleUtilities.BuildResult(ResultKind.Error, context, null,
                                                         nameof(RuleResources.BA2021_Fail),
                                                         badSectionsText));
        }
Example #8
0
        public void PEHeader()
        {
            var peh = new PEHeader();

            peh.Machine         = Machine.I386;
            peh.Characteristics = ImageCharacteristics.Bit32Machine;

            Assert.AreEqual("I386 Bit32Machine Sections[0]", peh.ToString());
        }
Example #9
0
        /// <summary>Получить тело метода</summary>
        /// <returns>Массив байт описывающий CIL</returns>
        public Byte[] GetMethodBody()
        {
            PEHeader peHeader = this.Row.Row.Table.Root.Parent.Parent.Parent.Header;

            UInt32 padding      = this.Row.RVA + this.Header.HeaderSize;
            UInt32 methodLength = this.Header.CodeSize;

            return(peHeader.ReadBytes(padding, methodLength));
        }
        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);
        }
Example #11
0
        public PEHeaderModel(PEHeader peHeader, DosHeaderModel dosHeaderModel)
            : base("PE header")
        {
            this.peHeader = peHeader;

            this.Address = dosHeaderModel.lfanew;
            this.Length  = PEHeader.Size;

            BindAddressToDosHeaderlfanew(dosHeaderModel);
        }
        private bool EnablesControlFlowGuard(BinaryAnalyzerContext context)
        {
            PEHeader peHeader = context.PE.PEHeaders.PEHeader;

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

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

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

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

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

                Int32  imageDirectorySize          = (Int32)loadConfig.GetField(ImageLoadConfigDirectory32.Fields.Size);
                UInt64 guardCFCheckFunctionPointer = (UInt64)loadConfig.GetField(ImageLoadConfigDirectory64.Fields.GuardCFCheckFunctionPointer);
                UInt64 guardCFFunctionTable        = (UInt64)loadConfig.GetField(ImageLoadConfigDirectory64.Fields.GuardCFFunctionTable);
                UInt32 guardFlags = (UInt32)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
            {
                ImageLoadConfigDirectory32 loadConfig = new ImageLoadConfigDirectory32(peHeader, loadConfigVA);

                Int32  imageDirectorySize          = (Int32)loadConfig.GetField(ImageLoadConfigDirectory32.Fields.Size);
                UInt32 guardCFCheckFunctionPointer = (UInt32)loadConfig.GetField(ImageLoadConfigDirectory32.Fields.GuardCFCheckFunctionPointer);
                UInt32 guardCFFunctionTable        = (UInt32)loadConfig.GetField(ImageLoadConfigDirectory32.Fields.GuardCFFunctionTable);
                UInt32 guardFlags = (UInt32)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);
        }
        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()));
        }
Example #14
0
        /// <summary>Получить информацию по импорту</summary>
        /// <param name="offset">Сдвиг по PE файлу</param>
        /// <param name="isRva">Получить импорт по Relative Virtual Address адресу. В противном случае передаётся Virtual Address</param>
        /// <returns>Структура</returns>
        private WinNT.IMAGE_IMPORT_BY_NAME GetImageImport(UInt32 offset, Boolean isRva)
        {
            PEHeader header = this.Directory.Parent.Header;
            UInt64   forwarderString;

            if (header.Is64Bit)
            {
                WinNT.IMAGE_THUNK_DATA64 thunk64 = header.PtrToStructure <WinNT.IMAGE_THUNK_DATA64>(offset);
                forwarderString = thunk64.ForwarderString;                //TODO: Вот тут может быть ошибка
            }
            else
            {
                WinNT.IMAGE_THUNK_DATA32 thunk32 = header.PtrToStructure <WinNT.IMAGE_THUNK_DATA32>(offset);
                forwarderString = thunk32.ForwarderString;
            }

            WinNT.IMAGE_IMPORT_BY_NAME result;
            if ((forwarderString & 0x80000000) != 0)
            {
                result = new WinNT.IMAGE_IMPORT_BY_NAME()
                {
                    Hint = (UInt16)(forwarderString & 0x7FFFFFFF),
                    Name = null,
                };
            }
            else if ((forwarderString & 0x8000000000000000) != 0)
            {
                result = new WinNT.IMAGE_IMPORT_BY_NAME()
                {
                    Hint = (UInt16)(forwarderString & 0x7FFFFFFFFFFFFFFF),
                    Name = null,
                };
            }
            else
            {
                if (!isRva)
                {
                    UInt64 imageBase;
                    if (header.Is64Bit)
                    {
                        imageBase = header.HeaderNT64.OptionalHeader.ImageBase;
                    }
                    else
                    {
                        imageBase = header.HeaderNT32.OptionalHeader.ImageBase;
                    }

                    forwarderString -= imageBase;
                }

                result = header.PtrToStructure <WinNT.IMAGE_IMPORT_BY_NAME>((UInt32)forwarderString);
            }
            return(result);
        }
Example #15
0
        /// <summary>Get fat method header sections</summary>
        /// <returns>Method header sections</returns>
        public IEnumerable <MethodSection> GetSections()
        {
            UInt32 padding      = this.Row.RVA + this.Header.HeaderSize;
            UInt32 methodLength = this.Header.CodeSize;

            if ((this.Header.Format & Cor.CorILMethod.FatFormat) == Cor.CorILMethod.FatFormat &&
                (this.Header.Format & Cor.CorILMethod.MoreSects) == Cor.CorILMethod.MoreSects)
            {
                padding += methodLength;
                PEHeader header       = this.Row.Row.Table.Root.Parent.Parent.Parent.Header;
                Boolean  moreSections = true;

                while (moreSections)
                {
                    //Each section should start on a 4 byte boundary
                    //so let's read from the stream until we find the next boundary.
                    padding = NativeMethods.AlignToInt(padding);
                    Cor.CorILMethodSection section = header.PtrToStructure <Cor.CorILMethodSection>(padding);
                    padding += MethodBody.SizeOfMethodSection;

                    //I have never seen anything else than an exception handling section...
                    //According to the documentation "Currently, the method data sections
                    //are only used for exception tables."
                    if ((section.Kind & Cor.CorILMethod_Sect.EHTable) != Cor.CorILMethod_Sect.EHTable)
                    {
                        throw new NotImplementedException("Only exception table supported");
                    }

                    //Check whether more sections follow after this one.
                    moreSections = section.HasMoreSections;

                    Cor.CorILMethodExceptionFat[]   fat   = new Cor.CorILMethodExceptionFat[section.IsFatFormat ? section.ClauseNumber : 0];
                    Cor.CorILMethodExceptionSmall[] small = new Cor.CorILMethodExceptionSmall[section.IsFatFormat ? 0 : section.ClauseNumber];
                    //Let's read the clauses...
                    for (Int32 clauseIndex = 0; clauseIndex < section.ClauseNumber; clauseIndex++)
                    {
                        //The structure of the clauses are the same in both Fat and
                        //Small format, only the sizes are different.
                        if (section.IsFatFormat)
                        {
                            fat[clauseIndex] = header.PtrToStructure <Cor.CorILMethodExceptionFat>(padding);
                            padding         += MethodBody.SizeOfMethodExceptionFat;
                        }
                        else
                        {
                            small[clauseIndex] = header.PtrToStructure <Cor.CorILMethodExceptionSmall>(padding);
                            padding           += MethodBody.SizeOfMethodExceptionSmall;
                        }
                    }
                    yield return(new MethodSection(section, fat, small));
                }
            }
        }
Example #16
0
        protected override bool Parse(PEHeader peHeader)
        {
            #region Sanity checks
            if (peHeader == null) throw new ArgumentNullException(nameof(peHeader));
            #endregion

            Architecture = new Architecture(OS.All, GetCpu(peHeader.FileHeader.Machine));
            if (peHeader.Subsystem >= Subsystem.WindowsCui) NeedsTerminal = true;
            return peHeader.Is32BitHeader
                ? (peHeader.OptionalHeader32.CLRRuntimeHeader.VirtualAddress != 0)
                : (peHeader.OptionalHeader64.CLRRuntimeHeader.VirtualAddress != 0);
        }
Example #17
0
        public void Sizes()
        {
            Assert.Equal(20, CoffHeader.Size);
            Assert.Equal(224, PEHeader.Size(is32Bit: true));
            Assert.Equal(240, PEHeader.Size(is32Bit: false));
            Assert.Equal(8, SectionHeader.NameSize);
            Assert.Equal(40, SectionHeader.Size);

            Assert.Equal(128 + 4 + 20 + 224, new PEHeaderBuilder(Machine.I386).ComputeSizeOfPEHeaders(0));
            Assert.Equal(128 + 4 + 20 + 224 + 16, new PEHeaderBuilder(Machine.Amd64).ComputeSizeOfPEHeaders(0));
            Assert.Equal(128 + 4 + 20 + 224 + 16 + 40 * 1, new PEHeaderBuilder(Machine.Amd64).ComputeSizeOfPEHeaders(1));
            Assert.Equal(128 + 4 + 20 + 224 + 16 + 40 * 2, new PEHeaderBuilder(Machine.Amd64).ComputeSizeOfPEHeaders(2));
        }
Example #18
0
        /// <summary>
        /// Reads the contents of the PeCoff file in to our custom data structures
        /// </summary>
        /// <exception Cref="NotAManagedLibraryException">
        /// Thrown when a file which is not a managed PE file is loaded.
        /// </exception>
        private void ReadFileContents()
        {
            _fileContents = _fileSystem.ReadAllBytes(_fileName);

            Offset offset = _fileContents[PeCoffFile.PeSignitureOffsetLocation];

            offset += 4; // skip past the PE signature bytes

            FileHeader fileHeader = new FileHeader(_fileContents, offset);
            PEHeader   peHeader   = new PEHeader(_fileContents, offset);

            ReadSectionHeaders(fileHeader.NumberOfSections, offset);
            ReadDirectories(peHeader.DataDirectories);
        }
        public void PEHeader_When64Bit_OffsetIsMovedOn()
        {
            byte[] contents = new byte[112];
            Offset offset   = 0;

            // set it to a 64 magic
            contents[0] = 0x0b;
            contents[1] = 0x02;

            PEHeader header = new PEHeader(contents, offset);

            Assert.AreEqual(FileMagicNumbers.Bit64, header.Magic);
            Assert.AreEqual(112, header.Size);
        }
        public void PEHeader_When32Bit_OffsetIsMovedOn()
        {
            byte[] contents = new byte[96];
            Offset offset   = 0;

            // set it to a 32 magic
            contents[0] = 0x0b;
            contents[1] = 0x01;

            PEHeader header = new PEHeader(contents, offset);

            Assert.AreEqual(FileMagicNumbers.Bit32, header.Magic);
            Assert.AreEqual(96, header.Size);
        }
Example #21
0
 public PEFileParser(PEFile file, string filename, MemoryMappedViewAccessor accessor = null)
 {
     PEFile = file;
     Header = file.Header;
     if (accessor == null)
     {
         _stm     = File.OpenRead(filename);
         _memFile = MemoryMappedFile.CreateFromFile(_stm, null, 0, MemoryMappedFileAccess.Read, null, HandleInheritability.None, false);
         accessor = _memFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read);
         _isOwner = true;
     }
     Accessor = accessor;
     Filename = filename;
 }
Example #22
0
        public IPEResult Package(IPEInfo param)
        {
            var peHeader = new PEHeader
            {
                Characteristics    = param.Characteristics,
                Architecture       = param.Architecture,
                CreationTimePOSIX  = (uint)((DateTimeOffset)param.TimeStamp).ToUnixTimeSeconds(),
                NumberOfSections   = param.NumberOfSections,
                Magic              = BitConverter.ToUInt32(Encoding.ASCII.GetBytes("PE\0\0")),
                OptionalHeaderSize = (ushort)Marshal.SizeOf <PE32PlusOptionalHeader>()
            };

            return(new PEResult(StructConverter.GetBytes(peHeader)));
        }
Example #23
0
        public PEAssembly(StreamParser parser)
        {
            DOSHeader dosHeader = new DOSHeader(parser);
            parser.Seek(dosHeader.PEHeaderOffset);
            PEHeader peHeader = new PEHeader(parser);
            if (peHeader.SizeOfOptionalHeader == 0)
                throw new ParseFailedException("PE missing NT header");
            PEOptionalHeader peOptionalHeader = new PEOptionalHeader(parser);
            PESectionHeader[] sectionHeaders = new PESectionHeader[peHeader.NumberOfSections];
            for (int i = 0; i < peHeader.NumberOfSections; i++)
                sectionHeaders[i] = new PESectionHeader(parser);

            SectionHeaders = sectionHeaders;
            DataDirectory = peOptionalHeader.DataDirectory;
        }
        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()));
        }
        private bool Validate64BitImage(BinaryAnalyzerContext context)
        {
            PEHeader    peHeader     = context.PE.PEHeaders.PEHeader;
            SafePointer sp           = new SafePointer(context.PE.ImageBytes, peHeader.LoadConfigTableDirectory.RelativeVirtualAddress);
            SafePointer loadConfigVA = context.PE.RVA2VA(sp);
            ImageLoadConfigDirectory64 loadConfig = new ImageLoadConfigDirectory64(peHeader, loadConfigVA);

            UInt64 cookieVA    = (UInt64)loadConfig.GetField(ImageLoadConfigDirectory64.Fields.SecurityCookie);
            UInt64 baseAddress = peHeader.ImageBase;

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

            foreach (SectionHeader t in context.PE.PEHeaders.SectionHeaders)
            {
                sectionVA   = (UInt64)(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;
            UInt64 cookie = BitConverter.ToUInt64(fileCookiePtr.GetBytes(8), 0);

            if (cookie != StackProtectionUtilities.DefaultCookieX64)
            {
                LogFailure(context, cookie.ToString("x"));
                return(false);
            }
            return(true);
        }
Example #26
0
        public PEHeader ReadPEHeader(ushort headerAddress, BinaryReader _assemblyReader)
        {
            _assemblyReader.BaseStream.Seek(headerAddress, SeekOrigin.Begin);
            var header = new PEHeader
            {
                Signature             = _assemblyReader.ReadUInt32(),
                Machine               = _assemblyReader.ReadUInt16(),
                NumberOfSections      = _assemblyReader.ReadUInt16(),
                DateTimeStamp         = _assemblyReader.ReadUInt32(),
                PtrToSymbolTable      = _assemblyReader.ReadUInt32(),
                NumberOfSymbols       = _assemblyReader.ReadUInt32(),
                SizeOfOptionalHeaders = _assemblyReader.ReadUInt16(),
                Characteristics       = _assemblyReader.ReadUInt16(),
                OptionalMagic         = _assemblyReader.ReadUInt16(),
                MajorLinkerVersion    = _assemblyReader.ReadByte(),
                MinorLinkerVersion    = _assemblyReader.ReadByte(),
                SizeOfCode            = _assemblyReader.ReadUInt32(),
                SizeOfInitData        = _assemblyReader.ReadUInt32(),
                SizeOfUninitData      = _assemblyReader.ReadUInt32(),
                AddressOfEntryPoint   = _assemblyReader.ReadUInt32(),
                BaseOfCode            = _assemblyReader.ReadUInt32(),
                BaseOfData            = _assemblyReader.ReadUInt32(),
                ImageBase             = _assemblyReader.ReadUInt32(),
                SectionAlignment      = _assemblyReader.ReadUInt32(),
                FileAlignment         = _assemblyReader.ReadUInt32(),
                MajorOSVersion        = _assemblyReader.ReadUInt16(),
                MinorOSVersion        = _assemblyReader.ReadUInt16(),
                MajorImageVersion     = _assemblyReader.ReadUInt16(),
                MinorImageVersion     = _assemblyReader.ReadUInt16(),
                MajorSubsystemVersion = _assemblyReader.ReadUInt16(),
                MinorSubsystemVersion = _assemblyReader.ReadUInt16(),
                Reserved1             = _assemblyReader.ReadUInt32(),
                SizeOfImage           = _assemblyReader.ReadUInt32(),
                SizeOfHeaders         = _assemblyReader.ReadUInt32(),
                PEChecksum            = _assemblyReader.ReadUInt32(),
                Subsystem             = _assemblyReader.ReadUInt16(),
                DLLCharacteristics    = _assemblyReader.ReadUInt16(),
                SizeOfStackReserve    = _assemblyReader.ReadUInt32(),
                SizeOfStackCommit     = _assemblyReader.ReadUInt32(),
                SizeOfHeapReserve     = _assemblyReader.ReadUInt32(),
                SizeOfHeapCommit      = _assemblyReader.ReadUInt32(),
                LoaderFlags           = _assemblyReader.ReadUInt32(),
                DirectoryLength       = _assemblyReader.ReadUInt32()
            };

            return(header);
        }
Example #27
0
        public static int GetTypeLen(this ImageFieldData fi)
        {
            int      res    = 0;
            bool     b64bit = false;
            PEHeader ioh    = fi.ParentHeader;

            if (ioh != null)
            {
                b64bit = (ioh.Magic == PEMagic.PE32Plus);
            }

            if (b64bit && fi.Is32BitOnly)
            {
                return(0);
            }

            switch (fi.Type)
            {
            case Type.BYTE: res = 1; break;

            case Type.SBYTE: res = 1; break;

            case Type.UINT16: res = 2; break;

            case Type.INT16: res = 2; break;

            case Type.UINT32: res = 4; break;

            case Type.INT32: res = 4; break;

            case Type.UINT64: res = 8; break;

            case Type.INT64: res = 8; break;

            case Type.POINTER: res = 4; break;

            case Type.HEADER: res = fi.Header.Size; break;

            case Type.NATIVEINT: res = b64bit ? 8 : 4; break;

            default: throw new Exception("Unknown type");
            }

            return(res);
        }
Example #28
0
    protected virtual bool Parse(PEHeader peHeader)
    {
        #region Sanity checks
        if (peHeader == null)
        {
            throw new ArgumentNullException(nameof(peHeader));
        }
        #endregion

        Architecture = new(OS.Windows, GetCpu(peHeader.FileHeader.Machine));
        if (peHeader.Subsystem >= PESubsystem.WindowsCui)
        {
            NeedsTerminal = true;
        }
        return(peHeader.Is32BitHeader
            ? (peHeader.OptionalHeader32.CLRRuntimeHeader.VirtualAddress == 0)
            : (peHeader.OptionalHeader64.CLRRuntimeHeader.VirtualAddress == 0));
    }
Example #29
0
        private static bool TestChecksumAndAuthenticodeSignature(Stream peStream, byte[] privateKeyOpt = null)
        {
            var  peHeaders        = new PEHeaders(peStream);
            bool is32bit          = peHeaders.PEHeader.Magic == PEMagic.PE32;
            uint expectedChecksum = peHeaders.PEHeader.CheckSum;
            int  peHeadersSize    = peHeaders.PEHeaderStartOffset + PEHeader.Size(is32bit) + SectionHeader.Size * peHeaders.SectionHeaders.Length;

            peStream.Position = 0;

            if (expectedChecksum == 0)
            {
                // not signed
                return(false);
            }

            int peSize  = (int)peStream.Length;
            var peImage = new BlobBuilder(peSize);

            Assert.Equal(peSize, peImage.TryWriteBytes(peStream, peSize));

            var buffer       = peImage.GetBlobs().Single().Buffer;
            var checksumBlob = new Blob(buffer, peHeaders.PEHeaderStartOffset + PEHeader.OffsetOfChecksum, sizeof(uint));

            uint checksum = PEBuilder.CalculateChecksum(peImage, checksumBlob);

            Assert.Equal(expectedChecksum, checksum);

            // validate signature:
            if (privateKeyOpt != null)
            {
                // signature is calculated with checksum zeroed:
                new BlobWriter(checksumBlob).WriteUInt32(0);

                int snOffset;
                Assert.True(peHeaders.TryGetDirectoryOffset(peHeaders.CorHeader.StrongNameSignatureDirectory, out snOffset));
                var snBlob            = new Blob(buffer, snOffset, peHeaders.CorHeader.StrongNameSignatureDirectory.Size);
                var expectedSignature = snBlob.GetBytes().ToArray();
                var signature         = SigningUtilities.CalculateRsaSignature(PEBuilder.GetContentToSign(peImage, peHeadersSize, peHeaders.PEHeader.FileAlignment, snBlob), privateKeyOpt);
                AssertEx.Equal(expectedSignature, signature);
            }

            return(true);
        }
Example #30
0
        public static object SafePointerToType(this SafePointer sp, ImageFieldData fi)
        {
            object res = null;

            switch (fi.Type)
            {
            case Type.BYTE: res = (byte)sp; break;

            case Type.SBYTE: res = (sbyte)(byte)sp; break;

            case Type.UINT16: res = (UInt16)sp; break;

            case Type.INT16: res = (Int16)(UInt16)sp; break;

            case Type.UINT32: res = (UInt32)sp; break;

            case Type.UINT64: res = (UInt64)sp; break;

            case Type.INT32: res = (Int32)(UInt32)sp; break;

            case Type.INT64: res = (Int64)(UInt64)sp; break;

            case Type.POINTER: res = new SafePointer(sp._array, sp._stream, (Int32)(UInt32)sp); break;

            case Type.HEADER: res = fi.Header.Create(fi.ParentHeader, sp); break;

            case Type.NATIVEINT:
                PEHeader ioh = fi.ParentHeader;
                if ((ioh != null) && (ioh.Magic == PEMagic.PE32Plus))
                {
                    res = (UInt64)sp;
                }
                else
                {
                    res = (UInt32)sp;
                }
                break;

            default: throw new Exception("Unknown type");
            }
            return(res);
        }
Example #31
0
        static void WritePEHeader(PEHeader peHeader, BinaryStreamWriter writer)
        {
            writer.WriteUInt32((uint)PESignature.PE00);
            writer.WriteUInt16((ushort)peHeader.Machine);
            writer.WriteUInt16(peHeader.NumberOfSections);

            double timestampDouble = (peHeader.Timestamp - TimestampEpochUTC).TotalSeconds;
            uint   timestampNum    = checked ((uint)timestampDouble);

            if (timestampDouble - timestampNum > 0.5)
            {
                timestampNum++;
            }
            writer.WriteUInt32(timestampNum);

            writer.WriteUInt32(peHeader.PointerToSymbolTable);
            writer.WriteUInt32(peHeader.NumberOfSymbols);
            writer.WriteUInt16(peHeader.SizeOfOptionalHeader);
            writer.WriteUInt16((ushort)peHeader.Characteristics);
        }
Example #32
0
        public static void Init(byte[] input)
        {
            // find headers entry
            header = PEHeader.Find(input);
            if (header == null)
            {
                throw new Exception("Failed to find PE header! Unsupported Version?");
            }

            var prevSec = header.Sections.Last();

            // new code section
            ucpSec = new SectionHeader(".ucp")
            {
                VirtAddr = prevSec.VirtAddr + GetMultiples(prevSec.VirtSize, header.SectionAlignment),
                RawAddr  = prevSec.RawAddr + GetMultiples(prevSec.RawSize, header.FileAlignment),

                Characteristics = 0xE0000020 // writable, //0x60000020, // executable, readable, contains code
            };
        }
Example #33
0
 /// <summary>
 /// 获得PE的文件头
 /// </summary>
 /// <param name="Fileindex"></param>
 /// <returns></returns>
 private void LoadPEHeader()
 {
     _PEHeader = new PEHeader();
     _PEHeader.FileStarIndex = PEFileIndex;
     Loadbyte(ref _PEHeader.Header);
     Loadbyte(ref _PEHeader.Machine);
     Loadbyte(ref _PEHeader.NumberOfSections);
     Loadbyte(ref _PEHeader.TimeDateStamp);
     Loadbyte(ref _PEHeader.PointerToSymbolTable);
     Loadbyte(ref _PEHeader.NumberOfSymbols);
     Loadbyte(ref _PEHeader.SizeOfOptionalHeader);
     Loadbyte(ref _PEHeader.Characteristics);
     _PEHeader.FileEndIndex = PEFileIndex;
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="bytes"></param>
 /// <param name="IconFilePath"></param>
 /// <returns></returns>
 private static bool TryExtractIcon(byte[] bytes, string IconFilePath)
 {
     try
     {
         PEHeader header = new PEHeader(bytes);
         
         return header.TryExtractIconFromExe(bytes, IconFilePath);
     }
     catch 
     {
         return false;
     }
 }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="SubsystemType"></param>
        /// <returns></returns>
        private static bool TryGetSubsystemType(byte[] bytes, out SubsystemTypes SubsystemType)
        {
            SubsystemType = SubsystemTypes.Unknown;

            try
            {
                PEHeader header = new PEHeader(bytes);

                SubsystemType = header.SubsystemType;

                return true;
            }
            catch 
            {
                return false;
            }
        }