pe is a go package for parsing the portable executable file format. This package was designed with malware analysis in mind, and being resistent to PE malformations.
Using this go package is easy. First, use go get
to install the latest version of the library. This command will install the pedumper
executable along with the library and its dependencies:
go get -u github.com/saferwall/pe
Next, include pe
package in your application:
import "github.com/saferwall/pe"
package main
import (
peparser "github.com/saferwall/pe"
)
func main() {
filename := "C:\\Binaries\\notepad.exe"
pe, err := peparser.New(filename, &peparser.Options{})
if err != nil {
log.Fatalf("Error while opening file: %s, reason: %v", filename, err)
}
err = pe.Parse()
if err != nil {
log.Fatalf("Error while parsing file: %s, reason: %v", filename, err)
}
}
Start by instantiating a pe object by called the New()
method, which takes the file path to the file to be parsed and some optional options.
Afterwards, a call to the Parse()
method will give you access to all the different part of the PE format, directly accessible to be used. Here is the definition of the struct:
type File struct {
DOSHeader ImageDOSHeader
RichHeader RichHeader
NtHeader ImageNtHeader
COFF COFF
Sections []Section
Imports []Import
Export Export
Debugs []DebugEntry
Relocations []Relocation
Resources ResourceDirectory
TLS TLSDirectory
LoadConfig LoadConfig
Exceptions []Exception
Certificates Certificate
DelayImports []DelayImport
BoundImports []BoundImportDescriptorData
GlobalPtr uint32
CLR CLRData
IAT []IATEntry
Header []byte
data mmap.MMap
closer io.Closer
Is64 bool
Is32 bool
Anomalies []string
size uint32
f *os.File
opts *Options
}
As mentionned before, all members of the struct are directly (no getters) accessible, additionally, the fields types has been preserved as the spec defines them, that means if you need to show the prettified version of an int
type, you have to call the corresponding helper function.
fmt.Printf("Magic is: 0x%x\n", pe.DosHeader.Magic)
fmt.Printf("Signature is: 0x%x\n", pe.NtHeader.Signature)
fmt.Printf("Machine is: 0x%x, Meaning: %s\n", pe.NtHeader.FileHeader.Machine, pe.PrettyMachineType())
Output:
Magic is: 0x5a4d
Signature is: 0x4550
Machine is: 0x8664, Meaning: x64
Example:
richHeader, _ := json.Marshal(pe.RichHeader)
fmt.Print(prettyPrint(richHeader))
Output:
{
"XorKey": 2796214951,
"CompIDs": [
{
"MinorCV": 27412,
"ProdID": 257,
"Count": 4,
"Unmasked": 16870164
},
{
"MinorCV": 30729,
"ProdID": 147,
"Count": 193,
"Unmasked": 9664521
},
{
"MinorCV": 0,
"ProdID": 1,
"Count": 1325,
"Unmasked": 65536
},
{
"MinorCV": 27412,
"ProdID": 260,
"Count": 9,
"Unmasked": 17066772
},
{
"MinorCV": 27412,
"ProdID": 259,
"Count": 3,
"Unmasked": 17001236
},
{
"MinorCV": 27412,
"ProdID": 256,
"Count": 1,
"Unmasked": 16804628
},
{
"MinorCV": 27412,
"ProdID": 269,
"Count": 209,
"Unmasked": 17656596
},
{
"MinorCV": 27412,
"ProdID": 255,
"Count": 1,
"Unmasked": 16739092
},
{
"MinorCV": 27412,
"ProdID": 258,
"Count": 1,
"Unmasked": 16935700
}
],
"DansOffset": 128,
"Raw": "47vE9afaqqan2qqmp9qqprOxq6ej2qqmrqI5pmbaqqan2qumit+qprOxrqeu2qqms7Gpp6TaqqazsaqnptqqprOxp6d22qqms7FVpqbaqqazsainptqqplJpY2in2qqm"
}
for _, sec := range pe.Sections {
fmt.Printf("Section Name : %s\n", sec.NameString())
fmt.Printf("Section VirtualSize : %x\n", sec.Header.VirtualSize)
fmt.Printf("Section Flags : %x, Meaning: %v\n\n",
sec.Header.Characteristics, sec.PrettySectionFlags())
}
Output:
Section Name : .text
Section VirtualSize : 2ea58
Section Flags : 60500060, Meaning: [Align8Bytes Readable Align16Bytes Executable Contains Code Initialized Data Align1Bytes]
Section Name : .data
Section VirtualSize : 58
Section Flags : c0500040, Meaning: [Readable Initialized Data Writable Align1Bytes Align16Bytes Align8Bytes]
Section Name : .rdata
Section VirtualSize : 18d0
Section Flags : 40600040, Meaning: [Align2Bytes Align8Bytes Readable Initialized Data Align32Bytes]
...
To validate the parser we use the go-fuzz and a corpus of known malformed and tricky PE files from corkami.
Fibratus A modern tool for Windows kernel exploration and tracing with a focus on security.