Switch remote deploy to vendored source builds
Move remote deployment to a vendored source bundle built on the target host via Docker so redeploys no longer require local cross-compilation or host Go installation. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
76
vendor/github.com/jchv/go-winloader/internal/pe/export.go
generated
vendored
Normal file
76
vendor/github.com/jchv/go-winloader/internal/pe/export.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
package pe
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
)
|
||||
|
||||
// ExportTable is a table of module exports.
|
||||
type ExportTable struct {
|
||||
symbols map[string]uint64
|
||||
ordinals map[uint16]uint64
|
||||
}
|
||||
|
||||
// Proc returns an exported function address by symbol, or 0 if it is not found.
|
||||
func (t *ExportTable) Proc(symbol string) (addr uint64) {
|
||||
return t.symbols[symbol]
|
||||
}
|
||||
|
||||
// Ordinal returns an exported function address by ordinal, or 0 if it is not found.
|
||||
func (t *ExportTable) Ordinal(ordinal uint16) (addr uint64) {
|
||||
return t.ordinals[ordinal]
|
||||
}
|
||||
|
||||
// LoadExports returns a symbol table.
|
||||
func LoadExports(m *Module, mem io.ReadWriteSeeker, base uint64) (*ExportTable, error) {
|
||||
table := &ExportTable{
|
||||
symbols: map[string]uint64{},
|
||||
ordinals: map[uint16]uint64{},
|
||||
}
|
||||
|
||||
dir := m.Header.OptionalHeader.DataDirectory[ImageDirectoryEntryExport]
|
||||
if dir.Size == 0 {
|
||||
return table, nil
|
||||
}
|
||||
|
||||
// Load export directory header
|
||||
header := ImageExportDirectory{}
|
||||
mem.Seek(int64(dir.VirtualAddress), io.SeekStart)
|
||||
binary.Read(mem, binary.LittleEndian, &header)
|
||||
|
||||
// Load addresses
|
||||
addresses := make([]uint32, header.NumberOfFunctions)
|
||||
mem.Seek(int64(header.AddressOfFunctions), io.SeekStart)
|
||||
for i := range addresses {
|
||||
b := [4]byte{}
|
||||
mem.Read(b[:])
|
||||
addresses[i] = binary.LittleEndian.Uint32(b[:])
|
||||
table.ordinals[uint16(i)] = base + uint64(addresses[i])
|
||||
}
|
||||
|
||||
// Load name ordinals
|
||||
nameords := make([]uint16, header.NumberOfNames)
|
||||
mem.Seek(int64(header.AddressOfNameOrdinals), io.SeekStart)
|
||||
for i := range nameords {
|
||||
b := [2]byte{}
|
||||
mem.Read(b[:])
|
||||
nameords[i] = binary.LittleEndian.Uint16(b[:])
|
||||
}
|
||||
|
||||
// Load name addresses
|
||||
nameaddrs := make([]uint32, header.NumberOfNames)
|
||||
mem.Seek(int64(header.AddressOfNames), io.SeekStart)
|
||||
for i := range nameaddrs {
|
||||
b := [4]byte{}
|
||||
mem.Read(b[:])
|
||||
nameaddrs[i] = binary.LittleEndian.Uint32(b[:])
|
||||
}
|
||||
|
||||
// Load names
|
||||
for i, nameaddr := range nameaddrs {
|
||||
mem.Seek(int64(nameaddr), io.SeekStart)
|
||||
table.symbols[readsz(mem)] = base + uint64(addresses[nameords[i]])
|
||||
}
|
||||
|
||||
return table, nil
|
||||
}
|
||||
522
vendor/github.com/jchv/go-winloader/internal/pe/format.go
generated
vendored
Normal file
522
vendor/github.com/jchv/go-winloader/internal/pe/format.go
generated
vendored
Normal file
@@ -0,0 +1,522 @@
|
||||
package pe
|
||||
|
||||
// CONSTANTS / MAGIC NUMBERS
|
||||
|
||||
// MZSignature is the signature of the MZ format. This is the value of the
|
||||
// Signature field in ImageDOSHeader.
|
||||
var MZSignature = [2]byte{'M', 'Z'}
|
||||
|
||||
// PESignature is the signature of the PE format. This is the value of the
|
||||
// Signature field in ImageNTHeaders32 and ImageNTHeaders64.
|
||||
var PESignature = [4]byte{'P', 'E', 0, 0}
|
||||
|
||||
// Enumeration of magic numbers
|
||||
const (
|
||||
// ImageNTOptionalHeader32Magic is the magic number for 32-bit optional
|
||||
// header (ImageOptionalHeader32)
|
||||
ImageNTOptionalHeader32Magic = 0x010b
|
||||
|
||||
// ImageNTOptionalHeader64Magic is the magic number for 64-bit optional
|
||||
// header (ImageOptionalHeader64)
|
||||
ImageNTOptionalHeader64Magic = 0x020b
|
||||
)
|
||||
|
||||
// Enumeration of structure lengths.
|
||||
const (
|
||||
// SizeOfImageDOSHeader is the on-disk size of the ImageDOSHeader
|
||||
// structure.
|
||||
SizeOfImageDOSHeader = 64
|
||||
|
||||
// SizeOfImageFileHeader is the on-disk size of the ImageFileHeader
|
||||
// structure.
|
||||
SizeOfImageFileHeader = 20
|
||||
|
||||
// SizeOfImageOptionalHeader32 is the on-disk size of the
|
||||
// ImageOptionalHeader32 structure.
|
||||
SizeOfImageOptionalHeader32 = 224
|
||||
|
||||
// SizeOfImageOptionalHeader64 is the on-disk size of the
|
||||
// ImageOptionalHeader64 structure.
|
||||
SizeOfImageOptionalHeader64 = 240
|
||||
|
||||
// SizeOfImageNTHeaders32 is the on-disk size of the ImageNTHeaders32
|
||||
// structure.
|
||||
SizeOfImageNTHeaders32 = 248
|
||||
|
||||
// SizeOfImageNTHeaders64 is the on-disk size of the ImageNTHeaders64
|
||||
// structure.
|
||||
SizeOfImageNTHeaders64 = 264
|
||||
|
||||
// SizeOfImageDataDirectory is the on-disk size of the ImageDataDirectory
|
||||
// structure.
|
||||
SizeOfImageDataDirectory = 8
|
||||
)
|
||||
|
||||
// Enumeration of useful field offsets.
|
||||
const (
|
||||
// OffsetOfOptionalHeaderFromNTHeader is the offset from the start of
|
||||
// the NT header to the optional header magic value. This is helpful for
|
||||
// determining if the PE file is PE32 or PE64.
|
||||
OffsetOfOptionalHeaderFromNTHeader = 0x18
|
||||
)
|
||||
|
||||
// Enumeration of fixed-size array lengths in PE
|
||||
const (
|
||||
// NumDirectoryEntries specifies the number of data directory entries.
|
||||
NumDirectoryEntries = 16
|
||||
|
||||
// SectionNameLength is the size of a section short name.
|
||||
SectionNameLength = 8
|
||||
)
|
||||
|
||||
// Enumeration of known Windows Loader limits. (Some of these may not be
|
||||
// imposed by the format itself and purely by Windows runtime.)
|
||||
const (
|
||||
// MaxNumSections specifies the maximum number of sections that are
|
||||
// allowed. This is imposed by Windows Loader.
|
||||
MaxNumSections = 96
|
||||
)
|
||||
|
||||
// ENUMERATION VALUES
|
||||
|
||||
// Enumeration of machine values for the file header.
|
||||
const (
|
||||
ImageFileMachineUnknown = 0x0000
|
||||
ImageFileMachineTargetHost = 0x0001
|
||||
ImageFileMachinei386 = 0x014c
|
||||
ImageFileMachineR3000BE = 0x0160
|
||||
ImageFileMachineR3000 = 0x0162
|
||||
ImageFileMachineR4000 = 0x0166
|
||||
ImageFileMachineR10000 = 0x0168
|
||||
ImageFileMachineWCEMIPSv2 = 0x0169
|
||||
ImageFileMachineAlpha = 0x0184
|
||||
ImageFileMachineSH3 = 0x01a2
|
||||
ImageFileMachineSH3DSP = 0x01a3
|
||||
ImageFileMachineSH3E = 0x01a4
|
||||
ImageFileMachineSH4 = 0x01a6
|
||||
ImageFileMachineSH5 = 0x01a8
|
||||
ImageFileMachineARM = 0x01c0
|
||||
ImageFileMachineTHUMB = 0x01c2
|
||||
ImageFileMachineARMNT = 0x01c4
|
||||
ImageFileMachineAM33 = 0x01d3
|
||||
ImageFileMachinePowerPC = 0x01F0
|
||||
ImageFileMachinePowerPCFP = 0x01f1
|
||||
ImageFileMachineIA64 = 0x0200
|
||||
ImageFileMachineMIPS16 = 0x0266
|
||||
ImageFileMachineAlpha64 = 0x0284
|
||||
ImageFileMachineMIPSFPU = 0x0366
|
||||
ImageFileMachineMIPSFPU16 = 0x0466
|
||||
ImageFileMachineAXP64 = ImageFileMachineAlpha64
|
||||
ImageFileMachineTricore = 0x0520
|
||||
ImageFileMachineCEF = 0x00CE
|
||||
ImageFileMachineEBC = 0x0EBC
|
||||
ImageFileMachineAMD64 = 0x8664
|
||||
ImageFileMachineM32R = 0x9041
|
||||
ImageFileMachineARM64 = 0xAA64
|
||||
ImageFileMachineCEE = 0x0C0E
|
||||
ImageFileMachineRISCV32 = 0x5032
|
||||
ImageFileMachineRISCV64 = 0x5064
|
||||
ImageFileMachineRISCV128 = 0x5128
|
||||
)
|
||||
|
||||
// Enumeration of charateristics values for the file header.
|
||||
const (
|
||||
ImageFileRelocsStripped = 0x0001
|
||||
ImageFileExecutableImage = 0x0002
|
||||
ImageFileLineNumsStripped = 0x0004
|
||||
ImageFileLocalSymsStripped = 0x0008
|
||||
ImageFileAggressiveWSTrim = 0x0010
|
||||
ImageFileLargeAddressAware = 0x0020
|
||||
ImageFileBytesReversedLo = 0x0080
|
||||
ImageFile32BitMachine = 0x0100
|
||||
ImageFileDebugStripped = 0x0200
|
||||
ImageFileRemovableRunFromSwap = 0x0400
|
||||
ImageFileNetRunFromSwap = 0x0800
|
||||
ImageFileSystem = 0x1000
|
||||
ImageFileDLL = 0x2000
|
||||
ImageFileUPSystemOnly = 0x4000
|
||||
ImageFileBytesReversedHi = 0x8000
|
||||
)
|
||||
|
||||
// Enumeration of image subsystem values.
|
||||
const (
|
||||
ImageSubsystemUnknown = 0
|
||||
ImageSubsystemNative = 1
|
||||
ImageSubsystemWindowsGUI = 2
|
||||
ImageSubsystemWindowsCUI = 3
|
||||
ImageSubsystemOS2CUI = 5
|
||||
ImageSubsystemPOSIXCUI = 7
|
||||
ImageSubsystemNativeWindows = 8
|
||||
ImageSubsystemWindowsCEGUI = 9
|
||||
ImageSubsystemEFIApplication = 10
|
||||
ImageSubsystemEFIBootServiceDriver = 11
|
||||
ImageSubsystemEFIRuntimeDriver = 12
|
||||
ImageSubsystemEFIROM = 13
|
||||
ImageSubsystemXBox = 14
|
||||
ImageSubsystemWindowsBootApplication = 16
|
||||
ImageSubsystemXBoxCodeCatalog = 17
|
||||
)
|
||||
|
||||
// Enumeration of DLL characteristics values.
|
||||
const (
|
||||
ImageDLLCharacteristicsHighEntropyVA = 0x0020
|
||||
ImageDLLCharacteristicsDynamicBase = 0x0040
|
||||
ImageDLLCharacteristicsForceIntegrity = 0x0080
|
||||
ImageDLLCharacteristicsNXCompat = 0x0100
|
||||
ImageDLLCharacteristicsNoIsolation = 0x0200
|
||||
ImageDLLCharacteristicsNoSEH = 0x0400
|
||||
ImageDLLCharacteristicsNoBind = 0x0800
|
||||
ImageDLLCharacteristicsAppContainer = 0x1000
|
||||
ImageDLLCharacteristicsWDMDriver = 0x2000
|
||||
ImageDLLCharacteristicsGuardCF = 0x4000
|
||||
ImageDLLCharacteristicsTerminalServerAware = 0x8000
|
||||
)
|
||||
|
||||
// Enumeration of image directory entry indexes. These represent indices into
|
||||
// the data directory array of the optional header.
|
||||
const (
|
||||
ImageDirectoryEntryExport = 0
|
||||
ImageDirectoryEntryImport = 1
|
||||
ImageDirectoryEntryResource = 2
|
||||
ImageDirectoryEntryException = 3
|
||||
ImageDirectoryEntrySecurity = 4
|
||||
ImageDirectoryEntryBaseReloc = 5
|
||||
ImageDirectoryEntryDebug = 6
|
||||
ImageDirectoryEntryCopyright = 7
|
||||
ImageDirectoryEntryArchitecture = 7
|
||||
ImageDirectoryEntryGlobalPtr = 8
|
||||
ImageDirectoryEntryTLS = 9
|
||||
ImageDirectoryEntryLoadConfig = 10
|
||||
ImageDirectoryEntryBoundImport = 11
|
||||
ImageDirectoryEntryIAT = 12
|
||||
ImageDirectoryEntryDelayImport = 13
|
||||
ImageDirectoryEntryCOMDescriptor = 14
|
||||
)
|
||||
|
||||
// Enumeration of image section characteristics.
|
||||
const (
|
||||
ImageSectionCharacteristicsNoPad = 0x00000008
|
||||
ImageSectionCharacteristicsContainsCode = 0x00000020
|
||||
ImageSectionCharacteristicsContainsInitializedData = 0x00000040
|
||||
ImageSectionCharacteristicsContainsUninitailizedData = 0x00000080
|
||||
ImageSectionCharacteristicsLinkOther = 0x00000100
|
||||
ImageSectionCharacteristicsLinkInfo = 0x00000200
|
||||
ImageSectionCharacteristicsLinkRemove = 0x00000800
|
||||
ImageSectionCharacteristicsLinkCOMDAT = 0x00001000
|
||||
ImageSectionCharacteristicsNoDeferSpecExc = 0x00004000
|
||||
ImageSectionCharacteristicsGPRel = 0x00008000
|
||||
ImageSectionCharacteristicsMemoryFarData = 0x00008000
|
||||
ImageSectionCharacteristicsMemoryPurgeable = 0x00020000
|
||||
ImageSectionCharacteristicsMemory16Bit = 0x00020000
|
||||
ImageSectionCharacteristicsMemoryLocked = 0x00040000
|
||||
ImageSectionCharacteristicsMemoryPreload = 0x00080000
|
||||
ImageSectionCharacteristicsAlign1Bytes = 0x00100000
|
||||
ImageSectionCharacteristicsAlign2Bytes = 0x00200000
|
||||
ImageSectionCharacteristicsAlign4Bytes = 0x00300000
|
||||
ImageSectionCharacteristicsAlign8Bytes = 0x00400000
|
||||
ImageSectionCharacteristicsAlign16Bytes = 0x00500000
|
||||
ImageSectionCharacteristicsAlign32Bytes = 0x00600000
|
||||
ImageSectionCharacteristicsAlign64Bytes = 0x00700000
|
||||
ImageSectionCharacteristicsAlign128Bytes = 0x00800000
|
||||
ImageSectionCharacteristicsAlign256Bytes = 0x00900000
|
||||
ImageSectionCharacteristicsAlign512Bytes = 0x00A00000
|
||||
ImageSectionCharacteristicsAlign1024Bytes = 0x00B00000
|
||||
ImageSectionCharacteristicsAlign2048Bytes = 0x00C00000
|
||||
ImageSectionCharacteristicsAlign4096Bytes = 0x00D00000
|
||||
ImageSectionCharacteristicsAlign8192Bytes = 0x00E00000
|
||||
ImageSectionCharacteristicsAlignMask = 0x00F00000
|
||||
ImageSectionCharacteristicsLinkNumRelocOverflow = 0x01000000
|
||||
ImageSectionCharacteristicsMemoryDiscardable = 0x02000000
|
||||
ImageSectionCharacteristicsMemoryNotCached = 0x04000000
|
||||
ImageSectionCharacteristicsMemoryNotPaged = 0x08000000
|
||||
ImageSectionCharacteristicsMemoryShared = 0x10000000
|
||||
ImageSectionCharacteristicsMemoryExecute = 0x20000000
|
||||
ImageSectionCharacteristicsMemoryRead = 0x40000000
|
||||
ImageSectionCharacteristicsMemoryWrite = 0x80000000
|
||||
)
|
||||
|
||||
// Enumeration of TLS characteristics.
|
||||
const (
|
||||
ImageSectionTLSCharacteristicsScaleIndex = 0x00000001
|
||||
)
|
||||
|
||||
// Enumeration of relocation types.
|
||||
const (
|
||||
ImageRelBasedAbsolute = 0
|
||||
ImageRelBasedHigh = 1
|
||||
ImageRelBasedLow = 2
|
||||
ImageRelBasedHighLow = 3
|
||||
ImageRelBasedHighAdj = 4
|
||||
ImageRelBasedMachineSpecific5 = 5
|
||||
ImageRelBasedReserved = 6
|
||||
ImageRelBasedMachineSpecific7 = 7
|
||||
ImageRelBasedMachineSpecific8 = 8
|
||||
ImageRelBasedMachineSpecific9 = 9
|
||||
ImageRelBasedDir64 = 10
|
||||
)
|
||||
|
||||
// ImageDOSHeader is the structure of the DOS MZ Executable format. All PE
|
||||
// files contain at least a valid stub DOS MZ executable at the top; the PE
|
||||
// format itself starts at the address specified by NewHeaderAddr.
|
||||
type ImageDOSHeader struct {
|
||||
Signature [2]byte
|
||||
LastPageBytes uint16
|
||||
CountPages uint16
|
||||
CountRelocs uint16
|
||||
HeaderLen uint16
|
||||
MinAlloc uint16
|
||||
MaxAlloc uint16
|
||||
InitialSS uint16
|
||||
InitialSP uint16
|
||||
Checksum uint16
|
||||
InitialIP uint16
|
||||
InitialCS uint16
|
||||
RelocAddr uint16
|
||||
OverlayNum uint16
|
||||
Reserved [4]uint16
|
||||
OEMID uint16
|
||||
OEMInfo uint16
|
||||
Reserved2 [10]uint16
|
||||
NewHeaderAddr uint32
|
||||
}
|
||||
|
||||
// ImageFileHeader contains some of the basic attributes about the PE/COFF
|
||||
// file, including the number of sections and the machine type.
|
||||
type ImageFileHeader struct {
|
||||
Machine uint16
|
||||
NumberOfSections uint16
|
||||
TimeDateStamp uint32
|
||||
PointerToSymbolTable uint32
|
||||
NumberOfSymbols uint32
|
||||
SizeOfOptionalHeader uint16
|
||||
Characteristics uint16
|
||||
}
|
||||
|
||||
// ImageOptionalHeader32 contains the optional header for 32-bit PE images. It
|
||||
// is only 'optional' in the sense that not all PE/COFF binaries have it,
|
||||
// however it is required for executables and DLLs.
|
||||
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 [NumDirectoryEntries]ImageDataDirectory
|
||||
}
|
||||
|
||||
// ImageOptionalHeader64 contains the optional header for 64-bit PE images.
|
||||
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 [NumDirectoryEntries]ImageDataDirectory
|
||||
}
|
||||
|
||||
// To64 converts the ImageOptionalHeader32 to an ImageOptionalHeader64.
|
||||
func (i ImageOptionalHeader32) To64() ImageOptionalHeader64 {
|
||||
return ImageOptionalHeader64{
|
||||
Magic: i.Magic,
|
||||
MajorLinkerVersion: i.MajorLinkerVersion,
|
||||
MinorLinkerVersion: i.MinorLinkerVersion,
|
||||
SizeOfCode: i.SizeOfCode,
|
||||
SizeOfInitializedData: i.SizeOfInitializedData,
|
||||
SizeOfUninitializedData: i.SizeOfUninitializedData,
|
||||
AddressOfEntryPoint: i.AddressOfEntryPoint,
|
||||
BaseOfCode: i.BaseOfCode,
|
||||
ImageBase: uint64(i.ImageBase),
|
||||
SectionAlignment: i.SectionAlignment,
|
||||
FileAlignment: i.FileAlignment,
|
||||
MajorOperatingSystemVersion: i.MajorOperatingSystemVersion,
|
||||
MinorOperatingSystemVersion: i.MinorOperatingSystemVersion,
|
||||
MajorImageVersion: i.MajorImageVersion,
|
||||
MinorImageVersion: i.MinorImageVersion,
|
||||
MajorSubsystemVersion: i.MajorSubsystemVersion,
|
||||
MinorSubsystemVersion: i.MinorSubsystemVersion,
|
||||
Win32VersionValue: i.Win32VersionValue,
|
||||
SizeOfImage: i.SizeOfImage,
|
||||
SizeOfHeaders: i.SizeOfHeaders,
|
||||
CheckSum: i.CheckSum,
|
||||
Subsystem: i.Subsystem,
|
||||
DllCharacteristics: i.DllCharacteristics,
|
||||
SizeOfStackReserve: uint64(i.SizeOfStackReserve),
|
||||
SizeOfStackCommit: uint64(i.SizeOfStackCommit),
|
||||
SizeOfHeapReserve: uint64(i.SizeOfHeapReserve),
|
||||
SizeOfHeapCommit: uint64(i.SizeOfHeapCommit),
|
||||
LoaderFlags: i.LoaderFlags,
|
||||
NumberOfRvaAndSizes: i.NumberOfRvaAndSizes,
|
||||
DataDirectory: i.DataDirectory,
|
||||
}
|
||||
}
|
||||
|
||||
// ImageNTHeaders32 contains the PE file headers for 32-bit PE images.
|
||||
type ImageNTHeaders32 struct {
|
||||
// Signature identifies the PE format; Always "PE\0\0".
|
||||
Signature [4]byte
|
||||
FileHeader ImageFileHeader
|
||||
OptionalHeader ImageOptionalHeader32
|
||||
}
|
||||
|
||||
// ImageNTHeaders64 contains the PE file headers for 64-bit PE images.
|
||||
type ImageNTHeaders64 struct {
|
||||
// Signature identifies the PE format; Always "PE\0\0".
|
||||
Signature [4]byte
|
||||
FileHeader ImageFileHeader
|
||||
OptionalHeader ImageOptionalHeader64
|
||||
}
|
||||
|
||||
// To64 converts the ImageNTHeaders32 to an ImageNTHeaders64.
|
||||
func (i ImageNTHeaders32) To64() ImageNTHeaders64 {
|
||||
return ImageNTHeaders64{
|
||||
Signature: i.Signature,
|
||||
FileHeader: i.FileHeader,
|
||||
OptionalHeader: i.OptionalHeader.To64(),
|
||||
}
|
||||
}
|
||||
|
||||
// ImageDataDirectory holds a record for the given data directory. Each data
|
||||
// directory contains information about another section, such as the import
|
||||
// table. The index of the directory entry determines which section it
|
||||
// pertains to.
|
||||
type ImageDataDirectory struct {
|
||||
VirtualAddress uint32
|
||||
Size uint32
|
||||
}
|
||||
|
||||
// ImageSectionHeader is the header for a section. Windows Loader uses these
|
||||
// entries to configure the memory mapping of the executable. A series of
|
||||
// these structures immediately follow the headers.
|
||||
type ImageSectionHeader struct {
|
||||
Name [SectionNameLength]byte
|
||||
PhysicalAddressOrVirtualSize uint32
|
||||
VirtualAddress uint32
|
||||
SizeOfRawData uint32
|
||||
PointerToRawData uint32
|
||||
PointerToRelocations uint32
|
||||
PointerToLinenumbers uint32
|
||||
NumberOfRelocations uint16
|
||||
NumberOfLinenumbers uint16
|
||||
Characteristics uint32
|
||||
}
|
||||
|
||||
// ImageBaseRelocation holds the header for a single page of base relocation
|
||||
// data. The .reloc section of the binary contains a series of blocks of
|
||||
// base relocation data, each starting with this header and followed by n
|
||||
// 16-bit values that each represent a single relocation. The 4 most
|
||||
// significant bits specify the type of relocation, while the 12 least
|
||||
// significant bits contain the lower bits of the address (which is combined
|
||||
// with the virtual address of the page.) The SizeOfBlock value specifies the
|
||||
// size of an entire block, in bytes, including its header.
|
||||
type ImageBaseRelocation struct {
|
||||
VirtualAddress uint32
|
||||
SizeOfBlock uint32
|
||||
}
|
||||
|
||||
// The ImageImportDescriptor contains information about an imported module.
|
||||
type ImageImportDescriptor struct {
|
||||
OriginalFirstThunk uint32
|
||||
TimeDateStamp uint32
|
||||
ForwarderChain uint32
|
||||
Name uint32
|
||||
FirstThunk uint32
|
||||
}
|
||||
|
||||
// The ImageExportDirectory contains information about the module's exports.
|
||||
type ImageExportDirectory struct {
|
||||
Characteristics uint32
|
||||
TimeDateStamp uint32
|
||||
MajorVersion uint16
|
||||
MinorVersion uint16
|
||||
Name uint32
|
||||
Base uint32
|
||||
NumberOfFunctions uint32
|
||||
NumberOfNames uint32
|
||||
AddressOfFunctions uint32
|
||||
AddressOfNames uint32
|
||||
AddressOfNameOrdinals uint32
|
||||
}
|
||||
|
||||
// ImageTLSDirectory32 contains information about the module's thread local
|
||||
// storage callbacks (in PE32)
|
||||
type ImageTLSDirectory32 struct {
|
||||
StartAddressOfRawData uint32
|
||||
EndAddressOfRawData uint32
|
||||
AddressOfIndex uint32
|
||||
AddressOfCallBacks uint32
|
||||
SizeOfZeroFill uint32
|
||||
Characteristics uint32
|
||||
}
|
||||
|
||||
// ImageTLSDirectory64 contains information about the module's thread local
|
||||
// storage callbacks (in PE64)
|
||||
type ImageTLSDirectory64 struct {
|
||||
StartAddressOfRawData uint64
|
||||
EndAddressOfRawData uint64
|
||||
AddressOfIndex uint64
|
||||
AddressOfCallBacks uint64
|
||||
SizeOfZeroFill uint32
|
||||
Characteristics uint32
|
||||
}
|
||||
|
||||
// To64 converts the ImageTLSDirectory32 to an ImageTLSDirectory64.
|
||||
func (i ImageTLSDirectory32) To64() ImageTLSDirectory64 {
|
||||
return ImageTLSDirectory64{
|
||||
StartAddressOfRawData: uint64(i.StartAddressOfRawData),
|
||||
EndAddressOfRawData: uint64(i.EndAddressOfRawData),
|
||||
AddressOfIndex: uint64(i.AddressOfIndex),
|
||||
AddressOfCallBacks: uint64(i.AddressOfCallBacks),
|
||||
SizeOfZeroFill: i.SizeOfZeroFill,
|
||||
Characteristics: i.Characteristics,
|
||||
}
|
||||
}
|
||||
106
vendor/github.com/jchv/go-winloader/internal/pe/import.go
generated
vendored
Normal file
106
vendor/github.com/jchv/go-winloader/internal/pe/import.go
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
package pe
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/jchv/go-winloader/internal/loader"
|
||||
)
|
||||
|
||||
// LinkModule links a PE module in-memory.
|
||||
func LinkModule(m *Module, mem io.ReadWriteSeeker, ldr loader.Loader) error {
|
||||
dir := m.Header.OptionalHeader.DataDirectory[ImageDirectoryEntryImport]
|
||||
if dir.Size == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Determine pointer size based on whether we're PE32 or PE64.
|
||||
psize := 4
|
||||
if m.IsPE64 {
|
||||
psize = 8
|
||||
}
|
||||
|
||||
// Load import descriptors
|
||||
descs := []ImageImportDescriptor{}
|
||||
mem.Seek(int64(dir.VirtualAddress), io.SeekStart)
|
||||
for {
|
||||
desc := ImageImportDescriptor{}
|
||||
binary.Read(mem, binary.LittleEndian, &desc)
|
||||
|
||||
if desc.Name == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
descs = append(descs, desc)
|
||||
}
|
||||
|
||||
// Load modules.
|
||||
for _, desc := range descs {
|
||||
thunk := int64(desc.OriginalFirstThunk)
|
||||
iat := int64(desc.FirstThunk)
|
||||
if thunk == 0 {
|
||||
thunk = iat
|
||||
}
|
||||
|
||||
// Read module name
|
||||
mem.Seek(int64(desc.Name), io.SeekStart)
|
||||
|
||||
// Load library
|
||||
libname := readsz(mem)
|
||||
lib, err := ldr.Load(libname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Read thunk addrs
|
||||
b := [8]byte{}
|
||||
thunks := []uint64{}
|
||||
mem.Seek(thunk, io.SeekStart)
|
||||
for {
|
||||
mem.Read(b[:psize])
|
||||
thunk := binary.LittleEndian.Uint64(b[:])
|
||||
if thunk == 0 {
|
||||
break
|
||||
}
|
||||
thunks = append(thunks, thunk)
|
||||
}
|
||||
|
||||
// Resolve thunks
|
||||
resolved := []uint64{}
|
||||
for _, thunk := range thunks {
|
||||
thunkord := int64(-1)
|
||||
if (m.IsPE64 && thunk&0x8000000000000000 != 0) || (!m.IsPE64 && thunk&0x80000000 != 0) {
|
||||
thunkord = int64(thunk & 0xFFFF)
|
||||
}
|
||||
if thunkord != -1 {
|
||||
// Import by ordinal
|
||||
if proc := lib.Ordinal(uint64(thunkord)); proc != nil {
|
||||
resolved = append(resolved, proc.Addr())
|
||||
} else {
|
||||
return fmt.Errorf("could not resolve ordinal %d in module %q", thunkord, libname)
|
||||
}
|
||||
} else {
|
||||
// Read name
|
||||
mem.Seek(int64(thunk+2), io.SeekStart)
|
||||
fnname := readsz(mem)
|
||||
|
||||
// Import by name
|
||||
if proc := lib.Proc(fnname); proc != nil {
|
||||
resolved = append(resolved, proc.Addr())
|
||||
} else {
|
||||
return fmt.Errorf("could not resolve symbol %q in module %q", fnname, libname)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write resolved IAT
|
||||
mem.Seek(iat, io.SeekStart)
|
||||
for _, fn := range resolved {
|
||||
binary.LittleEndian.PutUint64(b[:], uint64(fn))
|
||||
mem.Write(b[:psize])
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
91
vendor/github.com/jchv/go-winloader/internal/pe/module.go
generated
vendored
Normal file
91
vendor/github.com/jchv/go-winloader/internal/pe/module.go
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
package pe
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrBadMZSignature is returned when the MZ signature is invalid.
|
||||
ErrBadMZSignature = errors.New("mz: bad signature")
|
||||
|
||||
// ErrBadPESignature is returned when the PE signature is invalid.
|
||||
ErrBadPESignature = errors.New("pe: bad signature")
|
||||
|
||||
// ErrUnknownOptionalHeaderMagic is returned when the optional header
|
||||
// magic field has an unknown value.
|
||||
ErrUnknownOptionalHeaderMagic = errors.New("pe: unknown optional header magic")
|
||||
)
|
||||
|
||||
// Module contains a parsed and loaded PE file.
|
||||
type Module struct {
|
||||
IsPE64 bool
|
||||
DOSHeader ImageDOSHeader
|
||||
Header ImageNTHeaders64
|
||||
Sections []ImageSectionHeader
|
||||
}
|
||||
|
||||
// LoadModule loads a PE module into memory.
|
||||
func LoadModule(r io.ReadSeeker) (*Module, error) {
|
||||
m := &Module{}
|
||||
|
||||
r.Seek(0, io.SeekStart)
|
||||
dos := ImageDOSHeader{}
|
||||
if err := binary.Read(r, binary.LittleEndian, &dos); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if dos.Signature != MZSignature {
|
||||
return nil, ErrBadMZSignature
|
||||
}
|
||||
m.DOSHeader = dos
|
||||
|
||||
r.Seek(int64(dos.NewHeaderAddr), io.SeekStart)
|
||||
pesig := [4]byte{}
|
||||
if err := binary.Read(r, binary.LittleEndian, &pesig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if pesig != PESignature {
|
||||
return nil, ErrBadPESignature
|
||||
}
|
||||
|
||||
optmagic := uint16(0)
|
||||
r.Seek(int64(dos.NewHeaderAddr)+OffsetOfOptionalHeaderFromNTHeader, io.SeekStart)
|
||||
if err := binary.Read(r, binary.LittleEndian, &optmagic); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r.Seek(int64(dos.NewHeaderAddr), io.SeekStart)
|
||||
switch optmagic {
|
||||
case ImageNTOptionalHeader32Magic:
|
||||
m.IsPE64 = false
|
||||
nt := ImageNTHeaders32{}
|
||||
if err := binary.Read(r, binary.LittleEndian, &nt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m.Header = nt.To64()
|
||||
case ImageNTOptionalHeader64Magic:
|
||||
m.IsPE64 = true
|
||||
nt := ImageNTHeaders64{}
|
||||
if err := binary.Read(r, binary.LittleEndian, &nt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m.Header = nt
|
||||
default:
|
||||
return nil, ErrUnknownOptionalHeaderMagic
|
||||
}
|
||||
|
||||
// Seek past end of optional headers.
|
||||
r.Seek(int64(dos.NewHeaderAddr)+OffsetOfOptionalHeaderFromNTHeader+int64(m.Header.FileHeader.SizeOfOptionalHeader), io.SeekStart)
|
||||
|
||||
for i := uint16(0); i < m.Header.FileHeader.NumberOfSections; i++ {
|
||||
section := ImageSectionHeader{}
|
||||
if err := binary.Read(r, binary.LittleEndian, §ion); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m.Sections = append(m.Sections, section)
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
177
vendor/github.com/jchv/go-winloader/internal/pe/reloc.go
generated
vendored
Normal file
177
vendor/github.com/jchv/go-winloader/internal/pe/reloc.go
generated
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
package pe
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// BaseRelocation is a parsed PE base relocation.
|
||||
type BaseRelocation struct {
|
||||
// Relative virtual address of offset (that is, 0 == first byte of PE.)
|
||||
Offset uint64
|
||||
|
||||
// Type of base relocation using the ImageRelBased* constants.
|
||||
Type int
|
||||
}
|
||||
|
||||
// LoadBaseRelocs loads relocations from memory.
|
||||
func LoadBaseRelocs(m *Module, mem io.ReadSeeker) []BaseRelocation {
|
||||
relocs := []BaseRelocation{}
|
||||
dir := m.Header.OptionalHeader.DataDirectory[ImageDirectoryEntryBaseReloc]
|
||||
if dir.Size == 0 {
|
||||
return relocs
|
||||
}
|
||||
n := uint32(0)
|
||||
mem.Seek(int64(dir.VirtualAddress), io.SeekStart)
|
||||
for n < dir.Size {
|
||||
hdr := ImageBaseRelocation{}
|
||||
binary.Read(mem, binary.LittleEndian, &hdr)
|
||||
data := make([]uint16, hdr.SizeOfBlock/2-4)
|
||||
binary.Read(mem, binary.LittleEndian, &data)
|
||||
for _, i := range data {
|
||||
relocs = append(relocs, BaseRelocation{
|
||||
Offset: uint64(hdr.VirtualAddress) + uint64(i&0xFFF),
|
||||
Type: int(i >> 12),
|
||||
})
|
||||
}
|
||||
n += hdr.SizeOfBlock
|
||||
}
|
||||
return relocs
|
||||
}
|
||||
|
||||
// Relocate performs a series of relocations on m, where address is the load
|
||||
// address and original is the original address. The ReadWriteSeeker is
|
||||
// assumed to have the PE image at offset 0.
|
||||
func Relocate(machine int, rels []BaseRelocation, address uint64, original uint64, m io.ReadWriteSeeker, o binary.ByteOrder) error {
|
||||
b := [8]byte{}
|
||||
delta := address - original
|
||||
|
||||
if delta == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
read := func(off uint64, cb int) error {
|
||||
m.Seek(int64(off), io.SeekStart)
|
||||
err := readfully(m, b[0:cb])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.Seek(int64(-cb), io.SeekCurrent)
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, rel := range rels {
|
||||
switch rel.Type {
|
||||
case ImageRelBasedAbsolute:
|
||||
break
|
||||
|
||||
case ImageRelBasedHigh:
|
||||
if err := read(rel.Offset, 2); err != nil {
|
||||
return err
|
||||
}
|
||||
o.PutUint16(b[0:2], uint16(uint64(o.Uint16(b[:2]))+(delta>>16)))
|
||||
if _, err := m.Write(b[0:2]); err != nil {
|
||||
return err
|
||||
}
|
||||
break
|
||||
|
||||
case ImageRelBasedLow:
|
||||
if err := read(rel.Offset, 2); err != nil {
|
||||
return err
|
||||
}
|
||||
o.PutUint16(b[0:2], uint16(uint64(o.Uint16(b[:2]))+(delta>>0)))
|
||||
if _, err := m.Write(b[0:2]); err != nil {
|
||||
return err
|
||||
}
|
||||
break
|
||||
|
||||
case ImageRelBasedHighLow:
|
||||
if err := read(rel.Offset, 4); err != nil {
|
||||
return err
|
||||
}
|
||||
o.PutUint32(b[0:4], uint32(uint64(o.Uint32(b[:4]))+delta))
|
||||
if _, err := m.Write(b[0:4]); err != nil {
|
||||
return err
|
||||
}
|
||||
break
|
||||
|
||||
case ImageRelBasedDir64:
|
||||
if err := read(rel.Offset, 8); err != nil {
|
||||
return err
|
||||
}
|
||||
o.PutUint64(b[0:8], uint64(o.Uint64(b[:8]))+delta)
|
||||
if _, err := m.Write(b[0:8]); err != nil {
|
||||
return err
|
||||
}
|
||||
break
|
||||
|
||||
// Could use some help for ensuring we have proper support for
|
||||
// machine-specific relocations. If you are interested in this
|
||||
// use case for some reason, feel free to send PRs. -- john
|
||||
case ImageRelBasedMachineSpecific5:
|
||||
switch machine {
|
||||
// MIPS: JMP reloc
|
||||
case ImageFileMachineR3000, ImageFileMachineR3000BE,
|
||||
ImageFileMachineR4000, ImageFileMachineR10000,
|
||||
ImageFileMachineWCEMIPSv2, ImageFileMachineMIPS16,
|
||||
ImageFileMachineMIPSFPU, ImageFileMachineMIPSFPU16:
|
||||
return errors.New("MIPS JMP reloc not implemented")
|
||||
// ARM: MOV32 reloc
|
||||
case ImageFileMachineARM, ImageFileMachineTHUMB,
|
||||
ImageFileMachineARMNT:
|
||||
return errors.New("ARM MOV32 reloc not implemented")
|
||||
// RISC-V: HI20 reloc
|
||||
case ImageFileMachineRISCV32, ImageFileMachineRISCV64,
|
||||
ImageFileMachineRISCV128:
|
||||
return errors.New("RISC-V HI20 reloc not implemented")
|
||||
default:
|
||||
return fmt.Errorf("unknown machine-specific relocation type %d on machine type %04x", rel.Type, machine)
|
||||
}
|
||||
|
||||
case ImageRelBasedMachineSpecific7:
|
||||
switch machine {
|
||||
// THUMB: MOV32 reloc
|
||||
case ImageFileMachineARM, ImageFileMachineTHUMB,
|
||||
ImageFileMachineARMNT:
|
||||
return errors.New("THUMB MOV32 reloc not implemented")
|
||||
// RISC-V: LOW12I reloc
|
||||
case ImageFileMachineRISCV32, ImageFileMachineRISCV64,
|
||||
ImageFileMachineRISCV128:
|
||||
return errors.New("RISC-V LOW12I reloc not implemented")
|
||||
default:
|
||||
return fmt.Errorf("unknown machine-specific relocation type %d on machine type %04x", rel.Type, machine)
|
||||
}
|
||||
|
||||
case ImageRelBasedMachineSpecific8:
|
||||
switch machine {
|
||||
// RISC-V: LOW12S reloc
|
||||
case ImageFileMachineRISCV32, ImageFileMachineRISCV64,
|
||||
ImageFileMachineRISCV128:
|
||||
return errors.New("RISC-V LOW12S reloc not implemented")
|
||||
default:
|
||||
return fmt.Errorf("unknown machine-specific relocation type %d on machine type %04x", rel.Type, machine)
|
||||
}
|
||||
|
||||
case ImageRelBasedMachineSpecific9:
|
||||
switch machine {
|
||||
// MIPS: JMP16 reloc
|
||||
case ImageFileMachineR3000, ImageFileMachineR3000BE,
|
||||
ImageFileMachineR4000, ImageFileMachineR10000,
|
||||
ImageFileMachineWCEMIPSv2, ImageFileMachineMIPS16,
|
||||
ImageFileMachineMIPSFPU, ImageFileMachineMIPSFPU16:
|
||||
return errors.New("MIPS JMP16 reloc not implemented")
|
||||
// Itanium: Imm64 reloc
|
||||
case ImageFileMachineIA64:
|
||||
return errors.New("Itanium Imm64 reloc not implemented")
|
||||
default:
|
||||
return fmt.Errorf("unknown machine-specific relocation type %d on machine type %04x", rel.Type, machine)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unknown relocation type %d", rel.Type)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
40
vendor/github.com/jchv/go-winloader/internal/pe/util.go
generated
vendored
Normal file
40
vendor/github.com/jchv/go-winloader/internal/pe/util.go
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
package pe
|
||||
|
||||
import "io"
|
||||
|
||||
func readfully(r io.Reader, p []byte) error {
|
||||
n, err := r.Read(p)
|
||||
if n < 0 || n > len(p) {
|
||||
panic("invalid read length")
|
||||
}
|
||||
if err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
for n < len(p) {
|
||||
m, err := r.Read(p[n:])
|
||||
if m < 0 || m > len(p[n:]) {
|
||||
panic("invalid read length")
|
||||
}
|
||||
n += m
|
||||
if n < len(p) && err != nil {
|
||||
return err
|
||||
}
|
||||
if n >= len(p) && err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func readsz(r io.Reader) string {
|
||||
name := []byte{}
|
||||
for {
|
||||
b := [1]byte{}
|
||||
r.Read(b[:])
|
||||
if b[0] == 0 {
|
||||
break
|
||||
}
|
||||
name = append(name, b[0])
|
||||
}
|
||||
return string(name)
|
||||
}
|
||||
Reference in New Issue
Block a user