不使用debug/pe库
时间: 2023-07-30 15:07:15 浏览: 184
如果不使用`debug/pe`库,可以手动解析PE文件头和导入表。下面是一个简单的示例代码:
```go
package main
import (
"encoding/binary"
"fmt"
"os"
)
type IMAGE_DATA_DIRECTORY struct {
VirtualAddress uint32
Size uint32
}
type IMAGE_IMPORT_DESCRIPTOR struct {
OriginalFirstThunk uint32
TimeDateStamp uint32
ForwarderChain uint32
Name uint32
FirstThunk uint32
}
func checkError(err error) {
if err != nil {
fmt.Println("Error:", err)
os.Exit(1)
}
}
func main() {
if len(os.Args) != 2 {
fmt.Println("Usage: pe_imports <exe/dll>")
os.Exit(1)
}
file, err := os.Open(os.Args[1])
checkError(err)
defer file.Close()
// 读取PE文件头
var dosHeader struct {
Magic uint16
Lfanew int32
_ [58]byte
PeHeader [4]byte
}
err = binary.Read(file, binary.LittleEndian, &dosHeader)
checkError(err)
if dosHeader.Magic != 0x5a4d {
fmt.Println("Error: not a valid DOS header")
os.Exit(1)
}
if string(dosHeader.PeHeader[:]) != "PE\x00\x00" {
fmt.Println("Error: not a valid PE header")
os.Exit(1)
}
_, err = file.Seek(int64(dosHeader.Lfanew), 0)
checkError(err)
var peHeader struct {
_ [4]byte
Machine uint16
NumberOfSections uint16
TimeDateStamp uint32
PointerToSymbolTable uint32
NumberOfSymbols uint32
SizeOfOptionalHeader uint16
Characteristics uint16
Magic uint16
MajorLinkerVersion byte
MinorLinkerVersion byte
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]IMAGE_DATA_DIRECTORY
}
err = binary.Read(file, binary.LittleEndian, &peHeader)
checkError(err)
if peHeader.Magic != 0x10b && peHeader.Magic != 0x20b {
fmt.Println("Error: not a valid PE32/PE32+ header")
os.Exit(1)
}
// 获取导入表
importDirectory := peHeader.DataDirectory[1]
if importDirectory.VirtualAddress == 0 || importDirectory.Size == 0 {
fmt.Println("No import table found")
return
}
importTable := make([]IMAGE_IMPORT_DESCRIPTOR, importDirectory.Size/20)
_, err = file.Seek(int64(importDirectory.VirtualAddress), 0)
checkError(err)
err = binary.Read(file, binary.LittleEndian, importTable)
checkError(err)
fmt.Printf("Imported symbols for %s:\n", os.Args[1])
for _, importDesc := range importTable {
if importDesc.Name == 0 {
break
}
nameAddr := int64(importDesc.Name - peHeader.ImageBase)
_, err = file.Seek(nameAddr, 0)
checkError(err)
nameBuf := make([]byte, 1)
var name []byte
for {
err = binary.Read(file, binary.LittleEndian, &nameBuf)
checkError(err)
if nameBuf[0] == 0 {
break
}
name = append(name, nameBuf[0])
}
fmt.Printf("%s (from %s)\n", string(name), os.Args[1])
}
}
```
该程序也可以输出PE文件的导入表信息。需要注意的是,该程序仅支持PE32和PE32+格式的文件。
阅读全文