From 1d997ecd1c38820ff624aca71f14561517500b8c Mon Sep 17 00:00:00 2001 From: huoxue1 <3343780376@qq.com> Date: Fri, 7 Jul 2023 19:27:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E4=BB=93=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/.gitignore | 8 ++ .idea/PePase.iml | 9 +++ .idea/modules.xml | 8 ++ go.mod | 3 + pe.go | 199 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 227 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/PePase.iml create mode 100644 .idea/modules.xml create mode 100644 go.mod create mode 100644 pe.go diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/PePase.iml b/.idea/PePase.iml new file mode 100644 index 0000000..5e764c4 --- /dev/null +++ b/.idea/PePase.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..6e8ae36 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..88539c3 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module PeParse + +go 1.20 diff --git a/pe.go b/pe.go new file mode 100644 index 0000000..223823b --- /dev/null +++ b/pe.go @@ -0,0 +1,199 @@ +package main + +import ( + "encoding/binary" + "fmt" + "io" + "os" + "strings" +) + +type IMAGE_DOS_HEADER struct { + Emagic uint16 + Ecblp uint16 + Ecp uint16 + Ecrlc uint16 + Ecparhdr uint16 + Eminalloc uint16 + Emaxalloc uint16 + Ess uint16 + Esp uint16 + Ecsum uint16 + Eip uint16 + Ecs uint16 + Elfarlc uint16 + Eovno uint16 + Eres uint64 + Eoemid uint16 + Eoeminfo uint16 + Eres2 [20]byte + Elfanew uint32 +} + +type IMAGE_NT_HEADERS32 struct { + Signature uint32 + FileHeader IMAGE_FILE_HEADER + OptionalHeader IMAGE_OPTIONAL_HEADER32 +} + +type IMAGE_FILE_HEADER struct { + Machine uint16 + NumberOfSections uint16 + TimeDateStamp uint32 + PointerToSymbolTable uint32 + NumberOfSymbols uint32 + SizeOfOptionalHeader uint16 + Characteristics uint16 +} + +type IMAGE_OPTIONAL_HEADER32 struct { + Magic uint16 + MajorLinkerVersion byte + MinorLinkerVersion byte + SizeOfCode uint32 + SizeOfInitializedData uint32 + SizeOfUninitializedData uint32 + AddressOfEntryPoint uint32 + BaseOfCode uint32 + BaseOfData uint32 + ImageBase uint32 + //ImageBase uint64 + SectionAlignment uint32 + FileAlignment uint32 + MajorOperatingSystemVersion uint16 + MinorOperatingSystemVersion uint16 + MajorImageVersion uint16 + MinorImageVersion uint16 + MajorSubsystemVersion uint16 + MinorSubsystemVersion uint16 + Win32VersionValue uint32 + SizeOfImage uint32 + SizeOfHeaders uint32 + CheckSum uint32 + Subsystem uint16 + DllCharacteristics uint16 + SizeOfStackReserve uint32 + SizeOfStackCommit uint32 + SizeOfHeapReserve uint32 + SizeOfHeapCommit uint32 + //SizeOfStackReserve uint64 + //SizeOfStackCommit uint64 + //SizeOfHeapReserve uint64 + //SizeOfHeapCommit uint64 + LoaderFlags uint32 + NumberOfRvaAndSizes uint32 + DataDirectory [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]IMAGE_DATA_DIRECTORY +} + +type IMAGE_DATA_DIRECTORY struct { + VirtualAddress uint32 + Size uint32 +} + +const IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16 + +type IMAGE_SECTION_HEADER struct { + Name [8]byte + Misc uint32 + VirtualAddress uint32 + SizeOfRawData uint32 + PointerToRawData uint32 + PointerToRelocations uint32 + PointerToLinenumbers uint32 + NumberOfRelocations uint16 + NumberOfLinenumbers uint16 + Characteristics uint32 +} + +type IMAGE_RESOURCE_DIRECTORY struct { + Characteristics uint32 + TimeDateStamp uint32 + MajorVersion uint16 + MinorVersion uint16 + NumberOfNamedEntries uint16 + NumberOfIdEntries uint16 +} + +type IMAGE_RESOURCE_Entity struct { + Id uint32 + Offset uint32 +} + +type Resource struct { + Directory *IMAGE_RESOURCE_DIRECTORY + Entities []RealEntity +} + +type RealEntity struct { + IMAGE_RESOURCE_Entity + Childern Resource + IsFolder bool +} + +func ParsePe() { + data, _ := os.Open("D:\\software\\qq\\Bin\\QQ.exe") + doc := new(IMAGE_DOS_HEADER) + binary.Read(data, binary.LittleEndian, doc) + data.Seek(int64(doc.Elfanew), 0) + nt := new(IMAGE_NT_HEADERS32) + binary.Read(data, binary.LittleEndian, nt) + fmt.Printf("%v", nt.FileHeader.NumberOfSections) + //for _, directory := range nt.OptionalHeader.DataDirectory { + // fmt.Printf("\n%X,%X ", directory.VirtualAddress, directory.Size) + //} + sectionTables := make(map[string]*IMAGE_SECTION_HEADER) + for i := 0; i < int(nt.FileHeader.NumberOfSections); i++ { + head := new(IMAGE_SECTION_HEADER) + binary.Read(data, binary.LittleEndian, head) + sectionTables[strings.ReplaceAll(fmt.Sprintf("%s", head.Name), "\x00", "")] = head + fmt.Println(strings.ReplaceAll(fmt.Sprintf("%s", head.Name), "\x00", "") == ".rsrc") + } + resourceTable := sectionTables[".rsrc"] + for s, h := range sectionTables { + fmt.Printf("\n%q,%v", s, h.PointerToRawData) + } + fmt.Println(resourceTable) + + resource := ParseResource(data, int64(resourceTable.PointerToRawData), 0) + + fmt.Println(resource) +} + +func ParseResource(reader io.ReadSeeker, startOffset int64, offset int64) Resource { + reader.Seek(startOffset+offset, 0) + dir := new(IMAGE_RESOURCE_DIRECTORY) + binary.Read(reader, binary.LittleEndian, dir) + entities := make([]RealEntity, dir.NumberOfIdEntries+dir.NumberOfNamedEntries) + for i := 0; i < int(dir.NumberOfIdEntries+dir.NumberOfNamedEntries); i++ { + entity := new(IMAGE_RESOURCE_Entity) + binary.Read(reader, binary.LittleEndian, entity) + realEntity := &RealEntity{} + realEntity.IMAGE_RESOURCE_Entity = *entity + if isHighestBitSet(entity.Offset) { + realEntity.IsFolder = true + realEntity.Offset = entity.Offset & 0x7FFFFFFF + } + entities[i] = *realEntity + } + newEntities := make([]RealEntity, dir.NumberOfIdEntries+dir.NumberOfNamedEntries) + for i, entity := range entities { + if entity.IsFolder { + entity.Childern = ParseResource(reader, startOffset, int64(entity.Offset)) + } + newEntities[i] = entity + + } + return Resource{Directory: dir, Entities: newEntities} +} + +func isHighestBitSet(value uint32) bool { + // 右移 24 位,使最高位移到最低位 + highestBit := (value >> 31) & 0x01 + + // 判断最高位是否为 1 + return highestBit == 1 +} + +func main() { + ParsePe() +}