Added exe package to manage sections
This commit is contained in:
@ -7,7 +7,7 @@ import (
|
||||
|
||||
"git.urbach.dev/cli/q/src/config"
|
||||
"git.urbach.dev/cli/q/src/dll"
|
||||
"git.urbach.dev/cli/q/src/fs"
|
||||
"git.urbach.dev/cli/q/src/exe"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -24,31 +24,30 @@ type EXE struct {
|
||||
}
|
||||
|
||||
// Write writes the EXE file to the given writer.
|
||||
func Write(writer io.Writer, code []byte, data []byte, dlls dll.List) {
|
||||
func Write(writer io.Writer, codeBytes []byte, dataBytes []byte, dlls dll.List) {
|
||||
var (
|
||||
codeStart, codePadding = fs.Align(HeaderEnd, config.Align)
|
||||
dataStart, dataPadding = fs.Align(codeStart+len(code), config.Align)
|
||||
importsStart, importsPadding = fs.Align(dataStart+len(data), config.Align)
|
||||
subSystem = IMAGE_SUBSYSTEM_WINDOWS_CUI
|
||||
imports, dllData, dllImports, dllDataStart = importLibraries(dlls, importsStart)
|
||||
importDirectoryStart = dllDataStart + len(dllData)
|
||||
importDirectorySize = DLLImportSize * len(dllImports)
|
||||
importSectionSize = len(imports)*8 + len(dllData) + importDirectorySize
|
||||
imageSize, _ = fs.Align(importsStart+importSectionSize, config.Align)
|
||||
arch uint16
|
||||
sections = exe.MakeSections(HeaderEnd, codeBytes, dataBytes, nil)
|
||||
code = sections[0]
|
||||
data = sections[1]
|
||||
imports = sections[2]
|
||||
subSystem = IMAGE_SUBSYSTEM_WINDOWS_CUI
|
||||
arch = cpu()
|
||||
)
|
||||
|
||||
importsData, dllData, dllImports, dllDataStart := importLibraries(dlls, imports.FileOffset)
|
||||
buffer := bytes.Buffer{}
|
||||
binary.Write(&buffer, binary.LittleEndian, &importsData)
|
||||
binary.Write(&buffer, binary.LittleEndian, &dllData)
|
||||
binary.Write(&buffer, binary.LittleEndian, &dllImports)
|
||||
imports.Bytes = buffer.Bytes()
|
||||
importDirectoryStart := dllDataStart + len(dllData)
|
||||
importDirectorySize := DLLImportSize * len(dllImports)
|
||||
imageSize := exe.Align(imports.MemoryOffset+len(imports.Bytes), config.MemoryAlign)
|
||||
|
||||
if dlls.Contains("user32") {
|
||||
subSystem = IMAGE_SUBSYSTEM_WINDOWS_GUI
|
||||
}
|
||||
|
||||
switch config.TargetArch {
|
||||
case config.ARM:
|
||||
arch = IMAGE_FILE_MACHINE_ARM64
|
||||
case config.X86:
|
||||
arch = IMAGE_FILE_MACHINE_AMD64
|
||||
}
|
||||
|
||||
pe := &EXE{
|
||||
DOSHeader: DOSHeader{
|
||||
Magic: [4]byte{'M', 'Z', 0, 0},
|
||||
@ -68,14 +67,14 @@ func Write(writer io.Writer, code []byte, data []byte, dlls dll.List) {
|
||||
Magic: 0x020B, // PE32+ / 64-bit executable
|
||||
MajorLinkerVersion: 0x0E,
|
||||
MinorLinkerVersion: 0x16,
|
||||
SizeOfCode: uint32(len(code)),
|
||||
SizeOfCode: uint32(len(code.Bytes)),
|
||||
SizeOfInitializedData: 0,
|
||||
SizeOfUninitializedData: 0,
|
||||
AddressOfEntryPoint: uint32(codeStart),
|
||||
BaseOfCode: uint32(codeStart),
|
||||
AddressOfEntryPoint: uint32(code.MemoryOffset),
|
||||
BaseOfCode: uint32(code.MemoryOffset),
|
||||
ImageBase: config.BaseAddress,
|
||||
SectionAlignment: config.Align, // power of 2, must be greater than or equal to FileAlignment
|
||||
FileAlignment: config.Align, // power of 2
|
||||
SectionAlignment: config.MemoryAlign, // power of 2, must be greater than or equal to FileAlignment
|
||||
FileAlignment: config.FileAlign, // power of 2
|
||||
MajorOperatingSystemVersion: 0x06,
|
||||
MinorOperatingSystemVersion: 0,
|
||||
MajorImageVersion: 0,
|
||||
@ -83,8 +82,8 @@ func Write(writer io.Writer, code []byte, data []byte, dlls dll.List) {
|
||||
MajorSubsystemVersion: 0x06,
|
||||
MinorSubsystemVersion: 0,
|
||||
Win32VersionValue: 0,
|
||||
SizeOfImage: uint32(imageSize),
|
||||
SizeOfHeaders: uint32(codeStart), // section bodies begin here
|
||||
SizeOfImage: uint32(imageSize), // a multiple of SectionAlignment
|
||||
SizeOfHeaders: uint32(code.FileOffset), // section bodies begin here
|
||||
CheckSum: 0,
|
||||
Subsystem: uint16(subSystem),
|
||||
DllCharacteristics: IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA | IMAGE_DLLCHARACTERISTICS_NX_COMPAT | IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE, // IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
|
||||
@ -107,7 +106,7 @@ func Write(writer io.Writer, code []byte, data []byte, dlls dll.List) {
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: uint32(importsStart), Size: uint32(len(imports) * 8)}, // RVA of the import address table
|
||||
{VirtualAddress: uint32(imports.MemoryOffset), Size: uint32(len(importsData) * 8)}, // RVA of the import address table
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
@ -116,26 +115,26 @@ func Write(writer io.Writer, code []byte, data []byte, dlls dll.List) {
|
||||
Sections: []SectionHeader{
|
||||
{
|
||||
Name: [8]byte{'.', 't', 'e', 'x', 't'},
|
||||
VirtualSize: uint32(len(code)),
|
||||
VirtualAddress: uint32(codeStart),
|
||||
RawSize: uint32(len(code)), // must be a multiple of FileAlignment
|
||||
RawAddress: uint32(codeStart), // must be a multiple of FileAlignment
|
||||
VirtualSize: uint32(len(code.Bytes)),
|
||||
VirtualAddress: uint32(code.MemoryOffset),
|
||||
RawSize: uint32(len(code.Bytes)), // must be a multiple of FileAlignment
|
||||
RawAddress: uint32(code.FileOffset), // 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)),
|
||||
RawAddress: uint32(dataStart),
|
||||
VirtualSize: uint32(len(data.Bytes)),
|
||||
VirtualAddress: uint32(data.MemoryOffset),
|
||||
RawSize: uint32(len(data.Bytes)),
|
||||
RawAddress: uint32(data.FileOffset),
|
||||
Characteristics: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ,
|
||||
},
|
||||
{
|
||||
Name: [8]byte{'.', 'i', 'd', 'a', 't', 'a'},
|
||||
VirtualSize: uint32(importSectionSize),
|
||||
VirtualAddress: uint32(importsStart),
|
||||
RawSize: uint32(importSectionSize),
|
||||
RawAddress: uint32(importsStart),
|
||||
VirtualSize: uint32(len(imports.Bytes)),
|
||||
VirtualAddress: uint32(imports.MemoryOffset),
|
||||
RawSize: uint32(len(imports.Bytes)),
|
||||
RawAddress: uint32(imports.FileOffset),
|
||||
Characteristics: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ,
|
||||
},
|
||||
},
|
||||
@ -145,12 +144,10 @@ func Write(writer io.Writer, code []byte, data []byte, dlls dll.List) {
|
||||
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{0x00}, codePadding))
|
||||
writer.Write(code)
|
||||
writer.Write(bytes.Repeat([]byte{0x00}, dataPadding))
|
||||
writer.Write(data)
|
||||
writer.Write(bytes.Repeat([]byte{0x00}, importsPadding))
|
||||
binary.Write(writer, binary.LittleEndian, &imports)
|
||||
binary.Write(writer, binary.LittleEndian, &dllData)
|
||||
binary.Write(writer, binary.LittleEndian, &dllImports)
|
||||
writer.Write(bytes.Repeat([]byte{0x00}, code.Padding))
|
||||
writer.Write(code.Bytes)
|
||||
writer.Write(bytes.Repeat([]byte{0x00}, data.Padding))
|
||||
writer.Write(data.Bytes)
|
||||
writer.Write(bytes.Repeat([]byte{0x00}, imports.Padding))
|
||||
writer.Write(imports.Bytes)
|
||||
}
|
||||
|
15
src/pe/cpu.go
Normal file
15
src/pe/cpu.go
Normal file
@ -0,0 +1,15 @@
|
||||
package pe
|
||||
|
||||
import "git.urbach.dev/cli/q/src/config"
|
||||
|
||||
// cpu returns the CPU architecture used in the PE header.
|
||||
func cpu() uint16 {
|
||||
switch config.TargetArch {
|
||||
case config.ARM:
|
||||
return IMAGE_FILE_MACHINE_ARM64
|
||||
case config.X86:
|
||||
return IMAGE_FILE_MACHINE_AMD64
|
||||
default:
|
||||
panic("unknown architecture")
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user