【golang解析pe文件】

golang解析pe文件

PE图

请添加图片描述

DM

package main

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"os"
	"unsafe"
)

// DOS 头部结构
type ImageDOSHeader struct {
	Signature                [2]byte // "MZ"
	BytesOnLastPage          uint16
	PagesInFile              uint16
	Relocations              uint16
	SizeOfHeader             uint16
	MinExtraParagraphs       uint16
	MaxExtraParagraphs       uint16
	InitialSS                uint16
	InitialSP                uint16
	Checksum                 uint16
	InitialIP                uint16
	InitialCS                uint16
	AddressOfRelocationTable uint16
	OverlayNumber            uint16
	Reserved1                [4]uint16
	OEMID                    uint16
	OEMInfo                  uint16
	Reserved2                [10]uint16
	AddressOfNewExeHeader    uint32 // e_lfanew
}

// NT 头部结构
type ImageNTHeaders struct {
	Signature      [4]byte // "PE\0\0"
	FileHeader     ImageFileHeader
	OptionalHeader ImageOptionalHeader
}

// 文件头部结构
type ImageFileHeader struct {
	Machine              uint16
	NumberOfSections     uint16
	TimeDateStamp        uint32
	PointerToSymbolTable uint32
	NumberOfSymbols      uint32
	SizeOfOptionalHeader uint16
	Characteristics      uint16
}

// 可选头部结构 (通用)
type ImageOptionalHeader struct {
	Magic                       uint16
	MajorLinkerVersion          uint8
	MinorLinkerVersion          uint8
	SizeOfCode                  uint32
	SizeOfInitializedData       uint32
	SizeOfUninitializedData     uint32
	AddressOfEntryPoint         uint32
	BaseOfCode                  uint32
	BaseOfData                  uint32 // 32位专用
	ImageBase                   uint64 // 64位使用64位地址
	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          uint64
	SizeOfStackCommit           uint64
	SizeOfHeapReserve           uint64
	SizeOfHeapCommit            uint64
	LoaderFlags                 uint32
	NumberOfRvaAndSizes         uint32
	DataDirectory               [16]ImageDataDirectory
}

// 数据目录结构
type ImageDataDirectory struct {
	VirtualAddress uint32
	Size           uint32
}

// 节表结构
type ImageSectionHeader struct {
	Name                 [8]byte
	VirtualSize          uint32
	VirtualAddress       uint32
	SizeOfRawData        uint32
	PointerToRawData     uint32
	PointerToRelocations uint32
	PointerToLinenumbers uint32
	NumberOfRelocations  uint16
	NumberOfLinenumbers  uint16
	Characteristics      uint32
}

// PE 文件解析器
type PEResolver struct {
	file           *os.File
	dosHeader      ImageDOSHeader
	ntHeaders      ImageNTHeaders
	sectionHeaders []ImageSectionHeader
	is64Bit        bool
	data           []byte
	imageBuffer    []byte // 拉伸后的内存映像
	fileBuffer     []byte // 转回后的文件缓冲区
}

// 打开 PE 文件
func OpenPEFile(filename string) (*PEResolver, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, err
	}

	// 读取整个文件内容
	data, err := io.ReadAll(file)
	if err != nil {
		file.Close()
		return nil, err
	}

	pe := &PEResolver{
		file: file,
		data: data,
	}

	// 解析 DOS 头部
	if err := pe.parseDOSHeader(); err != nil {
		return nil, err
	}

	// 解析 NT 头部
	if err := pe.parseNTHeaders(); err != nil {
		return nil, err
	}

	// 解析节表
	if err := pe.parseSectionHeaders(); err != nil {
		return nil, err
	}

	return pe, nil
}

// 解析 DOS 头部
func (pe *PEResolver) parseDOSHeader() error {
	if len(pe.data) < int(unsafe.Sizeof(ImageDOSHeader{})) {
		return errors.New("文件太小,不是有效的 PE 文件")
	}

	buf := bytes.NewReader(pe.data)
	if err := binary.Read(buf, binary.LittleEndian, &pe.dosHeader); err != nil {
		return err
	}

	// 验证 DOS 签名
	if string(pe.dosHeader.Signature[:]) != "MZ" {
		return errors.New("不是有效的 PE 文件: 缺少 MZ 签名")
	}

	return nil
}

// 解析 NT 头部
func (pe *PEResolver) parseNTHeaders() error {
	offset := int64(pe.dosHeader.AddressOfNewExeHeader)
	if offset+int64(unsafe.Sizeof(ImageNTHeaders{})) > int64(len(pe.data)) {
		return errors.New("文件太小,无法包含 NT 头部")
	}

	// 读取 NT 签名
	var signature [4]byte
	copy(signature[:], pe.data[offset:offset+4])
	if string(signature[:]) != "PE\x00\x00" {
		fmt.Println(string(signature[:]))
		return errors.New("不是有效的 PE 文件: 缺少 PE 签名")
	}

	// 读取文件头部
	buf := bytes.NewReader(pe.data[offset+4:])
	if err := binary.Read(buf, binary.LittleEndian, &pe.ntHeaders.FileHeader); err != nil {
		return err
	}

	// 读取可选头部
	pe.is64Bit = (pe.ntHeaders.FileHeader.Machine == 0x8664) // IMAGE_FILE_MACHINE_AMD64

	if pe.is64Bit {
		// 64位可选头部
		var optionalHeader64 ImageOptionalHeader64
		if err := binary.Read(buf, binary.LittleEndian, &optionalHeader64); err != nil {
			return err
		}
		// 将64位可选头部转换为通用结构
		pe.ntHeaders.OptionalHeader.Magic = optionalHeader64.Magic
		pe.ntHeaders.OptionalHeader.MajorLinkerVersion = optionalHeader64.MajorLinkerVersion
		pe.ntHeaders.OptionalHeader.MinorLinkerVersion = optionalHeader64.MinorLinkerVersion
		pe.ntHeaders.OptionalHeader.SizeOfCode = optionalHeader64.SizeOfCode
		pe.ntHeaders.OptionalHeader.SizeOfInitializedData = optionalHeader64.SizeOfInitializedData
		pe.ntHeaders.OptionalHeader.SizeOfUninitializedData = optionalHeader64.SizeOfUninitializedData
		pe.ntHeaders.OptionalHeader.AddressOfEntryPoint = optionalHeader64.AddressOfEntryPoint
		pe.ntHeaders.OptionalHeader.BaseOfCode = optionalHeader64.BaseOfCode
		pe.ntHeaders.OptionalHeader.ImageBase = optionalHeader64.ImageBase
		pe.ntHeaders.OptionalHeader.SectionAlignment = optionalHeader64.SectionAlignment
		pe.ntHeaders.OptionalHeader.FileAlignment = optionalHeader64.FileAlignment
		pe.ntHeaders.OptionalHeader.MajorOperatingSystemVersion = optionalHeader64.MajorOperatingSystemVersion
		pe.ntHeaders.OptionalHeader.MinorOperatingSystemVersion = optionalHeader64.MinorOperatingSystemVersion
		pe.ntHeaders.OptionalHeader.MajorImageVersion = optionalHeader64.MajorImageVersion
		pe.ntHeaders.OptionalHeader.MinorImageVersion = optionalHeader64.MinorImageVersion
		pe.ntHeaders.OptionalHeader.MajorSubsystemVersion = optionalHeader64.MajorSubsystemVersion
		pe.ntHeaders.OptionalHeader.MinorSubsystemVersion = optionalHeader64.MinorSubsystemVersion
		pe.ntHeaders.OptionalHeader.Win32VersionValue = optionalHeader64.Win32VersionValue
		pe.ntHeaders.OptionalHeader.SizeOfImage = optionalHeader64.SizeOfImage
		pe.ntHeaders.OptionalHeader.SizeOfHeaders = optionalHeader64.SizeOfHeaders
		pe.ntHeaders.OptionalHeader.CheckSum = optionalHeader64.CheckSum
		pe.ntHeaders.OptionalHeader.Subsystem = optionalHeader64.Subsystem
		pe.ntHeaders.OptionalHeader.DllCharacteristics = optionalHeader64.DllCharacteristics
		pe.ntHeaders.OptionalHeader.SizeOfStackReserve = optionalHeader64.SizeOfStackReserve
		pe.ntHeaders.OptionalHeader.SizeOfStackCommit = optionalHeader64.SizeOfStackCommit
		pe.ntHeaders.OptionalHeader.SizeOfHeapReserve = optionalHeader64.SizeOfHeapReserve
		pe.ntHeaders.OptionalHeader.SizeOfHeapCommit = optionalHeader64.SizeOfHeapCommit
		pe.ntHeaders.OptionalHeader.LoaderFlags = optionalHeader64.LoaderFlags
		pe.ntHeaders.OptionalHeader.NumberOfRvaAndSizes = optionalHeader64.NumberOfRvaAndSizes
		copy(pe.ntHeaders.OptionalHeader.DataDirectory[:], optionalHeader64.DataDirectory[:])
	} else {
		// 32位可选头部
		var optionalHeader32 ImageOptionalHeader32
		if err := binary.Read(buf, binary.LittleEndian, &optionalHeader32); err != nil {
			return err
		}
		// 将32位可选头部转换为通用结构
		pe.ntHeaders.OptionalHeader.Magic = optionalHeader32.Magic
		pe.ntHeaders.OptionalHeader.MajorLinkerVersion = optionalHeader32.MajorLinkerVersion
		pe.ntHeaders.OptionalHeader.MinorLinkerVersion = optionalHeader32.MinorLinkerVersion
		pe.ntHeaders.OptionalHeader.SizeOfCode = optionalHeader32.SizeOfCode
		pe.ntHeaders.OptionalHeader.SizeOfInitializedData = optionalHeader32.SizeOfInitializedData
		pe.ntHeaders.OptionalHeader.SizeOfUninitializedData = optionalHeader32.SizeOfUninitializedData
		pe.ntHeaders.OptionalHeader.AddressOfEntryPoint = optionalHeader32.AddressOfEntryPoint
		pe.ntHeaders.OptionalHeader.BaseOfCode = optionalHeader32.BaseOfCode
		pe.ntHeaders.OptionalHeader.BaseOfData = optionalHeader32.BaseOfData
		pe.ntHeaders.OptionalHeader.ImageBase = uint64(optionalHeader32.ImageBase)
		pe.ntHeaders.OptionalHeader.SectionAlignment = optionalHeader32.SectionAlignment
		pe.ntHeaders.OptionalHeader.FileAlignment = optionalHeader32.FileAlignment
		pe.ntHeaders.OptionalHeader.MajorOperatingSystemVersion = optionalHeader32.MajorOperatingSystemVersion
		pe.ntHeaders.OptionalHeader.MinorOperatingSystemVersion = optionalHeader32.MinorOperatingSystemVersion
		pe.ntHeaders.OptionalHeader.MajorImageVersion = optionalHeader32.MajorImageVersion
		pe.ntHeaders.OptionalHeader.MinorImageVersion = optionalHeader32.MinorImageVersion
		pe.ntHeaders.OptionalHeader.MajorSubsystemVersion = optionalHeader32.MajorSubsystemVersion
		pe.ntHeaders.OptionalHeader.MinorSubsystemVersion = optionalHeader32.MinorSubsystemVersion
		pe.ntHeaders.OptionalHeader.Win32VersionValue = optionalHeader32.Win32VersionValue
		pe.ntHeaders.OptionalHeader.SizeOfImage = optionalHeader32.SizeOfImage
		pe.ntHeaders.OptionalHeader.SizeOfHeaders = optionalHeader32.SizeOfHeaders
		pe.ntHeaders.OptionalHeader.CheckSum = optionalHeader32.CheckSum
		pe.ntHeaders.OptionalHeader.Subsystem = optionalHeader32.Subsystem
		pe.ntHeaders.OptionalHeader.DllCharacteristics = optionalHeader32.DllCharacteristics
		pe.ntHeaders.OptionalHeader.SizeOfStackReserve = uint64(optionalHeader32.SizeOfStackReserve)
		pe.ntHeaders.OptionalHeader.SizeOfStackCommit = uint64(optionalHeader32.SizeOfStackCommit)
		pe.ntHeaders.OptionalHeader.SizeOfHeapReserve = uint64(optionalHeader32.SizeOfHeapReserve)
		pe.ntHeaders.OptionalHeader.SizeOfHeapCommit = uint64(optionalHeader32.SizeOfHeapCommit)
		pe.ntHeaders.OptionalHeader.LoaderFlags = optionalHeader32.LoaderFlags
		pe.ntHeaders.OptionalHeader.NumberOfRvaAndSizes = optionalHeader32.NumberOfRvaAndSizes
		copy(pe.ntHeaders.OptionalHeader.DataDirectory[:], optionalHeader32.DataDirectory[:])
	}

	return nil
}

// 解析节表
func (pe *PEResolver) parseSectionHeaders() error {
	numSections := pe.ntHeaders.FileHeader.NumberOfSections
	if numSections == 0 {
		return errors.New("PE 文件没有节表")
	}

	// 计算节表的起始位置
	offset := int64(pe.dosHeader.AddressOfNewExeHeader) + 4 +
		int64(unsafe.Sizeof(ImageFileHeader{})) +
		int64(pe.ntHeaders.FileHeader.SizeOfOptionalHeader)

	// 确保有足够的数据
	if offset+int64(numSections)*int64(unsafe.Sizeof(ImageSectionHeader{})) > int64(len(pe.data)) {
		return errors.New("文件太小,无法包含完整的节表")
	}

	// 读取所有节表项
	pe.sectionHeaders = make([]ImageSectionHeader, numSections)
	buf := bytes.NewReader(pe.data[offset:])

	for i := 0; i < int(numSections); i++ {
		if err := binary.Read(buf, binary.LittleEndian, &pe.sectionHeaders[i]); err != nil {
			return err
		}
	}

	return nil
}

// 拉伸 PE 文件到内存映像
func (pe *PEResolver) StretchToImageBuffer() error {
	// 创建内存映像缓冲区,大小为 PE 文件头中指定的 SizeOfImage
	imageSize := pe.ntHeaders.OptionalHeader.SizeOfImage
	if imageSize == 0 {
		return errors.New("PE 文件的 SizeOfImage 为 0,无法拉伸")
	}

	pe.imageBuffer = make([]byte, imageSize)

	// 复制 PE 文件头到内存映像的开始位置
	headerSize := pe.ntHeaders.OptionalHeader.SizeOfHeaders
	if int(headerSize) > len(pe.data) {
		return errors.New("PE 文件头大小超过实际文件大小")
	}

	copy(pe.imageBuffer[:headerSize], pe.data[:headerSize])

	// 处理每个节
	for _, section := range pe.sectionHeaders {
		// 节在内存中的虚拟地址
		virtualAddr := section.VirtualAddress

		// 节在文件中的原始数据大小和位置
		rawDataSize := section.SizeOfRawData
		rawDataPtr := section.PointerToRawData

		// 节的虚拟大小(可能大于原始数据大小)
		virtualSize := section.VirtualSize

		// 确保内存映像缓冲区足够大
		if virtualAddr+virtualSize > imageSize {
			return fmt.Errorf("节 %s 超出内存映像范围", string(bytes.TrimRight(section.Name[:], "\x00")))
		}

		// 如果节有原始数据,复制到内存映像
		if rawDataSize > 0 && rawDataPtr > 0 {
			// 确保文件数据足够
			if int(rawDataPtr+rawDataSize) > len(pe.data) {
				return fmt.Errorf("节 %s 的原始数据超出文件范围", string(bytes.TrimRight(section.Name[:], "\x00")))
			}

			// 复制原始数据到内存映像
			copy(pe.imageBuffer[virtualAddr:virtualAddr+rawDataSize],
				pe.data[rawDataPtr:rawDataPtr+rawDataSize])
		}

		// 如果虚拟大小大于原始数据大小,剩余部分填充为0(BSS段)
		if virtualSize > rawDataSize {
			zeroStart := virtualAddr + rawDataSize
			zeroLen := virtualSize - rawDataSize
			for i := uint32(0); i < zeroLen; i++ {
				pe.imageBuffer[zeroStart+i] = 0
			}
		}
	}

	return nil
}

// 将内存映像转回文件缓冲区
func (pe *PEResolver) ConvertImageToFileBuffer() error {
	if pe.imageBuffer == nil {
		return errors.New("请先调用 StretchToImageBuffer 生成内存映像")
	}

	// 计算文件缓冲区的大小
	// 文件大小 = 头部大小 + 所有节在文件中的大小总和
	headerSize := pe.ntHeaders.OptionalHeader.SizeOfHeaders
	maxFileSize := headerSize

	// 找到所有节的最大结束位置
	for _, section := range pe.sectionHeaders {
		sectionEnd := section.PointerToRawData + section.SizeOfRawData
		if sectionEnd > maxFileSize {
			maxFileSize = sectionEnd
		}
	}

	// 创建文件缓冲区
	pe.fileBuffer = make([]byte, maxFileSize)

	// 复制头部(DOS头、NT头、节表)
	copy(pe.fileBuffer[:headerSize], pe.imageBuffer[:headerSize])

	// 处理每个节,将内存中的数据转回文件格式
	for _, section := range pe.sectionHeaders {
		virtualAddr := section.VirtualAddress
		rawDataSize := section.SizeOfRawData
		rawDataPtr := section.PointerToRawData
		virtualSize := section.VirtualSize

		// 确保内存映像有足够的数据
		if virtualAddr+virtualSize > uint32(len(pe.imageBuffer)) {
			return fmt.Errorf("节 %s 超出内存映像范围", string(bytes.TrimRight(section.Name[:], "\x00")))
		}

		// 确保文件缓冲区有足够空间
		if rawDataPtr+rawDataSize > uint32(len(pe.fileBuffer)) {
			return fmt.Errorf("节 %s 超出文件缓冲区范围", string(bytes.TrimRight(section.Name[:], "\x00")))
		}

		// 复制数据回文件缓冲区
		if rawDataSize > 0 {
			// 计算实际需要复制的数据长度(取虚拟大小和原始数据大小的最小值)
			copySize := rawDataSize
			if virtualSize < rawDataSize {
				copySize = virtualSize
			}

			copy(pe.fileBuffer[rawDataPtr:rawDataPtr+copySize],
				pe.imageBuffer[virtualAddr:virtualAddr+copySize])

			// 如果原始数据大小大于虚拟大小,剩余部分填充0
			if copySize < rawDataSize {
				paddingSize := rawDataSize - copySize
				paddingStart := rawDataPtr + copySize
				for i := uint32(0); i < paddingSize; i++ {
					pe.fileBuffer[paddingStart+i] = 0
				}
			}
		}
	}

	return nil
}

// 获取拉伸后的内存映像
func (pe *PEResolver) GetImageBuffer() []byte {
	return pe.imageBuffer
}

// 获取文件缓冲区
func (pe *PEResolver) GetFileBuffer() []byte {
	return pe.fileBuffer
}

// 打印 PE 文件信息
func (pe *PEResolver) PrintInfo() {
	fmt.Println("=== PE 文件信息 ===")
	fmt.Printf("DOS 签名: %s\n", string(pe.dosHeader.Signature[:]))
	fmt.Printf("NT 签名: %s\n", string(pe.ntHeaders.Signature[:]))

	// 打印机器类型
	machineType := "Unknown"
	switch pe.ntHeaders.FileHeader.Machine {
	case 0x014c:
		machineType = "Intel 386"
	case 0x8664:
		machineType = "AMD64"
	}
	fmt.Printf("机器类型: %s\n", machineType)

	// 打印入口点
	fmt.Printf("入口点地址: 0x%X\n", pe.ntHeaders.OptionalHeader.AddressOfEntryPoint)

	// 打印内存布局信息
	fmt.Printf("映像基址: 0x%X\n", pe.ntHeaders.OptionalHeader.ImageBase)
	fmt.Printf("映像大小: 0x%X (%d 字节)\n",
		pe.ntHeaders.OptionalHeader.SizeOfImage,
		pe.ntHeaders.OptionalHeader.SizeOfImage)
	fmt.Printf("文件头大小: 0x%X (%d 字节)\n",
		pe.ntHeaders.OptionalHeader.SizeOfHeaders,
		pe.ntHeaders.OptionalHeader.SizeOfHeaders)

	// 打印节表信息
	fmt.Println("\n=== 节表信息 ===")
	for i, section := range pe.sectionHeaders {
		fmt.Printf("节 #%d: %s\n", i+1, string(bytes.TrimRight(section.Name[:], "\x00")))
		fmt.Printf("  虚拟地址: 0x%X\n", section.VirtualAddress)
		fmt.Printf("  虚拟大小: 0x%X\n", section.VirtualSize)
		fmt.Printf("  原始数据大小: 0x%X\n", section.SizeOfRawData)
		fmt.Printf("  原始数据指针: 0x%X\n", section.PointerToRawData)
	}
}

// 关闭文件
func (pe *PEResolver) Close() {
	pe.file.Close()
}

func main() {
	if len(os.Args) < 2 {
		fmt.Println("用法: go run pe_parser.go <PE文件路径>")
		return
	}

	filename := os.Args[1]
	pe, err := OpenPEFile(filename)
	if err != nil {
		fmt.Printf("打开 PE 文件失败: %v\n", err)
		return
	}
	defer pe.Close()

	pe.PrintInfo()

	// 拉伸 PE 文件到内存映像
	err = pe.StretchToImageBuffer()
	if err != nil {
		fmt.Printf("拉伸 PE 文件失败: %v\n", err)
		return
	}

	// 打印拉伸后的内存映像信息
	imageBuffer := pe.GetImageBuffer()
	fmt.Printf("\n=== 内存映像信息 ===\n")
	fmt.Printf("内存映像大小: %d 字节\n", len(imageBuffer))

	// 将内存映像转回文件缓冲区
	err = pe.ConvertImageToFileBuffer()
	if err != nil {
		fmt.Printf("转换回文件格式失败: %v\n", err)
		return
	}

	// 打印文件缓冲区信息
	fileBuffer := pe.GetFileBuffer()
	fmt.Printf("\n=== 文件缓冲区信息 ===\n")
	fmt.Printf("文件缓冲区大小: %d 字节\n", len(fileBuffer))

	// 保存内存映像到文件
	pwd, _ := os.Getwd()
	outputImageFile := pwd + "ss.stretched"
	err = saveBufferToFile(outputImageFile, imageBuffer)
	if err != nil {
		fmt.Printf("保存内存映像失败: %v\n", err)
	} else {
		fmt.Printf("\n内存映像已保存到: %s\n", outputImageFile)
	}

	// 保存文件缓冲区到文件
	outputFile := pwd + "ss.rebuilt"
	err = saveBufferToFile(outputFile, fileBuffer)
	if err != nil {
		fmt.Printf("保存重建文件失败: %v\n", err)
	} else {
		fmt.Printf("重建文件已保存到: %s\n", outputFile)
	}
}

// 保存缓冲区到文件
func saveBufferToFile(filename string, buffer []byte) error {
	file, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer file.Close()

	_, err = file.Write(buffer)
	return err
}

// 64位可选头部结构
type ImageOptionalHeader64 struct {
	Magic                       uint16
	MajorLinkerVersion          uint8
	MinorLinkerVersion          uint8
	SizeOfCode                  uint32
	SizeOfInitializedData       uint32
	SizeOfUninitializedData     uint32
	AddressOfEntryPoint         uint32
	BaseOfCode                  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          uint64
	SizeOfStackCommit           uint64
	SizeOfHeapReserve           uint64
	SizeOfHeapCommit            uint64
	LoaderFlags                 uint32
	NumberOfRvaAndSizes         uint32
	DataDirectory               [16]ImageDataDirectory
}

// 32位可选头部结构
type ImageOptionalHeader32 struct {
	Magic                       uint16
	MajorLinkerVersion          uint8
	MinorLinkerVersion          uint8
	SizeOfCode                  uint32
	SizeOfInitializedData       uint32
	SizeOfUninitializedData     uint32
	AddressOfEntryPoint         uint32
	BaseOfCode                  uint32
	BaseOfData                  uint32
	ImageBase                   uint32
	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
	LoaderFlags                 uint32
	NumberOfRvaAndSizes         uint32
	DataDirectory               [16]ImageDataDirectory
}

//go run main.go "C:\Windows\System32\notepad.exe"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值