View Single Post
Old 01-01-2022, 02:53
DavidXanatos DavidXanatos is offline
Join Date: Jun 2018
Posts: 168
Rept. Given: 2
Rept. Rcvd 40 Times in 27 Posts
Thanks Given: 53
Thanks Rcvd at 311 Times in 106 Posts
DavidXanatos Reputation: 40
and here we have the not lazy solution:



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

     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 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


Sbie_InvokeSyscall_asm ENDP


[email protected] 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

     ; 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

     mov         esp,ebp  
     pop         edi
     pop         esi
     pop         ebp

[email protected] ENDP
PUBLIC [email protected]



#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];
    int stack[19];
    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.
Reply With Quote
The Following 2 Users Say Thank You to DavidXanatos For This Useful Post:
niculaita (01-06-2022), WRP (01-02-2022)