Improved Windows support
This commit is contained in:
@ -1,6 +0,0 @@
|
||||
package pe
|
||||
|
||||
type DLL struct {
|
||||
Name string
|
||||
Functions []string
|
||||
}
|
@ -6,6 +6,7 @@ import (
|
||||
"io"
|
||||
|
||||
"git.akyoto.dev/cli/q/src/config"
|
||||
"git.akyoto.dev/cli/q/src/dll"
|
||||
"git.akyoto.dev/cli/q/src/exe"
|
||||
)
|
||||
|
||||
@ -18,56 +19,71 @@ type EXE struct {
|
||||
}
|
||||
|
||||
// Write writes the EXE file to the given writer.
|
||||
func Write(writer io.Writer, code []byte, data []byte, dlls []DLL) {
|
||||
NumSections := 2
|
||||
func Write(writer io.Writer, code []byte, data []byte, dlls dll.List) {
|
||||
if len(data) == 0 {
|
||||
data = []byte{0}
|
||||
}
|
||||
|
||||
NumSections := 3
|
||||
HeaderEnd := DOSHeaderSize + NTHeaderSize + OptionalHeader64Size + SectionHeaderSize*NumSections
|
||||
codeStart, codePadding := exe.Align(HeaderEnd, config.Align)
|
||||
dataStart, dataPadding := exe.Align(codeStart+len(code), config.Align)
|
||||
importsStart, importsPadding := exe.Align(dataStart+len(data), config.Align)
|
||||
|
||||
imports := make([]uint64, 0)
|
||||
dllData := make([]byte, 0)
|
||||
dllImports := []DLLImport{}
|
||||
|
||||
for _, dll := range dlls {
|
||||
dllAddresses := []uint64{}
|
||||
dllNamePos := len(data)
|
||||
data = append(data, dll.Name...)
|
||||
data = append(data, 0x00)
|
||||
|
||||
for _, f := range dll.Functions {
|
||||
pos := len(data)
|
||||
data = append(data, 0x00, 0x00)
|
||||
data = append(data, f...)
|
||||
data = append(data, 0x00)
|
||||
|
||||
if len(data)&1 != 0 {
|
||||
data = append(data, 0x00) // align the next entry on an even boundary
|
||||
}
|
||||
|
||||
dllAddresses = append(dllAddresses, uint64(dataStart+pos))
|
||||
}
|
||||
|
||||
dllAddresses = append(dllAddresses, 0)
|
||||
|
||||
// Add the address table to the data section
|
||||
functionAddressesStart := dataStart + len(data)
|
||||
data, _ = binary.Append(data, binary.LittleEndian, &dllAddresses)
|
||||
for _, library := range dlls {
|
||||
functionsStart := len(imports) * 8
|
||||
dllNamePos := len(dllData)
|
||||
dllData = append(dllData, library.Name...)
|
||||
dllData = append(dllData, 0x00)
|
||||
|
||||
dllImports = append(dllImports, DLLImport{
|
||||
RvaFunctionNameList: uint32(functionAddressesStart),
|
||||
RvaFunctionNameList: uint32(importsStart + functionsStart),
|
||||
TimeDateStamp: 0,
|
||||
ForwarderChain: 0,
|
||||
RvaModuleName: uint32(dataStart + dllNamePos),
|
||||
RvaFunctionAddressList: uint32(functionAddressesStart),
|
||||
RvaModuleName: uint32(dllNamePos),
|
||||
RvaFunctionAddressList: uint32(importsStart + functionsStart),
|
||||
})
|
||||
|
||||
for _, fn := range library.Functions {
|
||||
if len(dllData)&1 != 0 {
|
||||
dllData = append(dllData, 0x00) // align the next entry on an even boundary
|
||||
}
|
||||
|
||||
offset := len(dllData)
|
||||
dllData = append(dllData, 0x00, 0x00)
|
||||
dllData = append(dllData, fn...)
|
||||
dllData = append(dllData, 0x00)
|
||||
|
||||
imports = append(imports, uint64(offset))
|
||||
}
|
||||
|
||||
imports = append(imports, 0)
|
||||
}
|
||||
|
||||
dllDataStart := importsStart + len(imports)*8
|
||||
|
||||
for i := range imports {
|
||||
if imports[i] == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
imports[i] += uint64(dllDataStart)
|
||||
}
|
||||
|
||||
for i := range dllImports {
|
||||
dllImports[i].RvaModuleName += uint32(dllDataStart)
|
||||
}
|
||||
|
||||
dllImports = append(dllImports, DLLImport{}) // a zeroed structure marks the end of the list
|
||||
importDirectoryStart := dllDataStart + len(dllData)
|
||||
importDirectorySize := DLLImportSize * len(dllImports)
|
||||
|
||||
// Add imports to the data section
|
||||
importsStart := dataStart + len(data)
|
||||
importsSize := DLLImportSize * len(dllImports)
|
||||
data, _ = binary.Append(data, binary.LittleEndian, &dllImports)
|
||||
|
||||
imageSize := dataStart + len(data)
|
||||
importSectionSize := len(imports)*8 + len(dllData) + importDirectorySize
|
||||
imageSize := importsStart + importSectionSize
|
||||
imageSize, _ = exe.Align(imageSize, config.Align)
|
||||
|
||||
pe := &EXE{
|
||||
@ -117,8 +133,7 @@ func Write(writer io.Writer, code []byte, data []byte, dlls []DLL) {
|
||||
NumberOfRvaAndSizes: 16,
|
||||
DataDirectory: [16]DataDirectory{
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: uint32(importsStart), Size: uint32(importsSize)}, // RVA of the imported function table
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: uint32(importDirectoryStart), Size: uint32(importDirectorySize)}, // RVA of the imported function table
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
@ -129,6 +144,7 @@ func Write(writer io.Writer, code []byte, data []byte, dlls []DLL) {
|
||||
{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: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
{VirtualAddress: 0, Size: 0},
|
||||
@ -151,6 +167,14 @@ func Write(writer io.Writer, code []byte, data []byte, dlls []DLL) {
|
||||
RawAddress: uint32(dataStart),
|
||||
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),
|
||||
Characteristics: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -163,4 +187,8 @@ func Write(writer io.Writer, code []byte, data []byte, dlls []DLL) {
|
||||
writer.Write(code)
|
||||
writer.Write(bytes.Repeat([]byte{0x00}, int(dataPadding)))
|
||||
writer.Write(data)
|
||||
writer.Write(bytes.Repeat([]byte{0x00}, int(importsPadding)))
|
||||
binary.Write(writer, binary.LittleEndian, &imports)
|
||||
binary.Write(writer, binary.LittleEndian, &dllData)
|
||||
binary.Write(writer, binary.LittleEndian, &dllImports)
|
||||
}
|
||||
|
Reference in New Issue
Block a user