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()
+}