diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..d9e4734 --- /dev/null +++ b/go.mod @@ -0,0 +1,8 @@ +module github.com/soluwalana/pefile-go + +go 1.14 + +require ( + github.com/edsrzf/mmap-go v1.0.0 + golang.org/x/sys v0.0.0-20200722175500-76b94024e4b6 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..389541e --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +golang.org/x/sys v0.0.0-20200722175500-76b94024e4b6 h1:X9xIZ1YU8bLZA3l6gqDUHSFiD0GFI9S548h6C8nDtOY= +golang.org/x/sys v0.0.0-20200722175500-76b94024e4b6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/pefile-go/pe/parse_export_directory.go b/pefile-go/pe/parse_export_directory.go index be60bf2..a07e321 100644 --- a/pefile-go/pe/parse_export_directory.go +++ b/pefile-go/pe/parse_export_directory.go @@ -2,22 +2,24 @@ package pe import ( "errors" - "../lib" "fmt" + + "github.com/soluwalana/pefile-go/pefile-go/lib" + //"reflect" "log" ) /* Parse the export directory. - Given the RVA of the export directory, it will process all - its entries. +Given the RVA of the export directory, it will process all +its entries. - The exports will be made available as a list of ExportData - instances in the ExportDescriptors PE attribute. +The exports will be made available as a list of ExportData +instances in the ExportDescriptors PE attribute. */ func (self *PEFile) parseExportDirectory(rva, size uint32) (err error) { - + exportDir := lib.NewExportDirectory(self.getOffsetFromRva(rva)) start, _ := self.getDataBounds(rva, 0) if err = self.parseHeader(&exportDir.Data, start, exportDir.Size); err != nil { @@ -29,8 +31,7 @@ func (self *PEFile) parseExportDirectory(rva, size uint32) (err error) { startAddrOfNames, _ := self.getDataBounds(exportDir.Data.AddressOfNames, 0) startAddrOfOrdinals, _ := self.getDataBounds(exportDir.Data.AddressOfNameOrdinals, 0) startAddrOfFuncs, _ := self.getDataBounds(exportDir.Data.AddressOfFunctions, 0) - - + errMsg := "RVA %s in the export directory points to an invalid address: %x" //maxErrors := 10 @@ -40,15 +41,15 @@ func (self *PEFile) parseExportDirectory(rva, size uint32) (err error) { return errors.New(fmt.Sprintf(errMsg, "AddressOfNames", exportDir.Data.AddressOfNames)) } - + safetyBoundary := section.Data.VirtualAddress + section.Data.SizeOfRawData - exportDir.Data.AddressOfNames - numNames := Min(safetyBoundary / 4, exportDir.Data.NumberOfNames) + numNames := Min(safetyBoundary/4, exportDir.Data.NumberOfNames) // A hash set for tracking seen ordinals ordMap := make(map[uint16]bool) fmt.Printf("Safety boundary %x, num names %d\n", safetyBoundary, numNames) - for i := uint32(0); i < numNames; i ++ { + for i := uint32(0); i < numNames; i++ { sym := new(lib.ExportData) // Name and name offset @@ -69,7 +70,7 @@ func (self *PEFile) parseExportDirectory(rva, size uint32) (err error) { if err = self.parseHeader(&sym.Ordinal, sym.OrdinalOffset, 2); err != nil { return err } - + // Address sym.AddressOffset = startAddrOfFuncs + (uint32(sym.Ordinal) * 4) if err = self.parseHeader(&sym.Address, sym.AddressOffset, 4); err != nil { @@ -80,7 +81,7 @@ func (self *PEFile) parseExportDirectory(rva, size uint32) (err error) { } // Forwarder if applicable - if sym.Address >= rva && sym.Address < rva + size { + if sym.Address >= rva && sym.Address < rva+size { sym.Forwarder = self.getStringAtRva(sym.Address) sym.ForwarderOffset = self.getOffsetFromRva(sym.Address) } @@ -98,11 +99,11 @@ func (self *PEFile) parseExportDirectory(rva, size uint32) (err error) { return errors.New(fmt.Sprintf(errMsg, "AddressOfFunctions", exportDir.Data.AddressOfFunctions)) } safetyBoundary = section.Data.VirtualAddress + section.Data.SizeOfRawData - exportDir.Data.AddressOfFunctions - numNames = Min(safetyBoundary / 4, exportDir.Data.NumberOfFunctions) + numNames = Min(safetyBoundary/4, exportDir.Data.NumberOfFunctions) fmt.Printf("Safety2 boundary %x, num names %d\n", safetyBoundary, numNames) - for i := uint32(0); i < numNames; i ++ { - if _, ok := ordMap[uint16(i + exportDir.Data.Base)]; ok { + for i := uint32(0); i < numNames; i++ { + if _, ok := ordMap[uint16(i+exportDir.Data.Base)]; ok { continue } @@ -118,7 +119,7 @@ func (self *PEFile) parseExportDirectory(rva, size uint32) (err error) { } // Forwarder if applicable - if sym.Address >= rva && sym.Address < rva + size { + if sym.Address >= rva && sym.Address < rva+size { sym.Forwarder = self.getStringAtRva(sym.Address) sym.ForwarderOffset = self.getOffsetFromRva(sym.Address) } @@ -129,4 +130,4 @@ func (self *PEFile) parseExportDirectory(rva, size uint32) (err error) { } return nil -} \ No newline at end of file +} diff --git a/pefile-go/pe/parse_import_directory.go b/pefile-go/pe/parse_import_directory.go index 87909e4..be9c31b 100644 --- a/pefile-go/pe/parse_import_directory.go +++ b/pefile-go/pe/parse_import_directory.go @@ -4,25 +4,26 @@ package pe import ( "errors" - "../lib" "fmt" - "reflect" "log" + "reflect" + + "github.com/soluwalana/pefile-go/pefile-go/lib" ) /* Parse the import directory. - Given the RVA of the export directory, it will process all - its entries. +Given the RVA of the export directory, it will process all +its entries. - The exports will be made available as a list of ImportData - instances in the ImportDescriptors PE attribute. +The exports will be made available as a list of ImportData +instances in the ImportDescriptors PE attribute. */ func (self *PEFile) parseImportDirectory(rva, size uint32) (err error) { self.ImportDescriptors = make([]*lib.ImportDescriptor, 0) for { - + fileOffset := self.getOffsetFromRva(rva) importDesc := lib.NewImportDescriptor(fileOffset) @@ -38,8 +39,8 @@ func (self *PEFile) parseImportDirectory(rva, size uint32) (err error) { if lib.EmptyStruct(importDesc.Data) { break } - - rva += importDesc.Size + + rva += importDesc.Size importDesc.Dll = self.getStringAtRva(importDesc.Data.Name) if !validDosFilename(importDesc.Dll) { @@ -77,7 +78,7 @@ func (self *PEFile) parseImportDirectory(rva, size uint32) (err error) { return nil } -/* +/* Parse the imported symbols. It will fill a list, which will be available as the dictionary @@ -87,14 +88,18 @@ func (self *PEFile) parseImportDirectory(rva, size uint32) (err error) { func (self *PEFile) parseImports(importDesc *lib.ImportDescriptor) (err error) { var table []*lib.ThunkData ilt, err := self.getImportTable(importDesc.Data.Characteristics, importDesc) - if err != nil { return err } + if err != nil { + return err + } iat, err := self.getImportTable(importDesc.Data.FirstThunk, importDesc) - if err != nil { return err } + if err != nil { + return err + } if len(iat) == 0 && len(ilt) == 0 { return errors.New("Invalid Import Table information. Both ILT and IAT appear to be broken.") } - + impOffset := uint32(0x4) addressMask := uint32(0x7fffffff) ordinalFlag := IMAGE_ORDINAL_FLAG @@ -107,15 +112,15 @@ func (self *PEFile) parseImports(importDesc *lib.ImportDescriptor) (err error) { table = iat } - for idx := uint32(0); idx < uint32(len(table)); idx ++ { + for idx := uint32(0); idx < uint32(len(table)); idx++ { imp := new(lib.ImportData) imp.StructTable = table[idx] imp.OrdinalOffset = table[idx].FileOffset if table[idx].Data.AddressOfData > 0 { - + // If imported by ordinal, we will append the ordinal numberx - if table[idx].Data.AddressOfData & ordinalFlag > 0 { + if table[idx].Data.AddressOfData&ordinalFlag > 0 { imp.ImportByOrdinal = true imp.Ordinal = table[idx].Data.AddressOfData & uint32(0xffff) } else { @@ -131,42 +136,42 @@ func (self *PEFile) parseImports(importDesc *lib.ImportDescriptor) (err error) { if !validFuncName(imp.Name) { imp.Name = INVALID_IMP_NAME } - imp.NameOffset = self.getOffsetFromRva(table[idx].Data.AddressOfData + 2) + imp.NameOffset = self.getOffsetFromRva(table[idx].Data.AddressOfData + 2) } imp.ThunkOffset = table[idx].FileOffset imp.ThunkRva = self.getRvaFromOffset(imp.ThunkOffset) - } + } imp.Address = importDesc.Data.FirstThunk + self.OptionalHeader.Data.ImageBase + (idx * impOffset) - if len(iat) > 0 && len(ilt) > 0 && ilt[idx].Data.AddressOfData != iat[idx].Data.AddressOfData { - imp.Bound = iat[idx].Data.AddressOfData - imp.StructIat = iat[idx] - } - - hasName := len(imp.Name) > 0 + if len(iat) > 0 && len(ilt) > 0 && ilt[idx].Data.AddressOfData != iat[idx].Data.AddressOfData { + imp.Bound = iat[idx].Data.AddressOfData + imp.StructIat = iat[idx] + } + + hasName := len(imp.Name) > 0 // The file with hashe: // SHA256: 3d22f8b001423cb460811ab4f4789f277b35838d45c62ec0454c877e7c82c7f5 // has an invalid table built in a way that it's parseable but contains // invalid entries - if imp.Ordinal == 0 && !hasName { - return errors.New("Must have either an ordinal or a name in an import") - } - // Some PEs appear to interleave valid and invalid imports. Instead of - // aborting the parsing altogether we will simply skip the invalid entries. - // Although if we see 1000 invalid entries and no legit ones, we abort. - if reflect.DeepEqual(imp.Name, INVALID_IMP_NAME) { - if numInvalid > 1000 && numInvalid == idx { - return errors.New("Too many invalid names, aborting parsing") - } - numInvalid += 1 - continue - } - - if imp.Ordinal > 0 || hasName { - importDesc.Imports = append(importDesc.Imports, imp) - } + if imp.Ordinal == 0 && !hasName { + return errors.New("Must have either an ordinal or a name in an import") + } + // Some PEs appear to interleave valid and invalid imports. Instead of + // aborting the parsing altogether we will simply skip the invalid entries. + // Although if we see 1000 invalid entries and no legit ones, we abort. + if reflect.DeepEqual(imp.Name, INVALID_IMP_NAME) { + if numInvalid > 1000 && numInvalid == idx { + return errors.New("Too many invalid names, aborting parsing") + } + numInvalid += 1 + continue + } + + if imp.Ordinal > 0 || hasName { + importDesc.Imports = append(importDesc.Imports, imp) + } } return nil @@ -189,7 +194,7 @@ func (self *PEFile) getImportTable(rva uint32, importDesc *lib.ImportDescriptor) maxLen := self.dataLen - importDesc.FileOffset if rva > importDesc.Data.Characteristics || rva > importDesc.Data.FirstThunk { - maxLen = Max(rva - importDesc.Data.Characteristics, rva - importDesc.Data.FirstThunk) + maxLen = Max(rva-importDesc.Data.Characteristics, rva-importDesc.Data.FirstThunk) } lastAddr := rva + maxLen @@ -208,7 +213,7 @@ func (self *PEFile) getImportTable(rva uint32, importDesc *lib.ImportDescriptor) // if the addresses point somewhere but the difference between the highest // and lowest address is larger than MAX_ADDRESS_SPREAD we assume a bogus // table as the addresses should be contained within a module - if maxAddressOfData - minAddressOfData > MAX_ADDRESS_SPREAD { + if maxAddressOfData-minAddressOfData > MAX_ADDRESS_SPREAD { return []*lib.ThunkData{}, errors.New("data addresses too spread out") } @@ -229,23 +234,23 @@ func (self *PEFile) getImportTable(rva uint32, importDesc *lib.ImportDescriptor) // Seen in PE with SHA256: // 5945bb6f0ac879ddf61b1c284f3b8d20c06b228e75ae4f571fa87f5b9512902c if thunk.Data.AddressOfData >= startRva && thunk.Data.AddressOfData <= rva { - log.Printf("Error parsing the import table. " + - "AddressOfData overlaps with THUNK_DATA for THUNK at:\n " + + log.Printf("Error parsing the import table. "+ + "AddressOfData overlaps with THUNK_DATA for THUNK at:\n "+ "RVA 0x%x", rva) break } if thunk.Data.AddressOfData > 0 { // If the entry looks like could be an ordinal... - if thunk.Data.AddressOfData & ordinalFlag > 0 { + if thunk.Data.AddressOfData&ordinalFlag > 0 { // but its value is beyond 2^16, we will assume it's a // corrupted and ignore it altogether - if thunk.Data.AddressOfData & uint32(0x7fffffff) > uint32(0xffff) { + if thunk.Data.AddressOfData&uint32(0x7fffffff) > uint32(0xffff) { msg := fmt.Sprintf("Corruption detected in thunk data at 0x%x", rva) log.Printf(msg) return []*lib.ThunkData{}, errors.New(msg) } - // and if it looks like it should be an RVA + // and if it looks like it should be an RVA } else { // keep track of the RVAs seen and store them to study their // properties. When certain non-standard features are detected @@ -278,4 +283,3 @@ func (self *PEFile) getImportTable64(rva uint64) []*lib.ThunkData64 { // todo not implemeted yet return []*lib.ThunkData64{} } - diff --git a/pefile-go/pe/pe.go b/pefile-go/pe/pe.go index eee9f40..eeb3e07 100644 --- a/pefile-go/pe/pe.go +++ b/pefile-go/pe/pe.go @@ -1,35 +1,35 @@ package pe -/* +/* TODO: figure out how to detect endianess instead of forcing LittleEndian */ import ( - "../lib" - "log" - mmap "github.com/edsrzf/mmap-go" - "os" "bytes" - "sort" "encoding/binary" "errors" -) + "log" + "os" + "sort" + mmap "github.com/edsrzf/mmap-go" + "github.com/soluwalana/pefile-go/pefile-go/lib" +) /* The representation of the PEFile with some helpful abstractions */ type PEFile struct { - Filename string - DosHeader *lib.DosHeader - NTHeader *lib.NTHeader - FileHeader *lib.FileHeader - OptionalHeader *lib.OptionalHeader - OptionalHeader64 *lib.OptionalHeader64 - Sections []*lib.SectionHeader - ImportDescriptors []*lib.ImportDescriptor - ExportDirectory *lib.ExportDirectory + Filename string + DosHeader *lib.DosHeader + NTHeader *lib.NTHeader + FileHeader *lib.FileHeader + OptionalHeader *lib.OptionalHeader + OptionalHeader64 *lib.OptionalHeader64 + Sections []*lib.SectionHeader + ImportDescriptors []*lib.ImportDescriptor + ExportDirectory *lib.ExportDirectory // Private Fields - data mmap.MMap - dataLen uint32 - headerEnd uint32 + data mmap.MMap + dataLen uint32 + headerEnd uint32 } func NewPEFile(filename string) (pe *PEFile, err error) { @@ -56,7 +56,7 @@ func NewPEFile(filename string) (pe *PEFile, err error) { if pe.DosHeader.Data.E_magic == IMAGE_DOSZM_SIGNATURE { return nil, errors.New("Probably a ZM Executable (not a PE file).") } - + if pe.DosHeader.Data.E_magic != IMAGE_DOS_SIGNATURE { return nil, errors.New("DOS Header magic not found.") } @@ -64,7 +64,7 @@ func NewPEFile(filename string) (pe *PEFile, err error) { if pe.DosHeader.Data.E_lfanew > pe.dataLen { return nil, errors.New("Invalid e_lfanew value, probably not a PE file") } - + offset = pe.DosHeader.Data.E_lfanew pe.NTHeader = lib.NewNTHeader(offset) @@ -123,7 +123,7 @@ func NewPEFile(filename string) (pe *PEFile, err error) { // Section data //MAX_ASSUMED_VALID_NUMBER_OF_RVA_AND_SIZES := 0x100 var numRvaAndSizes uint32 - + msg := "Suspicious NumberOfRvaAndSizes in the Optional Header." msg += "Normal values are never larger than 0x10, the value is: 0x%x\n" @@ -133,7 +133,7 @@ func NewPEFile(filename string) (pe *PEFile, err error) { if pe.OptionalHeader64 != nil { if pe.OptionalHeader64.Data.NumberOfRvaAndSizes > 0x10 { - log.Printf(msg, pe.OptionalHeader64.Data.NumberOfRvaAndSizes) + log.Printf(msg, pe.OptionalHeader64.Data.NumberOfRvaAndSizes) } numRvaAndSizes = pe.OptionalHeader64.Data.NumberOfRvaAndSizes offset += pe.OptionalHeader64.Size @@ -147,10 +147,10 @@ func NewPEFile(filename string) (pe *PEFile, err error) { offset += pe.OptionalHeader.Size dataDir = pe.OptionalHeader.DataDirs } - - for i := uint32(0); i < 0x7fffffff & numRvaAndSizes; i ++ { - if pe.dataLen - offset == 0 { + for i := uint32(0); i < 0x7fffffff&numRvaAndSizes; i++ { + + if pe.dataLen-offset == 0 { break } @@ -160,9 +160,9 @@ func NewPEFile(filename string) (pe *PEFile, err error) { } offset += dirEntry.Size name, ok := lib.DirectoryEntryTypes[i] - + dirEntry.Name = name - + if !ok { break } @@ -188,7 +188,7 @@ func NewPEFile(filename string) (pe *PEFile, err error) { err = pe.parseDataDirectories() if err != nil { - return nil , err + return nil, err } /*offset, err = pe.parseRichHeader() if err != nil { @@ -199,6 +199,7 @@ func NewPEFile(filename string) (pe *PEFile, err error) { } type ByVAddr []*lib.SectionHeader + func (self ByVAddr) Len() int { return len(self) } @@ -211,7 +212,7 @@ func (s ByVAddr) Less(i, j int) bool { func (self *PEFile) parseSections(offset uint32) (newOffset uint32, err error) { newOffset = offset - for i := uint32(0); i < uint32(self.FileHeader.Data.NumberOfSections); i ++ { + for i := uint32(0); i < uint32(self.FileHeader.Data.NumberOfSections); i++ { section := lib.NewSectionHeader(newOffset) if err = self.parseHeader(§ion.Data, newOffset, section.Size); err != nil { return 0, err @@ -224,19 +225,19 @@ func (self *PEFile) parseSections(offset uint32) (newOffset uint32, err error) { // Suspecious check L2383 - L2395 self.Sections = append(self.Sections, section) - + newOffset += section.Size } - + // Sort the sections by their VirtualAddress and add a field to each of them // with the VirtualAddress of the next section. This will allow to check // for potentially overlapping sections in badly constructed PEs. sort.Sort(ByVAddr(self.Sections)) for idx, section := range self.Sections { - if idx == len(self.Sections) - 1 { + if idx == len(self.Sections)-1 { section.NextHeaderAddr = 0 } else { - section.NextHeaderAddr = self.Sections[idx + 1].Data.VirtualAddress + section.NextHeaderAddr = self.Sections[idx+1].Data.VirtualAddress } } @@ -244,7 +245,7 @@ func (self *PEFile) parseSections(offset uint32) (newOffset uint32, err error) { } func (self *PEFile) parseHeader(iface interface{}, offset, size uint32) (err error) { - buf := bytes.NewReader(self.data[offset : offset + size]) + buf := bytes.NewReader(self.data[offset : offset+size]) err = binary.Read(buf, binary.LittleEndian, iface) if err != nil { return err @@ -259,7 +260,7 @@ func (self *PEFile) parseDataDirectories() error { "IMAGE_DIRECTORY_ENTRY_IMPORT": self.parseImportDirectory, "IMAGE_DIRECTORY_ENTRY_EXPORT": self.parseExportDirectory, //"IMAGE_DIRECTORY_ENTRY_RESOURCE": self.parse_resources_directory, - + // TODO at a later time //"IMAGE_DIRECTORY_ENTRY_DEBUG": self.parseDebugDirectory, //"IMAGE_DIRECTORY_ENTRY_BASERELOC": self.parseRelocationsDirectory, @@ -276,8 +277,10 @@ func (self *PEFile) parseDataDirectories() error { } for name, dirEntry := range dataDirs { if dirEntry.Data.VirtualAddress > 0 { - parser, ok := funcMap[name] - if !ok { continue } + parser, ok := funcMap[name] + if !ok { + continue + } err := parser.(func(uint32, uint32) error)(dirEntry.Data.VirtualAddress, dirEntry.Data.Size) if err != nil { return err @@ -292,18 +295,18 @@ func (self *PEFile) getSectionByRva(rva uint32) *lib.SectionHeader { for _, section := range self.Sections { var size uint32 adjustedPointer := self.adjustFileAlignment(section.Data.PointerToRawData) - if self.dataLen - adjustedPointer < section.Data.SizeOfRawData { + if self.dataLen-adjustedPointer < section.Data.SizeOfRawData { size = section.Data.Misc } else { size = Max(section.Data.SizeOfRawData, section.Data.Misc) } vaddr := self.adjustSectionAlignment(section.Data.VirtualAddress) - if section.NextHeaderAddr != 0 && section.NextHeaderAddr > section.Data.VirtualAddress && vaddr + size > section.NextHeaderAddr { + if section.NextHeaderAddr != 0 && section.NextHeaderAddr > section.Data.VirtualAddress && vaddr+size > section.NextHeaderAddr { size = section.NextHeaderAddr - vaddr } - if vaddr <= rva && rva < (vaddr + size) { + if vaddr <= rva && rva < (vaddr+size) { return section } } @@ -312,10 +315,12 @@ func (self *PEFile) getSectionByRva(rva uint32) *lib.SectionHeader { func (self *PEFile) getSectionByOffset(offset uint32) *lib.SectionHeader { for _, section := range self.Sections { - if section.Data.PointerToRawData == 0 { continue } - + if section.Data.PointerToRawData == 0 { + continue + } + adjustedPointer := self.adjustFileAlignment(section.Data.PointerToRawData) - if adjustedPointer <= offset && offset < (adjustedPointer + section.Data.SizeOfRawData) { + if adjustedPointer <= offset && offset < (adjustedPointer+section.Data.SizeOfRawData) { return section } } @@ -327,7 +332,9 @@ func (self *PEFile) getRvaFromOffset(offset uint32) uint32 { minAddr := ^uint32(0) if section == nil { - if len(self.Sections) == 0 { return offset } + if len(self.Sections) == 0 { + return offset + } for _, section := range self.Sections { vaddr := self.adjustSectionAlignment(section.Data.VirtualAddress) @@ -340,7 +347,9 @@ func (self *PEFile) getRvaFromOffset(offset uint32) uint32 { // http://corkami.blogspot.com/2010/01/hey-hey-hey-whats-in-your-head.html // where the import table is not contained by any section // hence the RVA needs to be resolved to a raw offset - if offset < minAddr { return offset } + if offset < minAddr { + return offset + } log.Println("data at Offset can't be fetched. Corrupt header?") return ^uint32(0) @@ -379,7 +388,7 @@ func (self *PEFile) getOffsetFromRva(rva uint32) uint32 { // The following is a hard-coded constant if the Windows loader func (self *PEFile) adjustFileAlignment(pointer uint32) uint32 { fileAlignment := self.OptionalHeader.Data.FileAlignment - + if fileAlignment > FILE_ALIGNMENT_HARDCODED_VALUE { // If it's not a power of two, report it: if !PowerOfTwo(fileAlignment) { @@ -411,13 +420,13 @@ func (self *PEFile) adjustSectionAlignment(pointer uint32) uint32 { sectionAlignment = fileAlignment } // else if sectionAlignment < 0x80 { - // 0x200 is the minimum valid FileAlignment according to the documentation - // although ntoskrnl.exe has an alignment of 0x80 in some Windows versions + // 0x200 is the minimum valid FileAlignment according to the documentation + // although ntoskrnl.exe has an alignment of 0x80 in some Windows versions // sectionAlignment = 0x80 //} - if sectionAlignment != 0 && (pointer % sectionAlignment) != 0 { - return sectionAlignment * ( pointer / sectionAlignment ) + if sectionAlignment != 0 && (pointer%sectionAlignment) != 0 { + return sectionAlignment * (pointer / sectionAlignment) } return pointer } @@ -463,14 +472,14 @@ func (self *PEFile) getDataBounds(rva, length uint32) (start, size uint32) { } else { end = offset + section.Data.SizeOfRawData } - if end > pointer + section.Data.SizeOfRawData { + if end > pointer+section.Data.SizeOfRawData { end = section.Data.PointerToRawData + section.Data.SizeOfRawData } return offset, end } -// Get an ASCII string from within the data at an RVA considering -// section +// Get an ASCII string from within the data at an RVA considering +// section func (self *PEFile) getStringAtRva(rva uint32) []byte { start, _ := self.getDataBounds(rva, 0) return self.getStringFromData(start) @@ -497,7 +506,7 @@ func (self *PEFile) getStringFromData(offset uint32) []byte { // greater than 0 // fc91013eb72529da005110a3403541b6 example // Should this throw an exception in the minimum header offset -// can't be found? +// can't be found? func (self *PEFile) calculateHeaderEnd(offset uint32) { var rawDataPointers []uint32 for _, section := range self.Sections { @@ -521,4 +530,3 @@ func (self *PEFile) calculateHeaderEnd(offset uint32) { self.headerEnd = minSectionOffset } } - diff --git a/pefile-go/pefile.go b/pefile-go/pefile.go index 4bbff6b..d919632 100644 --- a/pefile-go/pefile.go +++ b/pefile-go/pefile.go @@ -1,10 +1,12 @@ package main import ( - "./pe" "log" "os" + + "github.com/soluwalana/pefile-go/pefile-go/pe" ) + func main() { log.Println("hello everyone, lets parse your PEFile") args := os.Args[1:] @@ -57,4 +59,4 @@ func main() { log.Println(string(entry.Name)) } -} \ No newline at end of file +}