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 }