Improved security
This commit is contained in:
parent
235188e457
commit
b1b83201eb
@ -9,9 +9,6 @@ import (
|
||||
"git.akyoto.dev/cli/q/src/arch/x64"
|
||||
"git.akyoto.dev/cli/q/src/config"
|
||||
"git.akyoto.dev/cli/q/src/os/common"
|
||||
"git.akyoto.dev/cli/q/src/os/linux/elf"
|
||||
"git.akyoto.dev/cli/q/src/os/mac/macho"
|
||||
"git.akyoto.dev/cli/q/src/os/windows/pe"
|
||||
"git.akyoto.dev/cli/q/src/sizeof"
|
||||
)
|
||||
|
||||
@ -341,25 +338,8 @@ restart:
|
||||
|
||||
data, dataLabels = a.Data.Finalize()
|
||||
|
||||
var (
|
||||
codeOffset Address
|
||||
align Address
|
||||
)
|
||||
|
||||
switch config.TargetOS {
|
||||
case "linux":
|
||||
codeOffset = elf.CodeOffset
|
||||
align = elf.Align
|
||||
case "mac":
|
||||
codeOffset = macho.CodeOffset
|
||||
align = macho.Align
|
||||
case "windows":
|
||||
codeOffset = pe.CodeOffset
|
||||
align = pe.Align
|
||||
}
|
||||
|
||||
dataStart := Address(config.BaseAddress) + codeOffset + Address(len(code))
|
||||
dataStart += int32(common.Padding(dataStart, align))
|
||||
dataStart := Address(config.BaseAddress) + config.CodeOffset + Address(len(code))
|
||||
dataStart += int32(common.Padding(dataStart, config.Align))
|
||||
|
||||
for _, pointer := range dataPointers {
|
||||
address := dataStart + pointer.Resolve()
|
||||
|
@ -8,6 +8,12 @@ const (
|
||||
|
||||
// The base address is the virtual address for our ELF file.
|
||||
BaseAddress = 0x40 * MinAddress
|
||||
|
||||
// Align decides the alignment of the sections and it must be a multiple of the page size.
|
||||
Align = 0x1000
|
||||
|
||||
// The code offset is the offset of the executable machine code within the file.
|
||||
CodeOffset = Align
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -1,6 +1,6 @@
|
||||
package common
|
||||
|
||||
// Padding calculates the padding needed to align `n` bytes with the specified alignment.
|
||||
func Padding[T int64 | uint64 | int32 | uint32](n T, align T) T {
|
||||
func Padding[T int | uint | int64 | uint64 | int32 | uint32](n T, align T) T {
|
||||
return align - (n % align)
|
||||
}
|
||||
|
@ -1,13 +1,5 @@
|
||||
package elf
|
||||
|
||||
const (
|
||||
// Align decides the alignment of the sections and it must be a multiple of the page size.
|
||||
Align = 0x1000
|
||||
|
||||
// The code offset is the offset of the executable machine code within the file.
|
||||
CodeOffset = HeaderSize + ProgramHeaderSize*2
|
||||
)
|
||||
|
||||
const (
|
||||
LittleEndian = 1
|
||||
TypeExecutable = 2
|
||||
|
@ -22,8 +22,9 @@ type ELF struct {
|
||||
|
||||
// New creates a new ELF binary.
|
||||
func New(code []byte, data []byte) *ELF {
|
||||
dataOffset := CodeOffset + int64(len(code))
|
||||
dataPadding := common.Padding(dataOffset, Align)
|
||||
codePadding := common.Padding(HeaderSize+ProgramHeaderSize*2, config.Align)
|
||||
dataOffset := config.CodeOffset + int64(len(code))
|
||||
dataPadding := common.Padding(dataOffset, config.Align)
|
||||
dataOffset += dataPadding
|
||||
|
||||
return &ELF{
|
||||
@ -37,7 +38,7 @@ func New(code []byte, data []byte) *ELF {
|
||||
Type: TypeExecutable,
|
||||
Architecture: ArchitectureAMD64,
|
||||
FileVersion: 1,
|
||||
EntryPointInMemory: config.BaseAddress + CodeOffset,
|
||||
EntryPointInMemory: config.BaseAddress + config.CodeOffset,
|
||||
ProgramHeaderOffset: HeaderSize,
|
||||
SectionHeaderOffset: 0,
|
||||
Flags: 0,
|
||||
@ -51,12 +52,12 @@ func New(code []byte, data []byte) *ELF {
|
||||
CodeHeader: ProgramHeader{
|
||||
Type: ProgramTypeLOAD,
|
||||
Flags: ProgramFlagsExecutable | ProgramFlagsReadable,
|
||||
Offset: CodeOffset,
|
||||
VirtualAddress: config.BaseAddress + CodeOffset,
|
||||
PhysicalAddress: config.BaseAddress + CodeOffset,
|
||||
Offset: config.CodeOffset,
|
||||
VirtualAddress: config.BaseAddress + config.CodeOffset,
|
||||
PhysicalAddress: config.BaseAddress + config.CodeOffset,
|
||||
SizeInFile: int64(len(code)),
|
||||
SizeInMemory: int64(len(code)),
|
||||
Align: Align,
|
||||
Align: config.Align,
|
||||
},
|
||||
DataHeader: ProgramHeader{
|
||||
Type: ProgramTypeLOAD,
|
||||
@ -66,9 +67,9 @@ func New(code []byte, data []byte) *ELF {
|
||||
PhysicalAddress: config.BaseAddress + dataOffset,
|
||||
SizeInFile: int64(len(data)),
|
||||
SizeInMemory: int64(len(data)),
|
||||
Align: Align,
|
||||
Align: config.Align,
|
||||
},
|
||||
CodePadding: nil,
|
||||
CodePadding: bytes.Repeat([]byte{0}, int(codePadding)),
|
||||
Code: code,
|
||||
DataPadding: bytes.Repeat([]byte{0}, int(dataPadding)),
|
||||
Data: data,
|
||||
|
@ -1,13 +1,5 @@
|
||||
package macho
|
||||
|
||||
const (
|
||||
// Align decides the alignment of the sections and it must be a multiple of the page size.
|
||||
Align = 0x1000
|
||||
|
||||
// The code offset is the offset of the executable machine code within the file.
|
||||
CodeOffset = 32 + 0x48*3 + 184
|
||||
)
|
||||
|
||||
type CPU uint32
|
||||
|
||||
const (
|
||||
|
@ -52,19 +52,19 @@ func (m *MachO) Write(writer io.Writer) {
|
||||
InitProt: 0,
|
||||
})
|
||||
|
||||
codeStart := uint64(32 + m.Header.SizeCommands)
|
||||
codePadding := common.Padding(32+m.Header.SizeCommands, config.Align)
|
||||
codeLength := uint64(len(m.Code))
|
||||
codeEnd := codeStart + codeLength
|
||||
dataPadding := common.Padding(codeEnd, Align)
|
||||
codeEnd := config.CodeOffset + codeLength
|
||||
dataPadding := common.Padding(codeEnd, config.Align)
|
||||
dataStart := codeEnd + dataPadding
|
||||
|
||||
binary.Write(writer, binary.LittleEndian, &Segment64{
|
||||
LoadCommand: LcSegment64,
|
||||
Length: 72,
|
||||
Name: [16]byte{'_', '_', 'T', 'E', 'X', 'T'},
|
||||
Address: config.BaseAddress + codeStart,
|
||||
Address: config.BaseAddress + config.CodeOffset,
|
||||
SizeInMemory: codeLength,
|
||||
Offset: 0,
|
||||
Offset: config.CodeOffset,
|
||||
SizeInFile: codeLength,
|
||||
NumSections: 0,
|
||||
Flag: 0,
|
||||
@ -110,13 +110,14 @@ func (m *MachO) Write(writer io.Writer) {
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
config.BaseAddress + uint32(codeStart), 0,
|
||||
config.BaseAddress + config.CodeOffset, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
})
|
||||
|
||||
writer.Write(bytes.Repeat([]byte{0}, int(codePadding)))
|
||||
writer.Write(m.Code)
|
||||
writer.Write(bytes.Repeat([]byte{0}, int(dataPadding)))
|
||||
writer.Write(m.Data)
|
||||
|
@ -1,13 +1,5 @@
|
||||
package pe
|
||||
|
||||
const (
|
||||
// Align decides the alignment of the sections.
|
||||
Align = 0x200
|
||||
|
||||
// The code offset is the offset of the executable machine code within the file.
|
||||
CodeOffset = Align
|
||||
)
|
||||
|
||||
// CPU
|
||||
const (
|
||||
IMAGE_FILE_MACHINE_AMD64 = 0x8664
|
||||
|
@ -7,5 +7,5 @@ const DOSHeaderSize = 64
|
||||
type DOSHeader struct {
|
||||
Magic [4]byte
|
||||
_ [56]byte
|
||||
PEHeaderOffset uint32
|
||||
NTHeaderOffset uint32
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ const NumSections = 2
|
||||
// EXE is the portable executable format used on Windows.
|
||||
type EXE struct {
|
||||
DOSHeader
|
||||
PEHeader
|
||||
NTHeader
|
||||
OptionalHeader64
|
||||
Sections [NumSections]SectionHeader
|
||||
CodePadding []byte
|
||||
@ -25,23 +25,23 @@ type EXE struct {
|
||||
|
||||
// New creates a new EXE file.
|
||||
func New(code []byte, data []byte) *EXE {
|
||||
codeStart := uint32(DOSHeaderSize + PEHeaderSize + OptionalHeader64Size + SectionHeaderSize*NumSections)
|
||||
codePadding := common.Padding(codeStart, Align)
|
||||
codeStart := uint32(DOSHeaderSize + NTHeaderSize + OptionalHeader64Size + SectionHeaderSize*NumSections)
|
||||
codePadding := common.Padding(codeStart, config.Align)
|
||||
codeStart += codePadding
|
||||
|
||||
dataStart := codeStart + uint32(len(code))
|
||||
dataPadding := common.Padding(dataStart, Align)
|
||||
dataPadding := common.Padding(dataStart, config.Align)
|
||||
dataStart += dataPadding
|
||||
|
||||
imageSize := uint32(dataStart + uint32(len(data)))
|
||||
imageSize += common.Padding(imageSize, Align)
|
||||
imageSize += common.Padding(imageSize, config.Align)
|
||||
|
||||
return &EXE{
|
||||
DOSHeader: DOSHeader{
|
||||
Magic: [4]byte{'M', 'Z', 0, 0},
|
||||
PEHeaderOffset: 0x40,
|
||||
NTHeaderOffset: 0x40,
|
||||
},
|
||||
PEHeader: PEHeader{
|
||||
NTHeader: NTHeader{
|
||||
Signature: [4]byte{'P', 'E', 0, 0},
|
||||
Machine: IMAGE_FILE_MACHINE_AMD64,
|
||||
NumberOfSections: NumSections,
|
||||
@ -54,9 +54,10 @@ func New(code []byte, data []byte) *EXE {
|
||||
MinorLinkerVersion: 0x16,
|
||||
SizeOfCode: uint32(len(code)),
|
||||
AddressOfEntryPoint: codeStart,
|
||||
BaseOfCode: codeStart,
|
||||
ImageBase: config.BaseAddress,
|
||||
SectionAlignment: Align, // power of 2, must be greater than or equal to FileAlignment
|
||||
FileAlignment: Align, // power of 2
|
||||
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: imageSize,
|
||||
@ -89,7 +90,7 @@ func New(code []byte, data []byte) *EXE {
|
||||
},
|
||||
Sections: [NumSections]SectionHeader{
|
||||
{
|
||||
Name: [8]byte{'.', 'c', 'o', 'd', 'e'},
|
||||
Name: [8]byte{'.', 't', 'e', 'x', 't'},
|
||||
VirtualSize: uint32(len(code)),
|
||||
VirtualAddress: codeStart,
|
||||
RawSize: uint32(len(code)), // must be a multiple of FileAlignment
|
||||
@ -97,7 +98,7 @@ func New(code []byte, data []byte) *EXE {
|
||||
Characteristics: IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ,
|
||||
},
|
||||
{
|
||||
Name: [8]byte{'.', 'd', 'a', 't', 'a'},
|
||||
Name: [8]byte{'.', 'r', 'd', 'a', 't', 'a'},
|
||||
VirtualSize: uint32(len(data)),
|
||||
VirtualAddress: dataStart,
|
||||
RawSize: uint32(len(data)), // must be a multiple of FileAlignment
|
||||
@ -115,7 +116,7 @@ func New(code []byte, data []byte) *EXE {
|
||||
// Write writes the EXE file to the given writer.
|
||||
func (pe *EXE) Write(writer io.Writer) {
|
||||
binary.Write(writer, binary.LittleEndian, &pe.DOSHeader)
|
||||
binary.Write(writer, binary.LittleEndian, &pe.PEHeader)
|
||||
binary.Write(writer, binary.LittleEndian, &pe.NTHeader)
|
||||
binary.Write(writer, binary.LittleEndian, &pe.OptionalHeader64)
|
||||
binary.Write(writer, binary.LittleEndian, &pe.Sections)
|
||||
binary.Write(writer, binary.LittleEndian, &pe.CodePadding)
|
||||
|
@ -1,8 +1,8 @@
|
||||
package pe
|
||||
|
||||
const PEHeaderSize = 24
|
||||
const NTHeaderSize = 24
|
||||
|
||||
type PEHeader struct {
|
||||
type NTHeader struct {
|
||||
Signature [4]byte
|
||||
Machine uint16
|
||||
NumberOfSections uint16
|
Loading…
Reference in New Issue
Block a user