and here we have the not lazy solution:
do_call.asm
Code:
.code
;----------------------------------------------------------------------------
ifdef _WIN64
Sbie_InvokeSyscall_asm PROC
mov qword ptr [rsp+20h], r9
mov qword ptr [rsp+18h], r8
mov qword ptr [rsp+10h], rdx
mov qword ptr [rsp+8], rcx
; note: (count & 0x0F) + 4 = 19 arguments are the absolute maximum
; quick sanity check
cmp rdx, 13h ; if count > 19
jle arg_count_ok
mov rax, 0C000001Ch ; return STATUS_INVALID_SYSTEM_SERVICE
ret
arg_count_ok:
push rsi
push rdi
; prepare enough stack for up to 19 arguments
sub rsp, 98h
; save our 3 relevant arguments to spare registers
mov r11, r8 ; args
mov r10, rdx ; count
mov rax, rcx ; func
; check if we have higher arguments and if not skip
cmp r10, 4
jle copy_reg_args
; copy arguments 5-19
mov rsi, r11 ; source
add rsi, 20h
mov rdi, rsp ; destination
add rdi, 20h
mov rcx, r10 ; arg count
sub rcx, 4 ; skip the register passed args
rep movsq
copy_reg_args:
; copy arguments 1-4
mov r9, qword ptr [r11+18h]
mov r8, qword ptr [r11+10h]
mov rdx, qword ptr [r11+08h]
mov rcx, qword ptr [r11+00h]
; call the function
call rax
; clear stack
add rsp, 98h
pop rdi
pop rsi
ret
Sbie_InvokeSyscall_asm ENDP
else
_Sbie_InvokeSyscall_asm@12 PROC
; NTSTATUS Sbie_InvokeSyscall_asm(void* func, int count, void* args);
; quick sanity check
cmp dword ptr [esp+04h+4h], 13h ; @count
jle args_ok
mov eax, 0C000001Ch ; return STATUS_INVALID_SYSTEM_SERVICE
ret
args_ok:
; prepare enough stack for up to 19 arguments
push ebp
push esi
push edi
mov ebp, esp
sub esp, 4Ch
; copy arguments 0-19
mov esi, dword ptr [ebp+10h+8h] ; source @args
mov edi, esp ; destination
mov ecx, dword ptr [ebp+10h+4h] ; arg count @count
rep movsd
; call the function
mov eax, dword ptr [ebp+10h+0h] ; @func
call eax
; clear stack
function_end:
mov esp,ebp
pop edi
pop esi
pop ebp
ret
_Sbie_InvokeSyscall_asm@12 ENDP
PUBLIC _Sbie_InvokeSyscall_asm@12
endif
;----------------------------------------------------------------------------
end
test.cpp:
Code:
#include <stdio.h>
NTSTATUS Test4(int arg1, int arg2, int arg3, int arg4)
{
printf("arg1: %x, arg2: %x, arg3: %x, arg4: %x\r\n", arg1, arg2, arg3, arg4);
return 0;
}
NTSTATUS Test8(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8)
{
printf("arg1: %x, arg2: %x, arg3: %x, arg4: %x; arg5: %x, arg6: %x, arg7: %x, arg8: %x\r\n", arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
return 0;
}
NTSTATUS Test19(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10, int arg11, int arg12, int arg13, int arg14, int arg15, int arg16, int arg17, int arg18, int arg19)
{
return 123;
}
NTSTATUS Sbie_InvokeSyscall_asm(void* func, int count, void* args);
int main(int argc, char *argv[])
{
#ifdef _WIN64
__int64 stack[19];
#else
int stack[19];
#endif
for (int i = 0; i < 19; i++)
stack[i] = i + 1;
Sbie_InvokeSyscall_asm(Test4, 4, stack);
Sbie_InvokeSyscall_asm(Test8, 8, stack);
Sbie_InvokeSyscall_asm(Test19, 19, stack);
Sbie_InvokeSyscall_asm(Test19, 20, stack);
return 0;
}
Last edited by DavidXanatos; 01-01-2022 at 05:42.
|