예제 #1
0
        static void PrintInspectionPE(Stream stream)
        {
            var metadata        = Inspector.InspectAsPE(stream).Metadata;
            var msDosStubHeader = metadata.OfType <Packager.PE.MsDosStubHeader>().FirstOrDefault();

            if (msDosStubHeader.Equals(default(Packager.PE.MsDosStubHeader)))
            {
                Console.Out.WriteLine("No MSDOS stub header found.");
            }

            Console.Out.WriteLine("MSDOS Header:");
            stream.Seek(0, SeekOrigin.Begin);
            var first2 = new byte[2];

            stream.Read(first2, 0, 2);
            Console.Out.WriteLine($"  Magic:   {first2.Select(b => $"{b:x2}").Aggregate((c, n) => $"{c} {n}")}");
            Console.Out.WriteLine($"  PE Header Offset:                  0x{msDosStubHeader.e_lfanew:x}");
            if (msDosStubHeader.e_lfanew % 8 != 0)
            {
                Console.Error.WriteLine("WARN: PE header should be aligned to an 8-byte boundary.");
            }

            {
                var peHeader = metadata.OfType <Packager.PE.PEHeader>().FirstOrDefault();
                if (peHeader.Equals(default(Packager.PE.PEHeader)))
                {
                    Console.Out.WriteLine("No PE header found.");
                }
                else
                {
                    stream.Seek(msDosStubHeader.e_lfanew, SeekOrigin.Begin);
                    stream.Read(first2, 0, 2);
                    Console.Out.WriteLine("\r\nPE Header:");
                    Console.Out.WriteLine($"  Magic:   {first2.Select(b => $"{b:x2}").Aggregate((c, n) => $"{c} {n}")}");
                    Console.Out.WriteLine($"  Machine:                           {PackagerUtility.GetEnumDescription<MachineType>(peHeader.mMachine)}");
                    Console.Out.WriteLine($"  Number of sections:                {peHeader.mNumberOfSections}");
                    var ts = DateTime.UnixEpoch.AddSeconds(peHeader.mTimeDateStamp).ToUniversalTime();
                    Console.Out.WriteLine($"  Timestamp:                         {ts.ToLongDateString()} {ts.ToLongTimeString()} UTC");
                    Console.Out.WriteLine($"  Pointer to symbol table:           0x{peHeader.mPointerToSymbolTable:x}");
                    Console.Out.WriteLine($"  Number of symbols:                 {peHeader.mNumberOfSymbols}");
                    Console.Out.WriteLine($"  Size of optional PE header:        {peHeader.mSizeOfOptionalHeader} (bytes)");
                    Console.Out.WriteLine($"  Characteristics:                   {PackagerUtility.GetEnumFlagsShortName<PECharacteristics>(peHeader.mCharacteristics, ", ")}");
                }
            }

            {
                var pe32 = metadata.OfType <Packager.PE.PEHeaderOption32>().FirstOrDefault();
                if (!pe32.Equals(default(Packager.PE.PEHeaderOption32)))
                {
                    Console.Out.WriteLine("\r\nPE Optional 32-bit Header:");
                    Console.Out.WriteLine($"  Linker version:                    {pe32.mMajorLinkerVersion}.{pe32.mMinorLinkerVersion}");
                    Console.Out.WriteLine($"  Size of code:                      {pe32.mSizeOfCode} (bytes)");
                    Console.Out.WriteLine($"  Size of initialized data:          {pe32.mSizeOfInitializedData} (bytes)");
                    Console.Out.WriteLine($"  Size of uninitialized data:        {pe32.mSizeOfUninitializedData} (bytes)");
                    Console.Out.WriteLine($"  Entry point:                       0x{pe32.mAddressOfEntryPoint:x}");
                    Console.Out.WriteLine($"  Base address of code section:      0x{pe32.mBaseOfCode:x}");
                    Console.Out.WriteLine($"  Base address of data section:      0x{pe32.mBaseOfData:x}");
                    Console.Out.WriteLine($"  Base address of image:             0x{pe32.mImageBase:x}");
                    Console.Out.WriteLine($"  Section alignment:                 {pe32.mSectionAlignment}");
                    if (pe32.mSectionAlignment < pe32.mFileAlignment)
                    {
                        Console.Error.WriteLine($"ERROR: Section alignment value must be greater than or equal to the file alignment!");
                    }
                    Console.Out.WriteLine($"  File alignment:                    {pe32.mFileAlignment}{(pe32.mFileAlignment != 512 ? " (Default is 512)" : string.Empty)}");
                    if (pe32.mFileAlignment < 512 || pe32.mFileAlignment > 65536 || (pe32.mFileAlignment & (pe32.mFileAlignment - 1)) != 0)
                    {
                        Console.Error.WriteLine($"WARN: The value should be a power of 2 between 512 and 64K (inclusive).");
                    }
                    Console.Out.WriteLine($"  Operating system version:          {pe32.mMajorOperatingSystemVersion}.{pe32.mMinorOperatingSystemVersion} ({GetWindowsVersion(pe32.mMajorOperatingSystemVersion, pe32.mMinorOperatingSystemVersion)})");
                    Console.Out.WriteLine($"  Image version:                     {pe32.mMajorImageVersion}.{pe32.mMinorImageVersion}");
                    Console.Out.WriteLine($"  Subsystem version:                 {pe32.mMajorSubsystemVersion}.{pe32.mMinorSubsystemVersion}");
                    if (pe32.mWin32VersionValue != 0)
                    {
                        Console.Out.WriteLine($"  Win32 version:                     {pe32.mWin32VersionValue}");
                        Console.Error.WriteLine($"ERROR: This member is reserved and must be 0!");
                    }
                    Console.Out.WriteLine($"  Size of image:                     {pe32.mSizeOfImage} (bytes)");
                    if (pe32.mSizeOfImage % pe32.mSectionAlignment != 0)
                    {
                        Console.Error.WriteLine($"ERROR: Size of image must be a multiple of the section alignment!");
                    }
                    Console.Out.WriteLine($"  Size of headers:                   {pe32.mSizeOfHeaders} (bytes)");
                    Console.Out.WriteLine($"  Checksum:                          0x{pe32.mCheckSum:x}");
                    Console.Out.WriteLine($"  Subsystem:                         {PackagerUtility.GetEnumDescription<Subsystem>(pe32.mSubsystem)} (0x{pe32.mSubsystem:x})");
                    Console.Out.WriteLine($"  DLL characteristics:               {PackagerUtility.GetEnumFlagsShortName<DllCharacteristics>(pe32.mDllCharacteristics, ", ")}");
                    Console.Out.WriteLine($"  Size of stack reserve:             {pe32.mSizeOfStackReserve} (bytes)");
                    Console.Out.WriteLine($"  Size of stack commit:              {pe32.mSizeOfStackCommit} (bytes)");
                    Console.Out.WriteLine($"  Size of heap reserve:              {pe32.mSizeOfHeapReserve} (bytes)");
                    Console.Out.WriteLine($"  Size of heap commit:               {pe32.mSizeOfHeapCommit} (bytes)");
                    Console.Out.WriteLine($"  Loader flags (obsolete):           0x{pe32.mLoaderFlags:x}");
                    Console.Out.WriteLine($"  Number of directory entries:       {pe32.mNumberOfRvaAndSizes}");
                }
            }

            {
                var pe64 = metadata.OfType <Packager.PE.PEHeaderOption64>().FirstOrDefault();
                if (!pe64.Equals(default(Packager.PE.PEHeaderOption64)))
                {
                    Console.Out.WriteLine("\r\nPE Optional 64-bit Header:");
                    Console.Out.WriteLine($"  Linker major version:              {pe64.mMajorLinkerVersion}");
                    Console.Out.WriteLine($"  Linker minor version:              {pe64.mMinorLinkerVersion}");
                    Console.Out.WriteLine($"  Size of code:                      {pe64.mSizeOfCode} (bytes)");
                    Console.Out.WriteLine($"  Size of initialized data:          {pe64.mSizeOfInitializedData} (bytes)");
                    Console.Out.WriteLine($"  Size of uninitialized data:        {pe64.mSizeOfUninitializedData} (bytes)");
                    Console.Out.WriteLine($"  Entry point:                       0x{pe64.mAddressOfEntryPoint:x}");
                    Console.Out.WriteLine($"  Base address of code section:      0x{pe64.mBaseOfCode:x}");
                    Console.Out.WriteLine($"  Base address of image:             0x{pe64.mImageBase:x}");
                    Console.Out.WriteLine($"  Section alignment:                 {pe64.mSectionAlignment}");
                    if (pe64.mSectionAlignment < pe64.mFileAlignment)
                    {
                        Console.Error.WriteLine($"ERROR: Section alignment value must be greater than or equal to the file alignment!");
                    }
                    Console.Out.WriteLine($"  File alignment:                    {pe64.mFileAlignment}{(pe64.mFileAlignment != 512 ? " (Default is 512)" : string.Empty)}");
                    if (pe64.mFileAlignment < 512 || pe64.mFileAlignment > 65536 || (pe64.mFileAlignment & (pe64.mFileAlignment - 1)) != 0)
                    {
                        Console.Error.WriteLine($"WARN: The value should be a power of 2 between 512 and 64K (inclusive).");
                    }
                    Console.Out.WriteLine($"  Operating system version:          {pe64.mMajorOperatingSystemVersion}.{pe64.mMinorOperatingSystemVersion} ({GetWindowsVersion(pe64.mMajorOperatingSystemVersion, pe64.mMinorOperatingSystemVersion)})");
                    Console.Out.WriteLine($"  Image version:                     {pe64.mMajorImageVersion}.{pe64.mMinorImageVersion}");
                    Console.Out.WriteLine($"  Subsystem version:                 {pe64.mMajorSubsystemVersion}.{pe64.mMinorSubsystemVersion}");
                    if (pe64.mWin32VersionValue != 0)
                    {
                        Console.Out.WriteLine($"  Win32 version:                     {pe64.mWin32VersionValue}");
                        Console.Error.WriteLine($"ERROR: This member is reserved and must be 0!");
                    }
                    Console.Out.WriteLine($"  Size of image:                     {pe64.mSizeOfImage} (bytes)");
                    if (pe64.mSizeOfImage % pe64.mSectionAlignment != 0)
                    {
                        Console.Error.WriteLine($"ERROR: Size of image must be a multiple of the section alignment!");
                    }
                    Console.Out.WriteLine($"  Size of headers:                   {pe64.mSizeOfHeaders} (bytes)");
                    Console.Out.WriteLine($"  Checksum:                          0x{pe64.mCheckSum:x}");
                    Console.Out.WriteLine($"  Subsystem:                         {PackagerUtility.GetEnumDescription<Subsystem>(pe64.mSubsystem)} (0x{pe64.mSubsystem:x})");
                    Console.Out.WriteLine($"  DLL characteristics:               {PackagerUtility.GetEnumFlagsShortName<DllCharacteristics>(pe64.mDllCharacteristics, ", ")}");
                    Console.Out.WriteLine($"  Size of stack reserve:             {pe64.mSizeOfStackReserve} (bytes)");
                    Console.Out.WriteLine($"  Size of stack commit:              {pe64.mSizeOfStackCommit} (bytes)");
                    Console.Out.WriteLine($"  Size of heap reserve:              {pe64.mSizeOfHeapReserve} (bytes)");
                    Console.Out.WriteLine($"  Size of heap commit:               {pe64.mSizeOfHeapCommit} (bytes)");
                    Console.Out.WriteLine($"  Loader flags (obsolete):           0x{pe64.mLoaderFlags:x}");
                    Console.Out.WriteLine($"  Number of directory entries:       {pe64.mNumberOfRvaAndSizes}");
                }
            }

            {
                var sht = metadata.OfType <SectionHeaderTable>().FirstOrDefault();
                Console.Out.WriteLine($"\r\nSection Headers:");
                Console.Out.WriteLine($"  [Nr] Name      VirtualAddress  VirtualSize");
                Console.Out.WriteLine($"       Characteristics");
                var i = 0;
                foreach (var sh in sht)
                {
                    var name = System.Text.Encoding.ASCII.GetString(BitConverter.GetBytes(sh.Name).TakeWhile(b => b != 0x00).ToArray());
                    Console.Out.WriteLine($"  [{i.ToString().PadLeft(2)}] {name.LeftAlignToSize(8)}  {sh.VirtualAddress.RightAlignHexToSize().LeftAlignToSize(14)}  {sh.VirtualSize.RightAlignHexToSize()}");
                    var flagString = PackagerUtility.GetEnumFlagsShortName <SectionHeaderCharacteristics>(sh.Characteristics, ", ");
                    Console.Out.WriteLine($"       {flagString}");

                    i++;
                }
            }

            {
                var dd = metadata.OfType <PEDataDictionary>().FirstOrDefault();
                if (!dd.Equals(default(PEDataDictionary)))
                {
                    Console.Out.WriteLine("\r\nPE Data Dictionaries:");
                    var i = 0;
                    foreach (var dde in dd)
                    {
                        if (dde.RelativeVirtualAddress > 0)
                        {
                            Console.Out.WriteLine($"  {Enum.GetName(typeof(PEDataDictionaryIndex), i)?.LeftAlignToSize(30) ?? string.Empty} at 0x{dde.RelativeVirtualAddress:x}");
                        }
                        i++;
                    }
                }
            }

            var verbosity = 1;
            {
                var idt  = metadata.OfType <PEImportDirectoryTable>().FirstOrDefault();
                var ilts = metadata.OfType <PEImportLookupTable>().ToArray();

                if (idt == default(PEImportDirectoryTable))
                {
                    Console.Error.WriteLine("WARN: Missing Import Directory Table..");
                }
                else
                {
                    if (ilts.Length == 0)
                    {
                        Console.Error.WriteLine("ERROR: Missing Import Lookup Table!");
                    }
                    if (ilts.Length != idt.Count)
                    {
                        Console.Error.WriteLine($"ERROR: Import Lookup Table count ({ilts.Length}) did not match directory table entry count ({idt.Count})!");
                    }

                    Console.Out.WriteLine("\r\nImport Directory Table:");
                    var i = 0;
                    foreach (var ide in idt)
                    {
                        Console.Out.WriteLine($"  {ide.Name}");
                        if (verbosity > 1)
                        {
                            var missingNames = 0;
                            foreach (var ile in ilts[i])
                            {
                                if (!string.IsNullOrEmpty(ile.Value))
                                {
                                    Console.Out.WriteLine($"    {ile.Value}");
                                }
                                else
                                {
                                    missingNames++;
                                }
                            }

                            if (missingNames > 0)
                            {
                                Console.Out.WriteLine($"   ...and {missingNames} unresolvable ordinal imports");
                            }
                        }
                        i++;
                    }
                }
            }
        }
예제 #2
0
        static void PrintInspectionElf64(Stream stream)
        {
            var metadata = Inspector.InspectAsElf64(stream).Metadata;
            var header   = metadata.OfType <Packager.Elf.Elf64.Header64>().FirstOrDefault();

            if (header.Equals(default(Packager.Elf.Elf64.Header64)))
            {
                Console.Out.WriteLine("No Elf64 header found.");
            }

            Console.Out.WriteLine("ELF Header:");
            stream.Seek(0, SeekOrigin.Begin);
            var first16 = new byte[16];

            stream.Read(first16, 0, 16);
            var first16String = first16.Select(b => $"{b:x2}").Aggregate((c, n) => $"{c} {n}");

            Console.Out.WriteLine($"  Magic:   {first16String}");
            Console.Out.WriteLine($"  Class:                             {PackagerUtility.GetEnumDescription(header.EI_CLASS)}");
            Console.Out.WriteLine($"  Data:                              {PackagerUtility.GetEnumDescription(header.EI_DATA)}");
            Console.Out.WriteLine($"  Version:                           {PackagerUtility.GetEnumDescription(header.EI_VERSION)}");
            Console.Out.WriteLine($"  OS/ABI:                            {PackagerUtility.GetEnumDescription(header.EI_OSABI)}");
            Console.Out.WriteLine($"  ABI Version:                       {header.EI_ABIVERSION}");
            Console.Out.WriteLine($"  Type:                              {PackagerUtility.GetEnumDescription(header.E_TYPE)}");
            Console.Out.WriteLine($"  Machine:                           {PackagerUtility.GetEnumDescription(header.E_MACHINE)}");
            Console.Out.WriteLine($"  Version:                           {PackagerUtility.GetEnumDescription(header.E_VERSION)}");
            Console.Out.WriteLine($"  Entry point address:               0x{header.E_ENTRY:x}");
            Console.Out.WriteLine($"  Start of program headers:          {header.E_PHOFF} (bytes into file)");
            Console.Out.WriteLine($"  Start of section headers:          {header.E_SHOFF} (bytes into file)");
            Console.Out.WriteLine($"  Flags:                             0x{header.E_FLAGS:x}");
            Console.Out.WriteLine($"  Size of this header:               {header.E_EHSIZE} (bytes)");
            Console.Out.WriteLine($"  Size of program headers:           {header.E_PHENTSIZE} (bytes)");
            Console.Out.WriteLine($"  Number of program headers:         {header.E_PHNUM}");
            Console.Out.WriteLine($"  Size of section headers:           {header.E_SHENTSIZE} (bytes)");
            Console.Out.WriteLine($"  Number of section headers:         {header.E_SHNUM}");
            Console.Out.WriteLine($"  Section header string table index: {header.E_SHSTRNDX}");

            Console.Out.WriteLine($"\r\nSection Headers:");
            Console.Out.WriteLine($"  [Nr] Name              Type             Address           Offset");
            Console.Out.WriteLine($"       Size              EntSize          Flags  Link  Info  Align");
            var  sectionHeaders               = metadata.OfType <Packager.Elf.Elf64.SectionHeader64>().ToArray();
            var  sectionHeaderNames           = new Dictionary <UInt32, string>();
            long?sectionHeaderNameTableOffset = header.E_SHSTRNDX == SpecialSectionIndexes.SHN_UNDEF ? default(long?) : (long)sectionHeaders[header.E_SHSTRNDX].SH_OFFSET;
            var  i = 0;

            foreach (var sh in sectionHeaders)
            {
                string name = "<MISSING TABLE>";
                if (sectionHeaderNameTableOffset != null)
                {
                    stream.Seek((long)sectionHeaderNameTableOffset + sh.SH_NAME, SeekOrigin.Begin);
                    name = stream.ReadNulTerminatedString();
                    sectionHeaderNames.Add(sh.SH_NAME, name);
                }

                var flagString = PackagerUtility.GetEnumFlagsShortName <SectionHeaderFlags>(sh.SH_FLAGS);

                Console.Out.WriteLine($"  [{i.ToString().PadLeft(2)}] {name.LeftAlignToSize(17)} {PackagerUtility.GetEnumAttributeValue<SectionHeaderType, ShortNameAttribute>(sh.SH_TYPE, sn => sn.DisplayName).LeftAlignToSize(16)} {sh.SH_ADDR.RightAlignHexToSize()}  {sh.SH_OFFSET.RightAlignHexToSize()}");
                Console.Out.WriteLine($"       {sh.SH_SIZE.RightAlignHexToSize()}  {sh.SH_ENTSIZE.RightAlignHexToSize()}  {flagString.LeftAlignToSize(4)}  {sh.SH_LINK.RightAlignDecToSize(4, ' ')}  {sh.SH_INFO.RightAlignDecToSize(4, ' ')}  {sh.SH_ADDRALIGN.RightAlignDecToSize(4, ' ')}");
                i++;
            }
            Console.Out.WriteLine("Key to Flags:");
            Console.Out.WriteLine("  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),");
            Console.Out.WriteLine("  L (link order), O (extra OS processing required), G (group), T (TLS),");
            Console.Out.WriteLine("  C (compressed), o (OS specific), E (exclude), p (processor specific)");

            Console.Out.WriteLine("\r\nProgram Headers:");
            Console.Out.WriteLine("  Type           Offset             VirtAddr           PhysAddr");
            Console.Out.WriteLine("                 FileSiz            MemSiz              Flags  Align");
            var programHeaders = metadata.OfType <Packager.Elf.Elf64.ProgramHeader64>().ToArray();

            foreach (var ph in programHeaders)
            {
                var flagString = new StringBuilder();
                flagString.Append(((SegmentPermissionFlags)ph.P_FLAGS).HasFlag(SegmentPermissionFlags.PF_R) ? 'R' : ' ');
                flagString.Append(((SegmentPermissionFlags)ph.P_FLAGS).HasFlag(SegmentPermissionFlags.PF_W) ? 'W' : ' ');
                flagString.Append(((SegmentPermissionFlags)ph.P_FLAGS).HasFlag(SegmentPermissionFlags.PF_X) ? 'E' : ' ');

                Console.Out.WriteLine($"  {PackagerUtility.GetEnumAttributeValue<ProgramHeaderType, ShortNameAttribute>(ph.P_TYPE, s => s.DisplayName).LeftAlignToSize(13)}  0x{ph.P_OFFSET.RightAlignHexToSize()} 0x{ph.P_VADDR.RightAlignHexToSize()} 0x{ph.P_PADDR.RightAlignHexToSize()}");
                Console.Out.WriteLine($"                 0x{ph.P_FILESZ.RightAlignHexToSize()} 0x{ph.P_MEMSZ.RightAlignHexToSize()}  {flagString.LeftAlignToSize(6)} 0x{ph.P_ALIGN:x}");
            }

            Console.Out.WriteLine("\r\nSection to Segment mapping:");
            Console.Out.WriteLine(" Segment Sections...");
            i = 0;
            foreach (var ph in programHeaders)
            {
                var shdrs = sectionHeaders
                            .Where(sh =>
                                   (sh.SH_ADDR > 0 || sh.SH_ENTSIZE > 0) &&
                                   sh.SH_ADDR >= ph.P_VADDR &&
                                   sh.SH_ADDR + sh.SH_SIZE <= ph.P_VADDR + ph.P_MEMSZ)
                            .Select(sh => sectionHeaderNames[sh.SH_NAME]).ToArray();
                var shdrNames = shdrs.Length == 0 ? string.Empty : shdrs.Aggregate((c, n) => $"{c} {n}");
                Console.Out.WriteLine($"  {i:00}     {shdrNames}");
                i++;
            }
        }