Merge pull request #19 from Binject/peload

Peload
This commit is contained in:
awgh
2021-01-01 13:07:38 -08:00
committed by GitHub
6 changed files with 261 additions and 165 deletions
+4
View File
@@ -11,6 +11,10 @@ import (
const CERTIFICATE_TABLE = 4
func readCertTable(f *File, r io.ReadSeeker) ([]byte, error) {
if f.OptionalHeader == nil { // Optional header is optional, might not exist
return nil, nil
}
var certTableOffset, certTableSize uint32
switch f.FileHeader.Machine {
+18 -71
View File
@@ -29,15 +29,17 @@ type File struct {
DosStub [64]byte // TODO(capnspacehook) make slice and correctly parse any DOS stub
RichHeader []byte
FileHeader
OptionalHeader interface{} // of type *OptionalHeader32 or *OptionalHeader64
Sections []*Section
Symbols []*Symbol // COFF symbols with auxiliary symbol records removed
COFFSymbols []COFFSymbol // all COFF symbols (including auxiliary symbol records)
StringTable StringTable
CertificateTable []byte
OptionalHeader interface{} // of type *OptionalHeader32 or *OptionalHeader64
Sections []*Section
BaseRelocationTable *[]RelocationTableEntry
Symbols []*Symbol // COFF symbols with auxiliary symbol records removed
COFFSymbols []COFFSymbol // all COFF symbols (including auxiliary symbol records)
StringTable StringTable
CertificateTable []byte
InsertionAddr uint32
InsertionBytes []byte
OptionalHeaderOffset int64 // offset of the start of the Optional Header
InsertionAddr uint32
InsertionBytes []byte
Net Net //If a managed executable, Net provides an interface to some of the metadata
@@ -183,7 +185,8 @@ func newFileInternal(r io.ReaderAt, memoryMode bool) (*File, error) {
}
// Read optional header.
sr.Seek(peHeaderOffset+int64(binary.Size(f.FileHeader)), seekStart)
f.OptionalHeaderOffset = peHeaderOffset + int64(binary.Size(f.FileHeader))
sr.Seek(f.OptionalHeaderOffset, seekStart)
var oh32 OptionalHeader32
var oh64 OptionalHeader64
@@ -251,6 +254,12 @@ func newFileInternal(r io.ReaderAt, memoryMode bool) (*File, error) {
}
}
// Read Base Relocation Block and Items
f.BaseRelocationTable, err = f.readBaseRelocationTable()
if err != nil {
return nil, err
}
// Read certificate table
f.CertificateTable, err = readCertTable(f, sr)
if err != nil {
@@ -456,65 +465,3 @@ func (f *File) IsManaged() bool {
return false
}
// RelocationBlock - for base relocation entries
type RelocationBlock struct {
VirtualAddress uint32
SizeOfBlock uint32
}
// BlockItem - relocation block item
type BlockItem struct {
Val uint16
Type uint16
Offset uint16
}
// Relocate - performs base relocations on this image to the given offset
func (f *File) Relocate(offset uint32) {
pe64 := f.Machine == IMAGE_FILE_MACHINE_AMD64
var addr uint32
var imageBase uint64
if pe64 {
addr = f.OptionalHeader.(*OptionalHeader64).DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress
imageBase = f.OptionalHeader.(*OptionalHeader64).ImageBase
} else {
addr = f.OptionalHeader.(*OptionalHeader32).DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress
imageBase = uint64(f.OptionalHeader.(*OptionalHeader32).ImageBase)
}
firstSectionRawDataPtr := uint32(0)
for i, val := range f.Sections {
if i == 0 {
firstSectionRawDataPtr = val.Offset
}
if val.VirtualAddress == addr { // name should be .reloc?
cur := val.Offset
d, _ := val.Data()
for cur-val.Offset < val.VirtualSize {
var reloBlock RelocationBlock
binary.Read(bytes.NewBuffer(d[cur:cur+8]), binary.LittleEndian, &reloBlock)
cur += 8
for i := uint32(0); i < reloBlock.SizeOfBlock-8; i += 2 {
var bi BlockItem
bi.Val = binary.LittleEndian.Uint16(d[cur : cur+2])
bi.Type = uint16(bi.Val >> 12)
bi.Offset = bi.Val & 0x0fff
localOffset := firstSectionRawDataPtr + uint32(bi.Offset)
relAddr := binary.LittleEndian.Uint32(d[localOffset : localOffset+4])
relAddr += offset - uint32(imageBase)
byts := make([]byte, 4)
binary.LittleEndian.PutUint32(byts, relAddr)
copy(d[localOffset:localOffset+4], byts)
cur += 2
}
}
break
}
}
if pe64 {
f.OptionalHeader.(*OptionalHeader64).ImageBase = uint64(offset)
} else {
f.OptionalHeader.(*OptionalHeader32).ImageBase = uint32(offset)
}
}
+62 -64
View File
@@ -6,7 +6,6 @@ package pe
import (
"debug/dwarf"
"internal/testenv"
"io/ioutil"
"os"
"os/exec"
@@ -28,23 +27,25 @@ type fileTest struct {
hasNoDwarfInfo bool
}
var zero8 [8]uint8
var fileTests = []fileTest{
{
file: "testdata/gcc-386-mingw-obj",
hdr: FileHeader{0x014c, 0x000c, 0x0, 0x64a, 0x1e, 0x0, 0x104},
sections: []*SectionHeader{
{".text", 0, 0, 36, 500, 1440, 0, 3, 0, 0x60300020},
{".data", 0, 0, 0, 0, 0, 0, 0, 0, 3224371264},
{".bss", 0, 0, 0, 0, 0, 0, 0, 0, 3224371328},
{".debug_abbrev", 0, 0, 137, 536, 0, 0, 0, 0, 0x42100000},
{".debug_info", 0, 0, 418, 673, 1470, 0, 7, 0, 1108344832},
{".debug_line", 0, 0, 128, 1091, 1540, 0, 1, 0, 1108344832},
{".rdata", 0, 0, 16, 1219, 0, 0, 0, 0, 1076887616},
{".debug_frame", 0, 0, 52, 1235, 1550, 0, 2, 0, 1110441984},
{".debug_loc", 0, 0, 56, 1287, 0, 0, 0, 0, 1108344832},
{".debug_pubnames", 0, 0, 27, 1343, 1570, 0, 1, 0, 1108344832},
{".debug_pubtypes", 0, 0, 38, 1370, 1580, 0, 1, 0, 1108344832},
{".debug_aranges", 0, 0, 32, 1408, 1590, 0, 2, 0, 1108344832},
{".text", [8]uint8{0x2e, 0x74, 0x65, 0x78, 0x74, 0x0, 0x0, 0x0}, 0, 0, 36, 500, 1440, 0, 3, 0, 0x60300020},
{".data", [8]uint8{0x2e, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0, 0x0}, 0, 0, 0, 0, 0, 0, 0, 0, 3224371264},
{".bss", [8]uint8{0x2e, 0x62, 0x73, 0x73, 0x0, 0x0, 0x0, 0x0}, 0, 0, 0, 0, 0, 0, 0, 0, 3224371328},
{".debug_abbrev", [8]uint8{0x2f, 0x34, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 0, 0, 137, 536, 0, 0, 0, 0, 0x42100000},
{".debug_info", [8]uint8{0x2f, 0x31, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0}, 0, 0, 418, 673, 1470, 0, 7, 0, 1108344832},
{".debug_line", [8]uint8{0x2f, 0x33, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0}, 0, 0, 128, 1091, 1540, 0, 1, 0, 1108344832},
{".rdata", [8]uint8{0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0, 0, 16, 1219, 0, 0, 0, 0, 1076887616},
{".debug_frame", [8]uint8{0x2f, 0x34, 0x32, 0x0, 0x0, 0x0, 0x0, 0x0}, 0, 0, 52, 1235, 1550, 0, 2, 0, 1110441984},
{".debug_loc", [8]uint8{0x2f, 0x35, 0x35, 0x0, 0x0, 0x0, 0x0, 0x0}, 0, 0, 56, 1287, 0, 0, 0, 0, 1108344832},
{".debug_pubnames", [8]uint8{0x2f, 0x36, 0x36, 0x0, 0x0, 0x0, 0x0, 0x0}, 0, 0, 27, 1343, 1570, 0, 1, 0, 1108344832},
{".debug_pubtypes", [8]uint8{0x2f, 0x38, 0x32, 0x0, 0x0, 0x0, 0x0, 0x0}, 0, 0, 38, 1370, 1580, 0, 1, 0, 1108344832},
{".debug_aranges", [8]uint8{0x2f, 0x39, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0}, 0, 0, 32, 1408, 1590, 0, 2, 0, 1108344832},
},
symbols: []*Symbol{
{".file", 0x0, -2, 0x0, 0x67},
@@ -90,21 +91,21 @@ var fileTests = []fileTest{
},
},
sections: []*SectionHeader{
{".text", 0xcd8, 0x1000, 0xe00, 0x400, 0x0, 0x0, 0x0, 0x0, 0x60500060},
{".data", 0x10, 0x2000, 0x200, 0x1200, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
{".rdata", 0x120, 0x3000, 0x200, 0x1400, 0x0, 0x0, 0x0, 0x0, 0x40300040},
{".bss", 0xdc, 0x4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0400080},
{".idata", 0x3c8, 0x5000, 0x400, 0x1600, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
{".CRT", 0x18, 0x6000, 0x200, 0x1a00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
{".tls", 0x20, 0x7000, 0x200, 0x1c00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
{".debug_aranges", 0x20, 0x8000, 0x200, 0x1e00, 0x0, 0x0, 0x0, 0x0, 0x42100000},
{".debug_pubnames", 0x51, 0x9000, 0x200, 0x2000, 0x0, 0x0, 0x0, 0x0, 0x42100000},
{".debug_pubtypes", 0x91, 0xa000, 0x200, 0x2200, 0x0, 0x0, 0x0, 0x0, 0x42100000},
{".debug_info", 0xe22, 0xb000, 0x1000, 0x2400, 0x0, 0x0, 0x0, 0x0, 0x42100000},
{".debug_abbrev", 0x157, 0xc000, 0x200, 0x3400, 0x0, 0x0, 0x0, 0x0, 0x42100000},
{".debug_line", 0x144, 0xd000, 0x200, 0x3600, 0x0, 0x0, 0x0, 0x0, 0x42100000},
{".debug_frame", 0x34, 0xe000, 0x200, 0x3800, 0x0, 0x0, 0x0, 0x0, 0x42300000},
{".debug_loc", 0x38, 0xf000, 0x200, 0x3a00, 0x0, 0x0, 0x0, 0x0, 0x42100000},
{".text", [8]uint8{0x2e, 0x74, 0x65, 0x78, 0x74, 0x0, 0x0, 0x0}, 0xcd8, 0x1000, 0xe00, 0x400, 0x0, 0x0, 0x0, 0x0, 0x60500060},
{".data", [8]uint8{0x2e, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0, 0x0}, 0x10, 0x2000, 0x200, 0x1200, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
{".rdata", [8]uint8{0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x120, 0x3000, 0x200, 0x1400, 0x0, 0x0, 0x0, 0x0, 0x40300040},
{".bss", [8]uint8{0x2e, 0x62, 0x73, 0x73, 0x0, 0x0, 0x0, 0x0}, 0xdc, 0x4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0400080},
{".idata", [8]uint8{0x2e, 0x69, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x3c8, 0x5000, 0x400, 0x1600, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
{".CRT", [8]uint8{0x2e, 0x43, 0x52, 0x54, 0x0, 0x0, 0x0, 0x0}, 0x18, 0x6000, 0x200, 0x1a00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
{".tls", [8]uint8{0x2e, 0x74, 0x6c, 0x73, 0x0, 0x0, 0x0, 0x0}, 0x20, 0x7000, 0x200, 0x1c00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
{".debug_aranges", [8]uint8{0x2f, 0x34, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x20, 0x8000, 0x200, 0x1e00, 0x0, 0x0, 0x0, 0x0, 0x42100000},
{".debug_pubnames", [8]uint8{0x2f, 0x31, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x51, 0x9000, 0x200, 0x2000, 0x0, 0x0, 0x0, 0x0, 0x42100000},
{".debug_pubtypes", [8]uint8{0x2f, 0x33, 0x35, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x91, 0xa000, 0x200, 0x2200, 0x0, 0x0, 0x0, 0x0, 0x42100000},
{".debug_info", [8]uint8{0x2f, 0x35, 0x31, 0x0, 0x0, 0x0, 0x0, 0x0}, 0xe22, 0xb000, 0x1000, 0x2400, 0x0, 0x0, 0x0, 0x0, 0x42100000},
{".debug_abbrev", [8]uint8{0x2f, 0x36, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x157, 0xc000, 0x200, 0x3400, 0x0, 0x0, 0x0, 0x0, 0x42100000},
{".debug_line", [8]uint8{0x2f, 0x37, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x144, 0xd000, 0x200, 0x3600, 0x0, 0x0, 0x0, 0x0, 0x42100000},
{".debug_frame", [8]uint8{0x2f, 0x38, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x34, 0xe000, 0x200, 0x3800, 0x0, 0x0, 0x0, 0x0, 0x42300000},
{".debug_loc", [8]uint8{0x2f, 0x31, 0x30, 0x32, 0x0, 0x0, 0x0, 0x0}, 0x38, 0xf000, 0x200, 0x3a00, 0x0, 0x0, 0x0, 0x0, 0x42100000},
},
},
{
@@ -131,14 +132,14 @@ var fileTests = []fileTest{
},
},
sections: []*SectionHeader{
{".text", 0xc64, 0x1000, 0xe00, 0x400, 0x0, 0x0, 0x0, 0x0, 0x60500060},
{".data", 0x10, 0x2000, 0x200, 0x1200, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
{".rdata", 0x134, 0x3000, 0x200, 0x1400, 0x0, 0x0, 0x0, 0x0, 0x40300040},
{".eh_fram", 0x3a0, 0x4000, 0x400, 0x1600, 0x0, 0x0, 0x0, 0x0, 0x40300040},
{".bss", 0x60, 0x5000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0300080},
{".idata", 0x378, 0x6000, 0x400, 0x1a00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
{".CRT", 0x18, 0x7000, 0x200, 0x1e00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
{".tls", 0x20, 0x8000, 0x200, 0x2000, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
{".text", [8]uint8{0x2e, 0x74, 0x65, 0x78, 0x74, 0x0, 0x0, 0x0}, 0xc64, 0x1000, 0xe00, 0x400, 0x0, 0x0, 0x0, 0x0, 0x60500060},
{".data", [8]uint8{0x2e, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0, 0x0}, 0x10, 0x2000, 0x200, 0x1200, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
{".rdata", [8]uint8{0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x134, 0x3000, 0x200, 0x1400, 0x0, 0x0, 0x0, 0x0, 0x40300040},
{".eh_fram", [8]uint8{0x2e, 0x65, 0x68, 0x5f, 0x66, 0x72, 0x61, 0x6d}, 0x3a0, 0x4000, 0x400, 0x1600, 0x0, 0x0, 0x0, 0x0, 0x40300040},
{".bss", [8]uint8{0x2e, 0x62, 0x73, 0x73, 0x0, 0x0, 0x0, 0x0}, 0x60, 0x5000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0300080},
{".idata", [8]uint8{0x2e, 0x69, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x378, 0x6000, 0x400, 0x1a00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
{".CRT", [8]uint8{0x2e, 0x43, 0x52, 0x54, 0x0, 0x0, 0x0, 0x0}, 0x18, 0x7000, 0x200, 0x1e00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
{".tls", [8]uint8{0x2e, 0x74, 0x6c, 0x73, 0x0, 0x0, 0x0, 0x0}, 0x20, 0x8000, 0x200, 0x2000, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
},
hasNoDwarfInfo: true,
},
@@ -146,12 +147,12 @@ var fileTests = []fileTest{
file: "testdata/gcc-amd64-mingw-obj",
hdr: FileHeader{0x8664, 0x6, 0x0, 0x198, 0x12, 0x0, 0x4},
sections: []*SectionHeader{
{".text", 0x0, 0x0, 0x30, 0x104, 0x15c, 0x0, 0x3, 0x0, 0x60500020},
{".data", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500040},
{".bss", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500080},
{".rdata", 0x0, 0x0, 0x10, 0x134, 0x0, 0x0, 0x0, 0x0, 0x40500040},
{".xdata", 0x0, 0x0, 0xc, 0x144, 0x0, 0x0, 0x0, 0x0, 0x40300040},
{".pdata", 0x0, 0x0, 0xc, 0x150, 0x17a, 0x0, 0x3, 0x0, 0x40300040},
{".text", [8]uint8{0x2e, 0x74, 0x65, 0x78, 0x74, 0x0, 0x0, 0x0}, 0x0, 0x0, 0x30, 0x104, 0x15c, 0x0, 0x3, 0x0, 0x60500020},
{".data", [8]uint8{0x2e, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0, 0x0}, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500040},
{".bss", [8]uint8{0x2e, 0x62, 0x73, 0x73, 0x0, 0x0, 0x0, 0x0}, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500080},
{".rdata", [8]uint8{0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x0, 0x0, 0x10, 0x134, 0x0, 0x0, 0x0, 0x0, 0x40500040},
{".xdata", [8]uint8{0x2e, 0x78, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x0, 0x0, 0xc, 0x144, 0x0, 0x0, 0x0, 0x0, 0x40300040},
{".pdata", [8]uint8{0x2e, 0x70, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x0, 0x0, 0xc, 0x150, 0x17a, 0x0, 0x3, 0x0, 0x40300040},
},
symbols: []*Symbol{
{".file", 0x0, -2, 0x0, 0x67},
@@ -191,23 +192,23 @@ var fileTests = []fileTest{
{0x0, 0x0},
}},
sections: []*SectionHeader{
{".text", 0x6860, 0x1000, 0x6a00, 0x600, 0x0, 0x0, 0x0, 0x0, 0x60500020},
{".data", 0xe0, 0x8000, 0x200, 0x7000, 0x0, 0x0, 0x0, 0x0, 0xc0500040},
{".rdata", 0x6b0, 0x9000, 0x800, 0x7200, 0x0, 0x0, 0x0, 0x0, 0x40600040},
{".pdata", 0x498, 0xa000, 0x600, 0x7a00, 0x0, 0x0, 0x0, 0x0, 0x40300040},
{".xdata", 0x488, 0xb000, 0x600, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x40300040},
{".bss", 0x1410, 0xc000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0600080},
{".idata", 0x990, 0xe000, 0xa00, 0x8600, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
{".CRT", 0x68, 0xf000, 0x200, 0x9000, 0x0, 0x0, 0x0, 0x0, 0xc0400040},
{".tls", 0x48, 0x10000, 0x200, 0x9200, 0x0, 0x0, 0x0, 0x0, 0xc0600040},
{".debug_aranges", 0x600, 0x11000, 0x600, 0x9400, 0x0, 0x0, 0x0, 0x0, 0x42500040},
{".debug_info", 0x1316e, 0x12000, 0x13200, 0x9a00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
{".debug_abbrev", 0x2ccb, 0x26000, 0x2e00, 0x1cc00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
{".debug_line", 0x3c4d, 0x29000, 0x3e00, 0x1fa00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
{".debug_frame", 0x18b8, 0x2d000, 0x1a00, 0x23800, 0x0, 0x0, 0x0, 0x0, 0x42400040},
{".debug_str", 0x396, 0x2f000, 0x400, 0x25200, 0x0, 0x0, 0x0, 0x0, 0x42100040},
{".debug_loc", 0x13240, 0x30000, 0x13400, 0x25600, 0x0, 0x0, 0x0, 0x0, 0x42100040},
{".debug_ranges", 0xa70, 0x44000, 0xc00, 0x38a00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
{".text", [8]uint8{0x2e, 0x74, 0x65, 0x78, 0x74, 0x0, 0x0, 0x0}, 0x6860, 0x1000, 0x6a00, 0x600, 0x0, 0x0, 0x0, 0x0, 0x60500020},
{".data", [8]uint8{0x2e, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0, 0x0}, 0xe0, 0x8000, 0x200, 0x7000, 0x0, 0x0, 0x0, 0x0, 0xc0500040},
{".rdata", [8]uint8{0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x6b0, 0x9000, 0x800, 0x7200, 0x0, 0x0, 0x0, 0x0, 0x40600040},
{".pdata", [8]uint8{0x2e, 0x70, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x498, 0xa000, 0x600, 0x7a00, 0x0, 0x0, 0x0, 0x0, 0x40300040},
{".xdata", [8]uint8{0x2e, 0x78, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x488, 0xb000, 0x600, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x40300040},
{".bss", [8]uint8{0x2e, 0x62, 0x73, 0x73, 0x0, 0x0, 0x0, 0x0}, 0x1410, 0xc000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0600080},
{".idata", [8]uint8{0x2e, 0x69, 0x64, 0x61, 0x74, 0x61, 0x0, 0x0}, 0x990, 0xe000, 0xa00, 0x8600, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
{".CRT", [8]uint8{0x2e, 0x43, 0x52, 0x54, 0x0, 0x0, 0x0, 0x0}, 0x68, 0xf000, 0x200, 0x9000, 0x0, 0x0, 0x0, 0x0, 0xc0400040},
{".tls", [8]uint8{0x2e, 0x74, 0x6c, 0x73, 0x0, 0x0, 0x0, 0x0}, 0x48, 0x10000, 0x200, 0x9200, 0x0, 0x0, 0x0, 0x0, 0xc0600040},
{".debug_aranges", [8]uint8{0x2f, 0x34, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x600, 0x11000, 0x600, 0x9400, 0x0, 0x0, 0x0, 0x0, 0x42500040},
{".debug_info", [8]uint8{0x2f, 0x31, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x1316e, 0x12000, 0x13200, 0x9a00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
{".debug_abbrev", [8]uint8{0x2f, 0x33, 0x31, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x2ccb, 0x26000, 0x2e00, 0x1cc00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
{".debug_line", [8]uint8{0x2f, 0x34, 0x35, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x3c4d, 0x29000, 0x3e00, 0x1fa00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
{".debug_frame", [8]uint8{0x2f, 0x35, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x18b8, 0x2d000, 0x1a00, 0x23800, 0x0, 0x0, 0x0, 0x0, 0x42400040},
{".debug_str", [8]uint8{0x2f, 0x37, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x396, 0x2f000, 0x400, 0x25200, 0x0, 0x0, 0x0, 0x0, 0x42100040},
{".debug_loc", [8]uint8{0x2f, 0x38, 0x31, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x13240, 0x30000, 0x13400, 0x25600, 0x0, 0x0, 0x0, 0x0, 0x42100040},
{".debug_ranges", [8]uint8{0x2f, 0x39, 0x32, 0x0, 0x0, 0x0, 0x0, 0x0}, 0xa70, 0x44000, 0xc00, 0x38a00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
},
},
}
@@ -313,7 +314,6 @@ func testDWARF(t *testing.T, linktype int) {
if runtime.GOOS != "windows" {
t.Skip("skipping windows only test")
}
testenv.MustHaveGoRun(t)
tmpdir, err := ioutil.TempDir("", "TestDWARF")
if err != nil {
@@ -350,7 +350,7 @@ func testDWARF(t *testing.T, linktype int) {
t.Fatalf("invalid linktype parameter of %v", linktype)
}
args = append(args, src)
out, err := exec.Command(testenv.GoToolPath(t), args...).CombinedOutput()
out, err := exec.Command("go", args...).CombinedOutput()
if err != nil {
t.Fatalf("building test executable for linktype %d failed: %s %s", linktype, err, out)
}
@@ -424,7 +424,6 @@ func testDWARF(t *testing.T, linktype int) {
}
func TestBSSHasZeros(t *testing.T) {
testenv.MustHaveExec(t)
if runtime.GOOS != "windows" {
t.Skip("skipping windows only test")
@@ -553,7 +552,6 @@ func main() {
`
func TestBuildingWindowsGUI(t *testing.T) {
testenv.MustHaveGoBuild(t)
if runtime.GOOS != "windows" {
t.Skip("skipping windows only test")
@@ -570,7 +568,7 @@ func TestBuildingWindowsGUI(t *testing.T) {
t.Fatal(err)
}
exe := filepath.Join(tmpdir, "a.exe")
cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags", "-H=windowsgui", "-o", exe, src)
cmd := exec.Command("go", "build", "-ldflags", "-H=windowsgui", "-o", exe, src)
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("building test executable failed: %s %s", err, out)
+171
View File
@@ -0,0 +1,171 @@
package pe
import (
"bytes"
"encoding/binary"
"fmt"
"io"
)
// RelocationTable - for base relocation entries
type RelocationTableEntry struct {
RelocationBlock
BlockItems []BlockItem
}
// RelocationBlock - for base relocation entries
type RelocationBlock struct {
VirtualAddress uint32
SizeOfBlock uint32
}
// BlockItem - relocation block item
type BlockItem struct {
Type byte // 4 bits
Offset uint16 // 12 bits
}
// Reloc represents a PE COFF relocation.
// Each section contains its own relocation list.
type Reloc struct {
VirtualAddress uint32
SymbolTableIndex uint32
Type uint16
}
const (
//IMAGE_REL_BASED_ABSOLUTE - The base relocation is skipped. This type can be used to pad a block.
IMAGE_REL_BASED_ABSOLUTE = 0
//IMAGE_REL_BASED_HIGH = 1
//IMAGE_REL_BASED_LOW = 2
//IMAGE_REL_BASED_HIGHLOW - The base relocation applies all 32 bits of the difference to the 32-bit field at offset.
IMAGE_REL_BASED_HIGHLOW = 3
//IMAGE_REL_BASED_HIGHADJ = 4
//IMAGE_REL_BASED_MIPS_JMPADDR = 5
//IMAGE_REL_BASED_ARM_MOV32 = 5
//IMAGE_REL_BASED_RISCV_HIGH20 = 5
//IMAGE_REL_BASED_THUMB_MOV32 = 7
//IMAGE_REL_BASED_RISCV_LOW12I = 7
//IMAGE_REL_BASED_RISCV_LOW12S = 8
//IMAGE_REL_BASED_MIPS_JMPADDR16 = 9
IMAGE_REL_BASED_DIR64 = 10
)
// readBaseRelocationTable - reads the base relocation table from the file and stores it
func (f *File) readBaseRelocationTable() (*[]RelocationTableEntry, error) {
if f.OptionalHeader == nil { // Optional header is optional, might not exist
return nil, nil
}
var dd DataDirectory
if f.Machine == IMAGE_FILE_MACHINE_AMD64 {
dd = f.OptionalHeader.(*OptionalHeader64).DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]
} else {
dd = f.OptionalHeader.(*OptionalHeader32).DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]
}
var sectionData []byte
var err error
for _, section := range f.Sections {
if section.VirtualAddress == dd.VirtualAddress {
sectionData, err = section.Data()
if err != nil {
return nil, err
}
break
}
}
r := bytes.NewReader(sectionData)
var reloBlocks []RelocationTableEntry
bytesRead := uint32(0)
for bytesRead < dd.Size {
var reloBlock RelocationBlock
err = binary.Read(r, binary.LittleEndian, &reloBlock)
bytesRead += 8
if err != nil {
return nil, fmt.Errorf("fail to read relocation block: %v", err)
}
numBlocks := (reloBlock.SizeOfBlock - 8) / 2
blocks := make([]BlockItem, numBlocks)
for i := uint32(0); i < numBlocks; i++ {
var buf [2]byte
err = binary.Read(r, binary.LittleEndian, &buf)
bytesRead += 2
if err != nil {
return nil, fmt.Errorf("fail to read relocation block item %d: %v", i, err)
}
var item BlockItem
val := binary.LittleEndian.Uint16(buf[:2])
item.Type = byte(val >> 12)
item.Offset = val & 0x0fff
blocks[i] = item
}
reloBlocks = append(reloBlocks, RelocationTableEntry{reloBlock, blocks})
}
return &reloBlocks, nil
}
// Relocate - performs base relocations on this image to the given offset
func (f *File) Relocate(baseAddr uint64, image *[]byte) {
var imageBase uint64
pe64 := f.Machine == IMAGE_FILE_MACHINE_AMD64
if pe64 {
imageBase = f.OptionalHeader.(*OptionalHeader64).ImageBase
} else {
imageBase = uint64(f.OptionalHeader.(*OptionalHeader32).ImageBase)
}
for _, block := range *f.BaseRelocationTable {
pageRVA := block.VirtualAddress
for _, item := range block.BlockItems {
if item.Type == IMAGE_REL_BASED_HIGHLOW { // 32 bit
delta := uint32(baseAddr - imageBase)
fileOffset := f.RVAToFileOffset(pageRVA)
idx := fileOffset + uint32(item.Offset)
originalAddress := binary.LittleEndian.Uint32((*image)[idx : idx+4])
b := make([]byte, 4)
binary.LittleEndian.PutUint32(b, originalAddress+delta)
copy((*image)[idx:idx+4], b)
} else if item.Type == IMAGE_REL_BASED_DIR64 { // 64 bit
delta := baseAddr - imageBase
fileOffset := f.RVAToFileOffset(pageRVA)
idx := fileOffset + uint32(item.Offset)
originalAddress := binary.LittleEndian.Uint64((*image)[idx : idx+8])
b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, originalAddress+delta)
copy((*image)[idx:idx+8], b)
}
}
}
// update imageBase in the optional header
if pe64 {
b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, baseAddr)
idx := f.OptionalHeaderOffset + 24
copy((*image)[idx:idx+8], b)
} else {
b := make([]byte, 4)
binary.LittleEndian.PutUint32(b, uint32(baseAddr))
idx := f.OptionalHeaderOffset + 28
copy((*image)[idx:idx+4], b)
}
}
func readRelocs(sh *SectionHeader, r io.ReadSeeker) ([]Reloc, error) {
if sh.NumberOfRelocations <= 0 {
return nil, nil
}
_, err := r.Seek(int64(sh.PointerToRelocations), seekStart)
if err != nil {
return nil, fmt.Errorf("fail to seek to %q section relocations: %v", sh.Name, err)
}
relocs := make([]Reloc, sh.NumberOfRelocations)
err = binary.Read(r, binary.LittleEndian, relocs)
if err != nil {
return nil, fmt.Errorf("fail to read section relocations: %v", err)
}
return relocs, nil
}
-28
View File
@@ -5,8 +5,6 @@
package pe
import (
"encoding/binary"
"fmt"
"io"
"strconv"
)
@@ -39,32 +37,6 @@ func (sh *SectionHeader32) fullName(st StringTable) (string, error) {
return st.String(uint32(i))
}
// TODO(brainman): copy all IMAGE_REL_* consts from ldpe.go here
// Reloc represents a PE COFF relocation.
// Each section contains its own relocation list.
type Reloc struct {
VirtualAddress uint32
SymbolTableIndex uint32
Type uint16
}
func readRelocs(sh *SectionHeader, r io.ReadSeeker) ([]Reloc, error) {
if sh.NumberOfRelocations <= 0 {
return nil, nil
}
_, err := r.Seek(int64(sh.PointerToRelocations), seekStart)
if err != nil {
return nil, fmt.Errorf("fail to seek to %q section relocations: %v", sh.Name, err)
}
relocs := make([]Reloc, sh.NumberOfRelocations)
err = binary.Read(r, binary.LittleEndian, relocs)
if err != nil {
return nil, fmt.Errorf("fail to read section relocations: %v", err)
}
return relocs, nil
}
// SectionHeader is similar to SectionHeader32 with Name
// field replaced by Go string. OriginalName is the
// original name of the section on disk.
+6 -2
View File
@@ -49,7 +49,11 @@ func readStringTable(fh *FileHeader, r io.ReadSeeker) (StringTable, error) {
if err != nil {
return nil, fmt.Errorf("fail to read string table: %v", err)
}
return StringTable(buf), nil
// re-add the length to the first four bytes of the string table
lbuf := make([]byte, 4)
binary.LittleEndian.PutUint32(lbuf, l)
return StringTable(append(lbuf, buf...)), nil
}
// String extracts string from COFF string table st at offset start.
@@ -58,7 +62,7 @@ func (st StringTable) String(start uint32) (string, error) {
if start < 4 {
return "", fmt.Errorf("offset %d is before the start of string table", start)
}
start -= 4
//start -= 4 // we are now including the uint32 length in the StringTable buffer as a prefix, this might change
if int(start) > len(st) {
return "", fmt.Errorf("offset %d is beyond the end of string table", start)
}