Skip to content

Commit

Permalink
chore: move syscall routines and stubs
Browse files Browse the repository at this point in the history
  • Loading branch information
f1zm0 committed Apr 21, 2023
1 parent 859833e commit 6dc95b5
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 20 deletions.
17 changes: 0 additions & 17 deletions acheron.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package acheron

import (
"errors"
"fmt"

"github.com/f1zm0/acheron/internal/resolver"
"github.com/f1zm0/acheron/internal/resolver/rvasort"
"github.com/f1zm0/acheron/pkg/hashing"
Expand Down Expand Up @@ -52,17 +49,3 @@ func WithHashFunction(f hashing.HashFunction) Option {
func (a *Acheron) HashString(s string) uint64 {
return a.hashFunction([]byte(s))
}

// Syscall executes an indirect syscall with the given function hash and arguments. Returns the error code if it fails.
func (a *Acheron) Syscall(fnHash uint64, args ...uintptr) error {
sys, err := a.resolver.GetSyscall(fnHash)
if err != nil {
return err
}
if errCode := execIndirectSyscall(sys.SSN, sys.TrampolineAddr, args...); errCode != 0 { // !NT_SUCCESS
return errors.New(fmt.Sprintf("syscall failed with error code %d", errCode))
}
return nil
}

func execIndirectSyscall(ssn uint16, gateAddr uintptr, argh ...uintptr) (errcode uint32)
78 changes: 75 additions & 3 deletions syscall_amd64.s
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

#define maxargs 16

// syscall implementation is a mix of:
// syscalls implementation is a mix of:
// - https://golang.org/src/runtime/sys_windows_amd64.s
// - https://github.com/C-Sto/BananaPhone/blob/master/pkg/BananaPhone/asm_x64.s#L96
// with custom modifications to support indirect syscall execution
// via a trampoline (syscall;ret instruction) in ntdll.dll


// func execIndirectSyscall(ssn uint16, trampoline uintptr, argh ...uintptr) (errcode uint32)
TEXT ·execIndirectSyscall(SB),NOSPLIT, $0-32
XORQ AX, AX
Expand All @@ -16,6 +17,8 @@ TEXT ·execIndirectSyscall(SB),NOSPLIT, $0-32
XORQ R11, R11
MOVQ trampoline+8(FP), R11

PUSHQ CX

//put variadic pointer into SI
MOVQ argh_base+16(FP),SI

Expand All @@ -28,8 +31,6 @@ TEXT ·execIndirectSyscall(SB),NOSPLIT, $0-32

// room for args
SUBQ $(maxargs*8), SP

PUSHQ CX

//no parameters, special case
CMPL CX, $0
Expand Down Expand Up @@ -80,3 +81,74 @@ jumpcall:
POPQ CX
MOVL AX, errcode+40(FP)
RET


// func execDirectSyscall(ssn uint16, trampoline uintptr, argh ...uintptr) (errcode uint32)
TEXT ·execDirectSyscall(SB),NOSPLIT, $0-32
XORQ AX, AX
MOVW ssn+0(FP), AX

PUSHQ CX

//put variadic pointer into SI
MOVQ argh_base+16(FP),SI

//put variadic size into CX
MOVQ argh_len+24(FP),CX

// SetLastError(0).
MOVQ 0x30(GS), DI
MOVL $0, 0x68(DI)

// room for args
SUBQ $(maxargs*8), SP

//no parameters, special case
CMPL CX, $0
JLE jumpcall

// Fast version, do not store args on the stack.
CMPL CX, $4
JLE loadregs

// Check we have enough room for args.
CMPL CX, $maxargs
JLE 2(PC)

// not enough room -> crash
INT $3

// Copy args to the stack.
MOVQ SP, DI
CLD
REP; MOVSQ
MOVQ SP, SI

loadregs:

// Load first 4 args into correspondent registers.
MOVQ 0(SI), CX
MOVQ 8(SI), DX
MOVQ 16(SI), R8
MOVQ 24(SI), R9

// Floating point arguments are passed in the XMM registers
// Set them here in case any of the arguments are floating point values.
// For details see: https://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
MOVQ CX, X0
MOVQ DX, X1
MOVQ R8, X2
MOVQ R9, X3

jumpcall:
MOVQ CX, R10

// direcy syscall
SYSCALL

ADDQ $((maxargs)*8), SP

// Return result
POPQ CX
MOVL AX, errcode+40(FP)
RET
34 changes: 34 additions & 0 deletions syscalls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package acheron

import (
"errors"
"fmt"
)

func execIndirectSyscall(ssn uint16, gateAddr uintptr, argh ...uintptr) (errcode uint32)

func execDirectSyscall(ssn uint16, argh ...uintptr) (errcode uint32)

// Syscall executes an indirect syscall with the given function hash and arguments. Returns the error code if it fails.
func (a *Acheron) Syscall(fnHash uint64, args ...uintptr) error {
sys, err := a.resolver.GetSyscall(fnHash)
if err != nil {
return err
}
if errCode := execIndirectSyscall(sys.SSN, sys.TrampolineAddr, args...); errCode != 0 { // !NT_SUCCESS
return errors.New(fmt.Sprintf("syscall failed with error code %d", errCode))
}
return nil
}

// DirectSyscall executes a direct syscall with the given function hash and arguments. Returns the error code if it fails.
func (a *Acheron) DirectSyscall(fnHash uint64, args ...uintptr) error {
sys, err := a.resolver.GetSyscall(fnHash)
if err != nil {
return err
}
if errCode := execDirectSyscall(sys.SSN, args...); errCode != 0 { // !NT_SUCCESS
return errors.New(fmt.Sprintf("syscall failed with error code %d", errCode))
}
return nil
}

0 comments on commit 6dc95b5

Please sign in to comment.