Simplified executable file formats
This commit is contained in:
parent
1cb93b39a7
commit
999e60e294
29 changed files with 236 additions and 218 deletions
119
src/exe/pe/EXE.go
Normal file
119
src/exe/pe/EXE.go
Normal file
|
@ -0,0 +1,119 @@
|
|||
package pe
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
|
||||
"git.akyoto.dev/cli/q/src/config"
|
||||
"git.akyoto.dev/cli/q/src/exe"
|
||||
)
|
||||
|
||||
const NumSections = 2
|
||||
|
||||
// EXE is the portable executable format used on Windows.
|
||||
type EXE struct {
|
||||
DOSHeader
|
||||
NTHeader
|
||||
OptionalHeader64
|
||||
Sections [NumSections]SectionHeader
|
||||
}
|
||||
|
||||
// Write writes the EXE file to the given writer.
|
||||
func Write(writer io.Writer, code []byte, data []byte) {
|
||||
const (
|
||||
HeaderEnd = DOSHeaderSize + NTHeaderSize + OptionalHeader64Size + SectionHeaderSize*NumSections
|
||||
)
|
||||
|
||||
var (
|
||||
codePadding = exe.Padding(HeaderEnd, config.Align)
|
||||
codeEnd = config.CodeOffset + len(code)
|
||||
dataPadding = exe.Padding(codeEnd, config.Align)
|
||||
dataStart = codeEnd + dataPadding
|
||||
)
|
||||
|
||||
imageSize := dataStart + len(data)
|
||||
imageSize += exe.Padding(imageSize, config.Align)
|
||||
|
||||
pe := &EXE{
|
||||
DOSHeader: DOSHeader{
|
||||
Magic: [4]byte{'M', 'Z', 0, 0},
|
||||
NTHeaderOffset: DOSHeaderSize,
|
||||
},
|
||||
NTHeader: NTHeader{
|
||||
Signature: [4]byte{'P', 'E', 0, 0},
|
||||
Machine: IMAGE_FILE_MACHINE_AMD64,
|
||||
NumberOfSections: NumSections,
|
||||
SizeOfOptionalHeader: OptionalHeader64Size,
|
||||
Characteristics: IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LARGE_ADDRESS_AWARE,
|
||||
},
|
||||
OptionalHeader64: OptionalHeader64{
|
||||
Magic: 0x020B, // PE32+ executable
|
||||
MajorLinkerVersion: 0x0E,
|
||||
MinorLinkerVersion: 0x16,
|
||||
SizeOfCode: uint32(len(code)),
|
||||
AddressOfEntryPoint: config.CodeOffset,
|
||||
BaseOfCode: config.CodeOffset,
|
||||
ImageBase: config.BaseAddress,
|
||||
SectionAlignment: config.Align, // power of 2, must be greater than or equal to FileAlignment
|
||||
FileAlignment: config.Align, // power of 2
|
||||
MajorOperatingSystemVersion: 0x06,
|
||||
MajorSubsystemVersion: 0x06,
|
||||
SizeOfImage: uint32(imageSize),
|
||||
SizeOfHeaders: config.CodeOffset, // section bodies begin here
|
||||
Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI,
|
||||
DllCharacteristics: IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA | IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE | IMAGE_DLLCHARACTERISTICS_NX_COMPAT | IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE,
|
||||
SizeOfStackReserve: 0x100000,
|
||||
SizeOfStackCommit: 0x1000,
|
||||
SizeOfHeapReserve: 0x100000,
|
||||
SizeOfHeapCommit: 0x1000,
|
||||
NumberOfRvaAndSizes: 16,
|
||||
DataDirectory: [16]DataDirectory{
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
},
|
||||
},
|
||||
Sections: [NumSections]SectionHeader{
|
||||
{
|
||||
Name: [8]byte{'.', 't', 'e', 'x', 't'},
|
||||
VirtualSize: uint32(len(code)),
|
||||
VirtualAddress: config.CodeOffset,
|
||||
RawSize: uint32(len(code)), // must be a multiple of FileAlignment
|
||||
RawAddress: config.CodeOffset, // must be a multiple of FileAlignment
|
||||
Characteristics: IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ,
|
||||
},
|
||||
{
|
||||
Name: [8]byte{'.', 'r', 'd', 'a', 't', 'a'},
|
||||
VirtualSize: uint32(len(data)),
|
||||
VirtualAddress: uint32(dataStart),
|
||||
RawSize: uint32(len(data)), // must be a multiple of FileAlignment
|
||||
RawAddress: uint32(dataStart), // must be a multiple of FileAlignment
|
||||
Characteristics: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
binary.Write(writer, binary.LittleEndian, &pe.DOSHeader)
|
||||
binary.Write(writer, binary.LittleEndian, &pe.NTHeader)
|
||||
binary.Write(writer, binary.LittleEndian, &pe.OptionalHeader64)
|
||||
binary.Write(writer, binary.LittleEndian, &pe.Sections)
|
||||
|
||||
writer.Write(bytes.Repeat([]byte{0}, int(codePadding)))
|
||||
writer.Write(code)
|
||||
writer.Write(bytes.Repeat([]byte{0}, int(dataPadding)))
|
||||
writer.Write(data)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue