github.com/saferwall/pe@v1.5.2/dosheader.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  // ImageDOSHeader represents the DOS stub of a PE.
    12  type ImageDOSHeader struct {
    13  	// Magic number.
    14  	Magic uint16 `json:"magic"`
    15  
    16  	// Bytes on last page of file.
    17  	BytesOnLastPageOfFile uint16 `json:"bytes_on_last_page_of_file"`
    18  
    19  	// Pages in file.
    20  	PagesInFile uint16 `json:"pages_in_file"`
    21  
    22  	// Relocations.
    23  	Relocations uint16 `json:"relocations"`
    24  
    25  	// Size of header in paragraphs.
    26  	SizeOfHeader uint16 `json:"size_of_header"`
    27  
    28  	// Minimum extra paragraphs needed.
    29  	MinExtraParagraphsNeeded uint16 `json:"min_extra_paragraphs_needed"`
    30  
    31  	// Maximum extra paragraphs needed.
    32  	MaxExtraParagraphsNeeded uint16 `json:"max_extra_paragraphs_needed"`
    33  
    34  	// Initial (relative) SS value.
    35  	InitialSS uint16 `json:"initial_ss"`
    36  
    37  	// Initial SP value.
    38  	InitialSP uint16 `json:"initial_sp"`
    39  
    40  	// Checksum.
    41  	Checksum uint16 `json:"checksum"`
    42  
    43  	// Initial IP value.
    44  	InitialIP uint16 `json:"initial_ip"`
    45  
    46  	// Initial (relative) CS value.
    47  	InitialCS uint16 `json:"initial_cs"`
    48  
    49  	// File address of relocation table.
    50  	AddressOfRelocationTable uint16 `json:"address_of_relocation_table"`
    51  
    52  	// Overlay number.
    53  	OverlayNumber uint16 `json:"overlay_number"`
    54  
    55  	// Reserved words.
    56  	ReservedWords1 [4]uint16 `json:"reserved_words_1"`
    57  
    58  	// OEM identifier.
    59  	OEMIdentifier uint16 `json:"oem_identifier"`
    60  
    61  	// OEM information.
    62  	OEMInformation uint16 `json:"oem_information"`
    63  
    64  	// Reserved words.
    65  	ReservedWords2 [10]uint16 `json:"reserved_words_2"`
    66  
    67  	// File address of new exe header (Elfanew).
    68  	AddressOfNewEXEHeader uint32 `json:"address_of_new_exe_header"`
    69  }
    70  
    71  // ParseDOSHeader parses the DOS header stub. Every PE file begins with a small
    72  // MS-DOS stub. The need for this arose in the early days of Windows, before a
    73  // significant number of consumers were running it. When executed on a machine
    74  // without Windows, the program could at least print out a message saying that
    75  // Windows was required to run the executable.
    76  func (pe *File) ParseDOSHeader() (err error) {
    77  	offset := uint32(0)
    78  	size := uint32(binary.Size(pe.DOSHeader))
    79  	err = pe.structUnpack(&pe.DOSHeader, offset, size)
    80  	if err != nil {
    81  		return err
    82  	}
    83  
    84  	// It can be ZM on an (non-PE) EXE.
    85  	// These executables still work under XP via ntvdm.
    86  	if pe.DOSHeader.Magic != ImageDOSSignature &&
    87  		pe.DOSHeader.Magic != ImageDOSZMSignature {
    88  		return ErrDOSMagicNotFound
    89  	}
    90  
    91  	// `e_lfanew` is the only required element (besides the signature) of the
    92  	// DOS header to turn the EXE into a PE. It is is a relative offset to the
    93  	// NT Headers. It can't be null (signatures would overlap).
    94  	// Can be 4 at minimum.
    95  	if pe.DOSHeader.AddressOfNewEXEHeader < 4 ||
    96  		pe.DOSHeader.AddressOfNewEXEHeader > pe.size {
    97  		return ErrInvalidElfanewValue
    98  	}
    99  
   100  	// tiny pe has a e_lfanew of 4, which means the NT Headers is overlapping
   101  	// the DOS Header.
   102  	if pe.DOSHeader.AddressOfNewEXEHeader <= 0x3c {
   103  		pe.Anomalies = append(pe.Anomalies, AnoPEHeaderOverlapDOSHeader)
   104  	}
   105  
   106  	pe.HasDOSHdr = true
   107  	return nil
   108  }