Improved Windows support

This commit is contained in:
Eduard Urbach 2024-08-19 17:25:51 +02:00
parent e9a0494aa7
commit 6b48ee0a48
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
8 changed files with 50 additions and 8 deletions

10
examples/winapi/winapi.q Normal file
View File

@ -0,0 +1,10 @@
import mem
main() {
text := mem.alloc(4)
text[0] = 'H'
text[1] = 'i'
text[2] = '!'
user32.MessageBoxA(0, text, text, 0x00240040)
mem.free(text, 4)
}

5
lib/mem/alloc_windows.q Normal file
View File

@ -0,0 +1,5 @@
import sys
alloc(length Int) -> Pointer {
return sys.mmap(0, length, 0x0004, 0x3000)
}

View File

@ -8,6 +8,10 @@ mmap(address Int, length Int, protection Int, flags Int) -> Pointer {
return kernel32.VirtualAlloc(address, length, flags, protection) return kernel32.VirtualAlloc(address, length, flags, protection)
} }
munmap(address Pointer, length Int) -> Int {
return kernel32.VirtualFree(address, length, 0x4000)
}
exit(code Int) { exit(code Int) {
kernel32.ExitProcess(code) kernel32.ExitProcess(code)
} }

View File

@ -0,0 +1,6 @@
package x64
// AlignStack aligns RSP on a 16-byte boundary.
func AlignStack(code []byte) []byte {
return append(code, 0x48, 0x83, 0xE4, 0xF0)
}

View File

@ -126,11 +126,13 @@ func (a Assembler) Finalize(dlls dll.List) ([]byte, []byte) {
case DLLCALL: case DLLCALL:
size := 4 size := 4
// TODO: R15 could be in use.
code = x64.MoveRegisterRegister(code, x64.R15, x64.RSP)
code = x64.AlignStack(code)
code = x64.SubRegisterNumber(code, x64.RSP, 32) code = x64.SubRegisterNumber(code, x64.RSP, 32)
code = x64.CallAtAddress(code, 0x00_00_00_00) code = x64.CallAtAddress(code, 0x00_00_00_00)
position := len(code) - size position := len(code) - size
code = x64.AddRegisterNumber(code, x64.RSP, 32) code = x64.MoveRegisterRegister(code, x64.RSP, x64.R15)
label := x.Data.(*Label) label := x.Data.(*Label)
pointer := &Pointer{ pointer := &Pointer{

View File

@ -50,7 +50,6 @@ func (r *Result) finalize() ([]byte, []byte, dll.List) {
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[1], 0) final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[1], 0)
final.Syscall() final.Syscall()
case "windows": case "windows":
final.RegisterNumber(asm.SUB, x64.RSP, 8)
final.RegisterNumber(asm.MOVE, windows.X64InputRegisters[0], 0) final.RegisterNumber(asm.MOVE, windows.X64InputRegisters[0], 0)
final.DLLCall("kernel32.ExitProcess") final.DLLCall("kernel32.ExitProcess")
} }
@ -83,9 +82,8 @@ func (r *Result) finalize() ([]byte, []byte, dll.List) {
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[1], 1) final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[1], 1)
final.Syscall() final.Syscall()
case "windows": case "windows":
final.RegisterNumber(asm.SUB, x64.RSP, 8)
final.RegisterNumber(asm.MOVE, windows.X64InputRegisters[0], 1) final.RegisterNumber(asm.MOVE, windows.X64InputRegisters[0], 1)
final.Label(asm.DLLCALL, "kernel32.ExitProcess") final.DLLCall("kernel32.ExitProcess")
} }
code, data := final.Finalize(dlls) code, data := final.Finalize(dlls)

View File

@ -5,7 +5,7 @@ type List []DLL
// Append adds a function for the given DLL if it doesn't exist yet. // Append adds a function for the given DLL if it doesn't exist yet.
func (list List) Append(dllName string, funcName string) List { func (list List) Append(dllName string, funcName string) List {
for _, dll := range list { for i, dll := range list {
if dll.Name != dllName { if dll.Name != dllName {
continue continue
} }
@ -16,13 +16,24 @@ func (list List) Append(dllName string, funcName string) List {
} }
} }
dll.Functions = append(dll.Functions, funcName) list[i].Functions = append(list[i].Functions, funcName)
return list return list
} }
return append(list, DLL{Name: dllName, Functions: []string{funcName}}) return append(list, DLL{Name: dllName, Functions: []string{funcName}})
} }
// Contains returns true if the library exists.
func (list List) Contains(dllName string) bool {
for _, dll := range list {
if dll.Name == dllName {
return true
}
}
return false
}
// Index returns the position of the given function name. // Index returns the position of the given function name.
func (list List) Index(dllName string, funcName string) int { func (list List) Index(dllName string, funcName string) int {
index := 0 index := 0

View File

@ -31,6 +31,12 @@ func Write(writer io.Writer, code []byte, data []byte, dlls dll.List) {
dataStart, dataPadding := exe.Align(codeStart+len(code), config.Align) dataStart, dataPadding := exe.Align(codeStart+len(code), config.Align)
importsStart, importsPadding := exe.Align(dataStart+len(data), config.Align) importsStart, importsPadding := exe.Align(dataStart+len(data), config.Align)
subSystem := IMAGE_SUBSYSTEM_WINDOWS_CUI
if dlls.Contains("user32") {
subSystem = IMAGE_SUBSYSTEM_WINDOWS_GUI
}
imports := make([]uint64, 0) imports := make([]uint64, 0)
dllData := make([]byte, 0) dllData := make([]byte, 0)
dllImports := []DLLImport{} dllImports := []DLLImport{}
@ -125,7 +131,7 @@ func Write(writer io.Writer, code []byte, data []byte, dlls dll.List) {
SizeOfImage: uint32(imageSize), SizeOfImage: uint32(imageSize),
SizeOfHeaders: config.CodeOffset, // section bodies begin here SizeOfHeaders: config.CodeOffset, // section bodies begin here
CheckSum: 0, CheckSum: 0,
Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI, Subsystem: uint16(subSystem),
DllCharacteristics: IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA | IMAGE_DLLCHARACTERISTICS_NX_COMPAT | IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE, // IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE DllCharacteristics: IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA | IMAGE_DLLCHARACTERISTICS_NX_COMPAT | IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE, // IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
SizeOfStackReserve: 0x100000, SizeOfStackReserve: 0x100000,
SizeOfStackCommit: 0x1000, SizeOfStackCommit: 0x1000,