title: “Syscall64” description: “Doing direct syscalls on all platforms” date: 2019-11-10T00:00:00+01:00
A slightly hacky way (C macros) to do direct syscalls on either x86 or x64 windows, without any code change.
http://vcs.wacked.codes/wacked/syscall64
Use with this:
;http://blogs.msdn.com/b/oldnewthing/archive/2004/01/14/58579.aspx
format ms coff
include 'u:\fasm\INCLUDE\win32wx.inc'
public _syscall64
section '.text' code readable executable
; Converts the arguments and then executes SYSCALL
; 1. Param: Count of args to pass to syscall
; 2. Param: Syscall id
; 3. - X. Param: Params for syscall
_syscall64:
; Those registers are pushed here so that the LEAVE instr cleans up the converted params without me needing to
; calc how much space those needed. Seriously what's 4*3 again?
push edi
push ebx
push edx ; used by the x64 code
push ebp
mov ebp, esp
; Alloc space for params
mov ecx, [ebp + 4*3 + 0x08] ; cnt
cmp ecx, 4 ; Reserve shadow space
jge @f
mov ecx, 4
@@:
shl ecx, 3
sub esp, ecx
and esp, 0xFFFFFFF0 ; Align stack
; Convert params to x64
mov edi, esp ; Destination
mov ecx, [ebp + 4*3 + 0x08] ; Count
lea ebx, [ebp + 4*3 + 0x10] ; Source for params
CONVERT_PARAMS_LOOP:
test ecx, ecx
je @f
mov eax, [ebx]
stosd ; mov dword[edi], dword[eax] edi += 4
mov eax, 0
stosd ; [edi] = 0 edi += 4
add ebx, 4 ; srcPtr++
dec ecx ; cnt--
jmp CONVERT_PARAMS_LOOP
@@:
;mov eax, [ebp + 4*3 + 0x0C] ; Get syscall id
call 0x33:X64_START
X86_RETURN_FROM_X64:
leave
pop edx
pop ebx
pop edi
ret
;align 16
X64_START:
use64
mov eax, dword [ebp + 0x18] ; Get syscall id (4*3 = saved registers, )
; Get args from shadow space
mov rcx, [rsp + 8]
mov rdx , [rsp + 0x10]
mov r8, [rsp + 0x18]
mov r9, [rsp + 0x20]
mov r10,rcx
syscall
use32
retf