github.com/saferwall/pe@v1.5.2/ntheader.go (about)

     1  // Copyright 2018 Saferwall. All rights reserved.
     2  // Use of this source code is governed by Apache v2 license
     3  // license that can be found in the LICENSE file.
     4  
     5  package pe
     6  
     7  import (
     8  	"encoding/binary"
     9  )
    10  
    11  // ImageFileHeaderMachineType represents the type of the image file header `Machine“ field.
    12  type ImageFileHeaderMachineType uint16
    13  
    14  // ImageFileHeaderCharacteristicsType represents the type of the image file header
    15  // `Characteristics` field.
    16  type ImageFileHeaderCharacteristicsType uint16
    17  
    18  // ImageOptionalHeaderSubsystemType represents the type of the optional header `Subsystem field.
    19  type ImageOptionalHeaderSubsystemType uint16
    20  
    21  // ImageOptionalHeaderDllCharacteristicsType represents the type of the optional header `DllCharacteristics field.
    22  type ImageOptionalHeaderDllCharacteristicsType uint16
    23  
    24  // ImageNtHeader represents the PE header and is the general term for a structure
    25  // named IMAGE_NT_HEADERS.
    26  type ImageNtHeader struct {
    27  	// Signature is a DWORD containing the value 50h, 45h, 00h, 00h.
    28  	Signature uint32 `json:"signature"`
    29  
    30  	// IMAGE_NT_HEADERS provides a standard COFF header. It is located
    31  	// immediately after the PE signature. The COFF header provides the most
    32  	// general characteristics of a PE/COFF file, applicable to both object and
    33  	// executable files. It is represented with IMAGE_FILE_HEADER structure.
    34  	FileHeader ImageFileHeader `json:"file_header"`
    35  
    36  	// OptionalHeader is of type *OptionalHeader32 or *OptionalHeader64.
    37  	OptionalHeader interface{} `json:"optional_header"`
    38  }
    39  
    40  // ImageFileHeader contains infos about the physical layout and properties of the
    41  // file.
    42  type ImageFileHeader struct {
    43  	// The number that identifies the type of target machine.
    44  	Machine ImageFileHeaderMachineType `json:"machine"`
    45  
    46  	// The number of sections. This indicates the size of the section table,
    47  	// which immediately follows the headers.
    48  	NumberOfSections uint16 `json:"number_of_sections"`
    49  
    50  	// // The low 32 bits of the number of seconds since 00:00 January 1, 1970
    51  	// (a C run-time time_t value), that indicates when the file was created.
    52  	TimeDateStamp uint32 `json:"time_date_stamp"`
    53  
    54  	// // The file offset of the COFF symbol table, or zero if no COFF symbol
    55  	// table is present. This value should be zero for an image because COFF
    56  	// debugging information is deprecated.
    57  	PointerToSymbolTable uint32 `json:"pointer_to_symbol_table"`
    58  
    59  	// The number of entries in the symbol table. This data can be used to
    60  	// locate the string table, which immediately follows the symbol table.
    61  	// This value should be zero for an image because COFF debugging information
    62  	// is deprecated.
    63  	NumberOfSymbols uint32 `json:"number_of_symbols"`
    64  
    65  	// The size of the optional header, which is required for executable files
    66  	// but not for object files. This value should be zero for an object file.
    67  	SizeOfOptionalHeader uint16 `json:"size_of_optional_header"`
    68  
    69  	// The flags that indicate the attributes of the file.
    70  	Characteristics ImageFileHeaderCharacteristicsType `json:"characteristics"`
    71  }
    72  
    73  // ImageOptionalHeader32 represents the PE32 format structure of the optional header.
    74  // PE32 contains this additional field, which is absent in PE32+.
    75  type ImageOptionalHeader32 struct {
    76  
    77  	// The unsigned integer that identifies the state of the image file.
    78  	// The most common number is 0x10B, which identifies it as a normal
    79  	// executable file. 0x107 identifies it as a ROM image, and 0x20B identifies
    80  	// it as a PE32+ executable.
    81  	Magic uint16 `json:"magic"`
    82  
    83  	// Linker major version number. The VC++ linker sets this field to current
    84  	// version of Visual Studio.
    85  	MajorLinkerVersion uint8 `json:"major_linker_version"`
    86  
    87  	// The linker minor version number.
    88  	MinorLinkerVersion uint8 `json:"minor_linker_version"`
    89  
    90  	// The size of the code (text) section, or the sum of all code sections
    91  	// if there are multiple sections.
    92  	SizeOfCode uint32 `json:"size_of_code"`
    93  
    94  	// The size of the initialized data section (held in the field SizeOfRawData
    95  	// of the respective section header), or the sum of all such sections if
    96  	// there are multiple data sections.
    97  	SizeOfInitializedData uint32 `json:"size_of_initialized_data"`
    98  
    99  	// The size of the uninitialized data section (BSS), or the sum of all
   100  	// such sections if there are multiple BSS sections. This data is not part
   101  	// of the disk file and does not have specific values, but the OS loader
   102  	// commits memory space for this data when the file is loaded.
   103  	SizeOfUninitializedData uint32 `json:"size_of_uninitialized_data"`
   104  
   105  	// The address of the entry point relative to the image base when the
   106  	// executable file is loaded into memory. For program images, this is the
   107  	// starting address. For device drivers, this is the address of the
   108  	// initialization function. An entry point is optional for DLLs. When no
   109  	// entry point is present, this field must be zero. For managed PE files,
   110  	// this value always points to the common language runtime invocation stub.
   111  	AddressOfEntryPoint uint32 `json:"address_of_entrypoint"`
   112  
   113  	// The address that is relative to the image base of the beginning-of-code
   114  	// section when it is loaded into memory.
   115  	BaseOfCode uint32 `json:"base_of_code"`
   116  
   117  	// The address that is relative to the image base of the beginning-of-data
   118  	// section when it is loaded into memory. This entry doesn’t exist in the
   119  	// 64-bit Optional header.
   120  	BaseOfData uint32 `json:"base_of_data"`
   121  
   122  	// The preferred address of the first byte of image when loaded into memory;
   123  	// must be a multiple of 64 K. The default for DLLs is 0x10000000. The
   124  	// default for Windows CE EXEs is 0x00010000. The default for Windows NT,
   125  	// Windows 2000, Windows XP, Windows 95, Windows 98, and Windows Me is
   126  	// 0x00400000.
   127  	ImageBase uint32 `json:"image_base"`
   128  
   129  	// The alignment (in bytes) of sections when they are loaded into memory.
   130  	// It must be greater than or equal to FileAlignment. The default is the
   131  	// page size for the architecture.
   132  	SectionAlignment uint32 `json:"section_alignment"`
   133  
   134  	// The alignment factor (in bytes) that is used to align the raw data of
   135  	// sections in the image file. The value should be a power of 2 between 512
   136  	// and 64 K, inclusive. The default is 512. If the SectionAlignment is less
   137  	// than the architecture's page size, then FileAlignment must match
   138  	// SectionAlignment.
   139  	FileAlignment uint32 `json:"file_alignment"`
   140  
   141  	// The major version number of the required operating system.
   142  	MajorOperatingSystemVersion uint16 `json:"major_os_version"`
   143  
   144  	// The minor version number of the required operating system.
   145  	MinorOperatingSystemVersion uint16 `json:"minor_os_version"`
   146  
   147  	// The major version number of the image.
   148  	MajorImageVersion uint16 `json:"major_image_version"`
   149  
   150  	// The minor version number of the image.
   151  	MinorImageVersion uint16 `json:"minor_image_version"`
   152  
   153  	// The major version number of the subsystem.
   154  	MajorSubsystemVersion uint16 `json:"major_subsystem_version"`
   155  
   156  	// The minor version number of the subsystem.
   157  	MinorSubsystemVersion uint16 `json:"minor_subsystem_version"`
   158  
   159  	// Reserved, must be zero.
   160  	Win32VersionValue uint32 `json:"win32_version_value"`
   161  
   162  	// The size (in bytes) of the image, including all headers, as the image
   163  	// is loaded in memory. It must be a multiple of SectionAlignment.
   164  	SizeOfImage uint32 `json:"size_of_image"`
   165  
   166  	// The combined size of an MS-DOS stub, PE header, and section headers
   167  	// rounded up to a multiple of FileAlignment.
   168  	SizeOfHeaders uint32 `json:"size_of_headers"`
   169  
   170  	// The image file checksum. The algorithm for computing the checksum is
   171  	// incorporated into IMAGHELP.DLL. The following are checked for validation
   172  	// at load time: all drivers, any DLL loaded at boot time, and any DLL
   173  	// that is loaded into a critical Windows process.
   174  	CheckSum uint32 `json:"checksum"`
   175  
   176  	// The subsystem that is required to run this image.
   177  	Subsystem ImageOptionalHeaderSubsystemType `json:"subsystem"`
   178  
   179  	// For more information, see DLL Characteristics later in this specification.
   180  	DllCharacteristics ImageOptionalHeaderDllCharacteristicsType `json:"dll_characteristics"`
   181  
   182  	// Size of virtual memory to reserve for the initial thread’s stack. Only
   183  	// the SizeOfStackCommit field is committed; the rest is available in
   184  	// one-page increments. The default is 1MB for 32-bit images and 4MB for
   185  	// 64-bit images.
   186  	SizeOfStackReserve uint32 `json:"size_of_stack_reserve"`
   187  
   188  	// Size of virtual memory initially committed for the initial thread’s
   189  	// stack. The default is one page (4KB) for 32-bit images and 16KB for
   190  	// 64-bit images.
   191  	SizeOfStackCommit uint32 `json:"size_of_stack_commit"`
   192  
   193  	// size of the local heap space to reserve. Only SizeOfHeapCommit is
   194  	// committed; the rest is made available one page at a time until the
   195  	// reserve size is reached. The default is 1MB for both 32-bit and 64-bit
   196  	// images.
   197  	SizeOfHeapReserve uint32 `json:"size_of_heap_reserve"`
   198  
   199  	// Size of virtual memory initially committed for the process heap. The
   200  	// default is 4KB (one operating system memory page) for 32-bit images and
   201  	// 16KB for 64-bit images.
   202  	SizeOfHeapCommit uint32 `json:"size_of_heap_commit"`
   203  
   204  	// Reserved, must be zero.
   205  	LoaderFlags uint32 `json:"loader_flags"`
   206  
   207  	// Number of entries in the DataDirectory array; at least 16. Although it
   208  	// is theoretically possible to emit more than 16 data directories, all
   209  	// existing managed compilers emit exactly 16 data directories, with the
   210  	// 16th (last) data directory never used (reserved).
   211  	NumberOfRvaAndSizes uint32 `json:"number_of_rva_and_sizes"`
   212  
   213  	// An array of 16 IMAGE_DATA_DIRECTORY structures.
   214  	DataDirectory [16]DataDirectory `json:"data_directories"`
   215  }
   216  
   217  // ImageOptionalHeader64 represents the PE32+ format structure of the optional header.
   218  type ImageOptionalHeader64 struct {
   219  	// The unsigned integer that identifies the state of the image file.
   220  	// The most common number is 0x10B, which identifies it as a normal
   221  	// executable file. 0x107 identifies it as a ROM image, and 0x20B identifies
   222  	// it as a PE32+ executable.
   223  	Magic uint16 `json:"magic"`
   224  
   225  	// Linker major version number. The VC++ linker sets this field to current
   226  	// version of Visual Studio.
   227  	MajorLinkerVersion uint8 `json:"major_linker_version"`
   228  
   229  	// The linker minor version number.
   230  	MinorLinkerVersion uint8 `json:"minor_linker_version"`
   231  
   232  	// The size of the code (text) section, or the sum of all code sections
   233  	// if there are multiple sections.
   234  	SizeOfCode uint32 `json:"size_of_code"`
   235  
   236  	// The size of the initialized data section (held in the field SizeOfRawData
   237  	// of the respective section header), or the sum of all such sections if
   238  	// there are multiple data sections.
   239  	SizeOfInitializedData uint32 `json:"size_of_initialized_data"`
   240  
   241  	// The size of the uninitialized data section (BSS), or the sum of all
   242  	// such sections if there are multiple BSS sections. This data is not part
   243  	// of the disk file and does not have specific values, but the OS loader
   244  	// commits memory space for this data when the file is loaded.
   245  	SizeOfUninitializedData uint32 `json:"size_of_uninitialized_data"`
   246  
   247  	// The address of the entry point relative to the image base when the
   248  	// executable file is loaded into memory. For program images, this is the
   249  	// starting address. For device drivers, this is the address of the
   250  	// initialization function. An entry point is optional for DLLs. When no
   251  	// entry point is present, this field must be zero. For managed PE files,
   252  	// this value always points to the common language runtime invocation stub.
   253  	AddressOfEntryPoint uint32 `json:"address_of_entrypoint"`
   254  
   255  	// The address that is relative to the image base of the beginning-of-code
   256  	// section when it is loaded into memory.
   257  	BaseOfCode uint32 `json:"base_of_code"`
   258  
   259  	// In PE+, ImageBase is 8 bytes size.
   260  	ImageBase uint64 `json:"image_base"`
   261  
   262  	// The alignment (in bytes) of sections when they are loaded into memory.
   263  	// It must be greater than or equal to FileAlignment. The default is the
   264  	// page size for the architecture.
   265  	SectionAlignment uint32 `json:"section_alignment"`
   266  
   267  	// The alignment factor (in bytes) that is used to align the raw data of
   268  	// sections in the image file. The value should be a power of 2 between 512
   269  	// and 64 K, inclusive. The default is 512. If the SectionAlignment is less
   270  	// than the architecture's page size, then FileAlignment must match SectionAlignment.
   271  	FileAlignment uint32 `json:"file_alignment"`
   272  
   273  	// The major version number of the required operating system.
   274  	MajorOperatingSystemVersion uint16 `json:"major_os_version"`
   275  
   276  	// The minor version number of the required operating system.
   277  	MinorOperatingSystemVersion uint16 `json:"minor_os_version"`
   278  
   279  	// The major version number of the image.
   280  	MajorImageVersion uint16 `json:"major_image_version"`
   281  
   282  	// The minor version number of the image.
   283  	MinorImageVersion uint16 `json:"minor_image_version"`
   284  
   285  	// The major version number of the subsystem.
   286  	MajorSubsystemVersion uint16 `json:"major_subsystem_version"`
   287  
   288  	// The minor version number of the subsystem.
   289  	MinorSubsystemVersion uint16 `json:"minor_subsystem_version"`
   290  
   291  	// Reserved, must be zero.
   292  	Win32VersionValue uint32 `json:"win32_version_value"`
   293  
   294  	// The size (in bytes) of the image, including all headers, as the image
   295  	// is loaded in memory. It must be a multiple of SectionAlignment.
   296  	SizeOfImage uint32 `json:"size_of_image"`
   297  
   298  	// The combined size of an MS-DOS stub, PE header, and section headers
   299  	// rounded up to a multiple of FileAlignment.
   300  	SizeOfHeaders uint32 `json:"size_of_headers"`
   301  
   302  	// The image file checksum. The algorithm for computing the checksum is
   303  	// incorporated into IMAGHELP.DLL. The following are checked for validation
   304  	// at load time: all drivers, any DLL loaded at boot time, and any DLL
   305  	// that is loaded into a critical Windows process.
   306  	CheckSum uint32 `json:"checksum"`
   307  
   308  	// The subsystem that is required to run this image.
   309  	Subsystem ImageOptionalHeaderSubsystemType `json:"subsystem"`
   310  
   311  	// For more information, see DLL Characteristics later in this specification.
   312  	DllCharacteristics ImageOptionalHeaderDllCharacteristicsType `json:"dll_characteristics"`
   313  
   314  	// Size of virtual memory to reserve for the initial thread’s stack. Only
   315  	// the SizeOfStackCommit field is committed; the rest is available in
   316  	// one-page increments. The default is 1MB for 32-bit images and 4MB for
   317  	// 64-bit images.
   318  	SizeOfStackReserve uint64 `json:"size_of_stack_reserve"`
   319  
   320  	// Size of virtual memory initially committed for the initial thread’s
   321  	// stack. The default is one page (4KB) for 32-bit images and 16KB for
   322  	// 64-bit images.
   323  	SizeOfStackCommit uint64 `json:"size_of_stack_commit"`
   324  
   325  	// size of the local heap space to reserve. Only SizeOfHeapCommit is
   326  	// committed; the rest is made available one page at a time until the
   327  	// reserve size is reached. The default is 1MB for both 32-bit and 64-bit
   328  	// images.
   329  	SizeOfHeapReserve uint64 `json:"size_of_heap_reserve"`
   330  
   331  	// Size of virtual memory initially committed for the process heap. The
   332  	// default is 4KB (one operating system memory page) for 32-bit images and
   333  	// 16KB for 64-bit images.
   334  	SizeOfHeapCommit uint64 `json:"size_of_heap_commit"`
   335  
   336  	// Reserved, must be zero.
   337  	LoaderFlags uint32 `json:"loader_flags"`
   338  
   339  	// Number of entries in the DataDirectory array; at least 16. Although it
   340  	// is theoretically possible to emit more than 16 data directories, all
   341  	// existing managed compilers emit exactly 16 data directories, with the
   342  	// 16th (last) data directory never used (reserved).
   343  	NumberOfRvaAndSizes uint32 `json:"number_of_rva_and_sizes"`
   344  
   345  	// An array of 16 IMAGE_DATA_DIRECTORY structures.
   346  	DataDirectory [16]DataDirectory `json:"data_directories"`
   347  }
   348  
   349  // DataDirectory represents an array of 16 IMAGE_DATA_DIRECTORY structures,
   350  // 8 bytes apiece, each relating to an important data structure in the PE file.
   351  // The data directory table starts at offset 96 in a 32-bit PE header and at
   352  // offset 112 in a 64-bit PE header. Each entry in the data directory table
   353  // contains the RVA and size of a table or a string that this particular
   354  // directory entry describes;this information is used by the operating system.
   355  type DataDirectory struct {
   356  	// The RVA of the data structure.
   357  	VirtualAddress uint32 `json:"virtual_address"`
   358  	// The size in bytes of the data structure referred to.
   359  	Size uint32 `json:"size"`
   360  }
   361  
   362  // ParseNTHeader parse the PE NT header structure referred as IMAGE_NT_HEADERS.
   363  // Its offset is given by the e_lfanew field in the IMAGE_DOS_HEADER at the
   364  // beginning of the file.
   365  func (pe *File) ParseNTHeader() (err error) {
   366  	ntHeaderOffset := pe.DOSHeader.AddressOfNewEXEHeader
   367  	signature, err := pe.ReadUint32(ntHeaderOffset)
   368  	if err != nil {
   369  		return ErrInvalidNtHeaderOffset
   370  	}
   371  
   372  	// Probe for PE signature.
   373  	if signature&0xFFFF == ImageOS2Signature {
   374  		return ErrImageOS2SignatureFound
   375  	}
   376  	if signature&0xFFFF == ImageOS2LESignature {
   377  		return ErrImageOS2LESignatureFound
   378  	}
   379  	if signature&0xFFFF == ImageVXDSignature {
   380  		return ErrImageVXDSignatureFound
   381  	}
   382  	if signature&0xFFFF == ImageTESignature {
   383  		return ErrImageTESignatureFound
   384  	}
   385  
   386  	// This is the smallest requirement for a valid PE.
   387  	if signature != ImageNTSignature {
   388  		return ErrImageNtSignatureNotFound
   389  	}
   390  	pe.NtHeader.Signature = signature
   391  
   392  	// The file header structure contains some basic information about the file;
   393  	// most importantly, a field describing the size of the optional data that
   394  	// follows it.
   395  	fileHeaderSize := uint32(binary.Size(pe.NtHeader.FileHeader))
   396  	fileHeaderOffset := ntHeaderOffset + 4
   397  	err = pe.structUnpack(&pe.NtHeader.FileHeader, fileHeaderOffset, fileHeaderSize)
   398  	if err != nil {
   399  		return err
   400  	}
   401  
   402  	// The PE header which immediately follows the COFF header, provides
   403  	// information for the OS loader. Although this header is referred to as
   404  	// the optional header, it is optional only in the sense that object files
   405  	// usually don’t contain it. For PE files, this header is mandatory.
   406  	// The size of the PE header is not fixed. It depends on the number of data
   407  	// directories defined in the header and is specified in the
   408  	// SizeOfOptionalHeader field of the COFF header.
   409  	// The optional header could be either for a PE or PE+ file.
   410  	oh32 := ImageOptionalHeader32{}
   411  	oh64 := ImageOptionalHeader64{}
   412  
   413  	optHeaderOffset := ntHeaderOffset + (fileHeaderSize + 4)
   414  	magic, err := pe.ReadUint16(optHeaderOffset)
   415  	if err != nil {
   416  		return err
   417  	}
   418  
   419  	// Probes for PE32/PE32+ optional header magic.
   420  	if magic != ImageNtOptionalHeader32Magic &&
   421  		magic != ImageNtOptionalHeader64Magic {
   422  		return ErrImageNtOptionalHeaderMagicNotFound
   423  	}
   424  
   425  	// Are we dealing with a PE64 optional header.
   426  	switch magic {
   427  	case ImageNtOptionalHeader64Magic:
   428  		size := uint32(binary.Size(oh64))
   429  		err = pe.structUnpack(&oh64, optHeaderOffset, size)
   430  		if err != nil {
   431  			return err
   432  		}
   433  		pe.Is64 = true
   434  		pe.NtHeader.OptionalHeader = oh64
   435  	case ImageNtOptionalHeader32Magic:
   436  		size := uint32(binary.Size(oh32))
   437  		err = pe.structUnpack(&oh32, optHeaderOffset, size)
   438  		if err != nil {
   439  			return err
   440  		}
   441  		pe.Is32 = true
   442  		pe.NtHeader.OptionalHeader = oh32
   443  	}
   444  
   445  	// ImageBase should be multiple of 10000h.
   446  	if (pe.Is64 && oh64.ImageBase%0x10000 != 0) || (pe.Is32 && oh32.ImageBase%0x10000 != 0) {
   447  		return ErrImageBaseNotAligned
   448  	}
   449  
   450  	// ImageBase can be any value as long as:
   451  	// ImageBase + SizeOfImage < 80000000h for PE32.
   452  	// ImageBase + SizeOfImage < 0xffff080000000000 for PE32+.
   453  	if (pe.Is32 && oh32.ImageBase+oh32.SizeOfImage >= 0x80000000) || (pe.Is64 && oh64.ImageBase+uint64(oh64.SizeOfImage) >= 0xffff080000000000) {
   454  		pe.Anomalies = append(pe.Anomalies, AnoImageBaseOverflow)
   455  	}
   456  
   457  	pe.HasNTHdr = true
   458  	return nil
   459  }
   460  
   461  // String returns the string representations of the `Machine` field of the IMAGE_FILE_HEADER.
   462  func (t ImageFileHeaderMachineType) String() string {
   463  	machineType := map[ImageFileHeaderMachineType]string{
   464  		ImageFileMachineUnknown:   "Unknown",
   465  		ImageFileMachineAM33:      "Matsushita AM33",
   466  		ImageFileMachineAMD64:     "x64",
   467  		ImageFileMachineARM:       "ARM little endian",
   468  		ImageFileMachineARM64:     "ARM64 little endian",
   469  		ImageFileMachineARMNT:     "ARM Thumb-2 little endian",
   470  		ImageFileMachineEBC:       "EFI byte code",
   471  		ImageFileMachineI386:      "Intel 386 or later / compatible processors",
   472  		ImageFileMachineIA64:      "Intel Itanium processor family",
   473  		ImageFileMachineM32R:      "Mitsubishi M32R little endian",
   474  		ImageFileMachineMIPS16:    "MIPS16",
   475  		ImageFileMachineMIPSFPU:   "MIPS with FPU",
   476  		ImageFileMachineMIPSFPU16: "MIPS16 with FPU",
   477  		ImageFileMachinePowerPC:   "Power PC little endian",
   478  		ImageFileMachinePowerPCFP: "Power PC with floating point support",
   479  		ImageFileMachineR4000:     "MIPS little endian",
   480  		ImageFileMachineRISCV32:   "RISC-V 32-bit address space",
   481  		ImageFileMachineRISCV64:   "RISC-V 64-bit address space",
   482  		ImageFileMachineRISCV128:  "RISC-V 128-bit address space",
   483  		ImageFileMachineSH3:       "Hitachi SH3",
   484  		ImageFileMachineSH3DSP:    "Hitachi SH3 DSP",
   485  		ImageFileMachineSH4:       "Hitachi SH4",
   486  		ImageFileMachineSH5:       "Hitachi SH5",
   487  		ImageFileMachineTHUMB:     "Thumb",
   488  		ImageFileMachineWCEMIPSv2: "MIPS little-endian WCE v2",
   489  	}
   490  
   491  	if val, ok := machineType[t]; ok {
   492  		return val
   493  	}
   494  	return "?"
   495  }
   496  
   497  // String returns the string representations of the `Characteristics` field of the IMAGE_FILE_HEADER.
   498  func (t ImageFileHeaderCharacteristicsType) String() []string {
   499  	var values []string
   500  	fileHeaderCharacteristics := map[ImageFileHeaderCharacteristicsType]string{
   501  		ImageFileRelocsStripped:       "RelocsStripped",
   502  		ImageFileExecutableImage:      "ExecutableImage",
   503  		ImageFileLineNumsStripped:     "LineNumsStripped",
   504  		ImageFileLocalSymsStripped:    "LocalSymsStripped",
   505  		ImageFileAggressiveWSTrim:     "AgressibeWsTrim",
   506  		ImageFileLargeAddressAware:    "LargeAddressAware",
   507  		ImageFileBytesReservedLow:     "BytesReservedLow",
   508  		ImageFile32BitMachine:         "32BitMachine",
   509  		ImageFileDebugStripped:        "DebugStripped",
   510  		ImageFileRemovableRunFromSwap: "RemovableRunFromSwap",
   511  		ImageFileSystem:               "FileSystem",
   512  		ImageFileDLL:                  "DLL",
   513  		ImageFileUpSystemOnly:         "UpSystemOnly",
   514  		ImageFileBytesReservedHigh:    "BytesReservedHigh",
   515  	}
   516  
   517  	for k, s := range fileHeaderCharacteristics {
   518  		if k&t != 0 {
   519  			values = append(values, s)
   520  		}
   521  	}
   522  
   523  	return values
   524  }
   525  
   526  // String returns the string representations of the `DllCharacteristics` field of ImageOptionalHeader.
   527  func (t ImageOptionalHeaderDllCharacteristicsType) String() []string {
   528  	var values []string
   529  
   530  	imgDllCharacteristics := map[ImageOptionalHeaderDllCharacteristicsType]string{
   531  		ImageDllCharacteristicsHighEntropyVA:        "HighEntropyVA",
   532  		ImageDllCharacteristicsDynamicBase:          "DynamicBase",
   533  		ImageDllCharacteristicsForceIntegrity:       "ForceIntegrity",
   534  		ImageDllCharacteristicsNXCompact:            "NXCompact",
   535  		ImageDllCharacteristicsNoIsolation:          "NoIsolation",
   536  		ImageDllCharacteristicsNoSEH:                "NoSEH",
   537  		ImageDllCharacteristicsNoBind:               "NoBind",
   538  		ImageDllCharacteristicsAppContainer:         "AppContainer",
   539  		ImageDllCharacteristicsWdmDriver:            "WdmDriver",
   540  		ImageDllCharacteristicsGuardCF:              "GuardCF",
   541  		ImageDllCharacteristicsTerminalServiceAware: "TerminalServiceAware",
   542  	}
   543  
   544  	for k, s := range imgDllCharacteristics {
   545  		if k&t != 0 {
   546  			values = append(values, s)
   547  		}
   548  	}
   549  
   550  	return values
   551  }
   552  
   553  // String returns the string representations of the `Subsystem` field
   554  // of ImageOptionalHeader.
   555  func (subsystem ImageOptionalHeaderSubsystemType) String() string {
   556  	subsystemMap := map[ImageOptionalHeaderSubsystemType]string{
   557  		ImageSubsystemUnknown:                "Unknown",
   558  		ImageSubsystemNative:                 "Native",
   559  		ImageSubsystemWindowsGUI:             "Windows GUI",
   560  		ImageSubsystemWindowsCUI:             "Windows CUI",
   561  		ImageSubsystemOS2CUI:                 "OS/2 character",
   562  		ImageSubsystemPosixCUI:               "POSIX character",
   563  		ImageSubsystemNativeWindows:          "Native Win9x driver",
   564  		ImageSubsystemWindowsCEGUI:           "Windows CE GUI",
   565  		ImageSubsystemEFIApplication:         "EFI Application",
   566  		ImageSubsystemEFIBootServiceDriver:   "EFI Boot Service Driver",
   567  		ImageSubsystemEFIRuntimeDriver:       "EFI ROM image",
   568  		ImageSubsystemEFIRom:                 "EFI ROM image",
   569  		ImageSubsystemXBOX:                   "XBOX",
   570  		ImageSubsystemWindowsBootApplication: "Windows boot application",
   571  	}
   572  
   573  	if val, ok := subsystemMap[subsystem]; ok {
   574  		return val
   575  	}
   576  
   577  	return "?"
   578  }
   579  
   580  // PrettyOptionalHeaderMagic returns the string representations of the
   581  // `Magic` field of ImageOptionalHeader.
   582  func (pe *File) PrettyOptionalHeaderMagic() string {
   583  
   584  	var magic uint16
   585  
   586  	if pe.Is64 {
   587  		magic =
   588  			pe.NtHeader.OptionalHeader.(ImageOptionalHeader64).Magic
   589  	} else {
   590  		magic =
   591  			pe.NtHeader.OptionalHeader.(ImageOptionalHeader32).Magic
   592  	}
   593  
   594  	switch magic {
   595  	case ImageNtOptionalHeader32Magic:
   596  		return "PE32"
   597  	case ImageNtOptionalHeader64Magic:
   598  		return "PE64"
   599  	case ImageROMOptionalHeaderMagic:
   600  		return "ROM"
   601  	default:
   602  		return "?"
   603  	}
   604  }