Skip to content

Instantly share code, notes, and snippets.

@josephspurrier
Created February 1, 2015 10:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save josephspurrier/120d6f1c87fde4d9769e to your computer and use it in GitHub Desktop.
Save josephspurrier/120d6f1c87fde4d9769e to your computer and use it in GitHub Desktop.
Golang - Output PE Info
// Copyright 2015 Joseph Spurrier
// Author: Joseph Spurrier (http://josephspurrier.com)
// License: http://www.apache.org/licenses/LICENSE-2.0.html
package main
import (
"debug/pe"
"flag"
"fmt"
"os"
"time"
)
var (
Version string
BuildDate string
)
func init() {
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Version: %s\n", Version)
fmt.Fprintf(os.Stderr, "Build Date: %s\n", BuildDate)
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
flag.PrintDefaults()
}
flag.Parse()
}
func printExtra(extra ...interface{}) {
if extra != nil {
for _, v := range extra {
fmt.Print(" | ", v)
}
}
fmt.Println()
}
func printHexAndDec(name string, value interface{}, extra ...interface{}) {
fmt.Printf(name+" %0#8x | %d", value, value)
printExtra(extra...)
}
func printHexAndString(name string, value interface{}, extra ...interface{}) {
fmt.Printf(name+" %0#8x | %v", value, value)
printExtra(extra...)
}
func printHexAndTime(name string, value interface{}, extra ...interface{}) {
fmt.Printf(name+" %0#8x | %s", value, time.Unix(int64(value.(uint32)), 0))
printExtra(extra...)
}
func getMachine(i uint16) string {
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms680313%28v=vs.85%29.aspx
switch i {
case 0x8664:
return "x64"
case 0x0200:
return "Intel Itanium"
case 0x014c:
return "x86"
default:
return "unknown: " + fmt.Sprintf("%0#8x", i)
}
}
type Bitmask uint16
// BitValue is a value and a description
type BitValue struct {
value Bitmask
description string
}
// Bitwise returns a string array of all set bits
func (value Bitmask) ListDescriptions(values []BitValue) []string {
list := make([]string, 0)
currentValue := value
for currentValue > 0 {
for _, bv := range values {
if currentValue&bv.value != 0 {
currentValue ^= bv.value
list = append(list, bv.description)
}
}
}
return list
}
// Bitwise returns a string array of all set bits
func (value Bitmask) ListValues(values []BitValue) []Bitmask {
list := make([]Bitmask, 0)
currentValue := value
for currentValue > 0 {
for _, bv := range values {
if currentValue&bv.value != 0 {
currentValue ^= bv.value
list = append(list, bv.value)
}
}
}
return list
}
// IsSet returns true if a bit is set
func (value Bitmask) IsSet(test Bitmask) bool {
if value&test != 0 {
return true
}
return false
}
func main() {
fmt.Println("Microsoft Windows Portable Executable")
fmt.Println("File: starttest.exe\n")
f, _ := pe.Open("starttest.exe")
defer f.Close()
charValues := []BitValue{
{0x8000, "IMAGE_FILE_BYTES_REVERSED_HI"},
{0x4000, "IMAGE_FILE_UP_SYSTEM_ONLY"},
{0x2000, "IMAGE_FILE_DLL"},
{0x800, "IMAGE_FILE_NET_RUN_FROM_SWAP"},
{0x400, "IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP"},
{0x200, "IMAGE_FILE_DEBUG_STRIPPED"},
{0x100, "IMAGE_FILE_32BIT_MACHINE"},
{0x80, "IMAGE_FILE_BYTES_REVERSED_LO"},
{0x20, "IMAGE_FILE_LARGE_ADDRESS_AWARE"},
{0x10, "IMAGE_FILE_AGGRESIVE_WS_TRIM"},
{0x8, "IMAGE_FILE_LOCAL_SYMS_STRIPPED"},
{0x4, "IMAGE_FILE_LINE_NUMS_STRIPPED"},
{0x2, "IMAGE_FILE_EXECUTABLE_IMAGE"},
{0x1, "IMAGE_FILE_RELOCS_STRIPPED"},
}
// Use this table for Characteristics
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms680313%28v=vs.85%29.aspx
printHexAndDec("Header Characteristics: ", f.FileHeader.Characteristics, Bitmask(f.FileHeader.Characteristics).ListDescriptions(charValues))
printHexAndDec("Header Machine: ", f.FileHeader.Machine, getMachine(f.FileHeader.Machine))
printHexAndDec("Header Number of Sections: ", f.FileHeader.NumberOfSections)
printHexAndDec("Header Number of Symbols: ", f.FileHeader.NumberOfSymbols)
printHexAndDec("Header Pointer to Symbol Table:", f.FileHeader.PointerToSymbolTable)
printHexAndDec("Header Size of Optional Header:", f.FileHeader.SizeOfOptionalHeader)
printHexAndTime("Header Timestamp: ", f.FileHeader.TimeDateStamp)
fmt.Println()
fmt.Println("Sections:\n")
for _, s := range f.Sections {
fmt.Printf("%s\n", s.Name)
fmt.Printf("%0#8x %s\n", s.VirtualSize, "Virtual Size")
fmt.Printf("%0#8x %s\n", s.VirtualAddress, "Virtual Address")
fmt.Printf("%0#8x %s\n", s.Size, "Size")
fmt.Printf("%0#8x %s\n", s.Offset, "Offset")
fmt.Printf("%0#8x %s\n", s.PointerToRelocations, "Pointer To Relocations")
fmt.Printf("%0#8x %s\n", s.PointerToLineNumbers, "Pointer to Line Numbers")
fmt.Printf("%0#8x %s\n", s.NumberOfRelocations, "Number of Relocations")
fmt.Printf("%0#8x %s\n", s.NumberOfLineNumbers, "Number of Line Numbers")
fmt.Printf("%0#8x %s\n", s.Characteristics, "Characteristics")
fmt.Println()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment