This commit is contained in:
DavidXanatos 2022-01-05 12:24:10 +01:00
parent 55febcef1a
commit fd61ce01ca
4 changed files with 111 additions and 44 deletions

View File

@ -421,12 +421,7 @@
<ClCompile Include="process_util.c" />
<ClCompile Include="log_buff.c" />
<ClCompile Include="session.c" />
<ClCompile Include="syscall.c">
<ControlFlowGuard Condition="'$(Configuration)|$(Platform)'=='SbieRelease|Win32'">false</ControlFlowGuard>
<ControlFlowGuard Condition="'$(Configuration)|$(Platform)'=='SbieDebug|Win32'">false</ControlFlowGuard>
<ControlFlowGuard Condition="'$(Configuration)|$(Platform)'=='SbieRelease|x64'">false</ControlFlowGuard>
<ControlFlowGuard Condition="'$(Configuration)|$(Platform)'=='SbieDebug|x64'">false</ControlFlowGuard>
</ClCompile>
<ClCompile Include="syscall.c" />
<ClCompile Include="syscall_32.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieDebug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='SbieRelease|Win32'">true</ExcludedFromBuild>

View File

@ -110,7 +110,7 @@ static BOOLEAN Syscall_GetKernelAddr(
//---------------------------------------------------------------------------
/*
typedef NTSTATUS (*P_SystemService00)(void);
typedef NTSTATUS (*P_SystemService01)(
ULONG_PTR arg01);
@ -187,6 +187,7 @@ typedef NTSTATUS (*P_SystemService19)(
ULONG_PTR arg13, ULONG_PTR arg14, ULONG_PTR arg15, ULONG_PTR arg16,
ULONG_PTR arg17, ULONG_PTR arg18, ULONG_PTR arg19);
// (count & 0x0F) + 4 -> 19 is absolute maximum
*/
//---------------------------------------------------------------------------
// Variables
@ -602,6 +603,24 @@ _FX void Syscall_ErrorForAsciiName(const UCHAR *name_a)
//---------------------------------------------------------------------------
extern unsigned int g_TrapFrameOffset;
#ifdef _WIN64
//NTSTATUS Sbie_InvokeSyscall_jmp(
// ULONG_PTR arg01, ULONG_PTR arg02, ULONG_PTR arg03, ULONG_PTR arg04,
// ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08,
// ULONG_PTR arg09, ULONG_PTR arg10, ULONG_PTR arg11, ULONG_PTR arg12,
// ULONG_PTR arg13, ULONG_PTR arg14, ULONG_PTR arg15, ULONG_PTR arg16,
// ULONG_PTR arg17, ULONG_PTR arg18, ULONG_PTR arg19, void* func);
NTSTATUS Sbie_InvokeSyscall_hack(void* func, int count, void* args, ULONG_PTR arg04,
ULONG_PTR arg05, ULONG_PTR arg06, ULONG_PTR arg07, ULONG_PTR arg08,
ULONG_PTR arg09, ULONG_PTR arg10, ULONG_PTR arg11, ULONG_PTR arg12,
ULONG_PTR arg13, ULONG_PTR arg14, ULONG_PTR arg15, ULONG_PTR arg16,
ULONG_PTR arg17, ULONG_PTR arg18, ULONG_PTR arg19);
#else
NTSTATUS Sbie_InvokeSyscall_asm(void* func, int count, void* args);
#endif
_FX NTSTATUS Syscall_Invoke(SYSCALL_ENTRY *entry, ULONG_PTR *stack)
{
NTSTATUS status;
@ -609,14 +628,39 @@ _FX NTSTATUS Syscall_Invoke(SYSCALL_ENTRY *entry, ULONG_PTR *stack)
//
// Note: when directly calling win32k functions with "Core Isolation" (HVCI) enabled
// the nt!guard_dispatch_icall will cause a bugcheck!
// Hence we it is required to disable "Control Flow Guard" for this file
// Hence we use a call proxy Sbie_InvokeSyscall_asm instead of a direct call
// alternatively we could disable "Control Flow Guard" for this file
//
__try {
//DbgPrint("[syscall] request param count = %d\n", entry->param_count);
if (entry->param_count == 0) {
#ifdef _WIN64
//
// Note: For some weird reason the x64 version of Sbie_InvokeSyscall_asm
// while working for 64 bit apps, makes 32 bit apps crash under wow64,
// this should not be possible yet it happens, hence we use a hacky workaround
// where our sys call invoker does not do a call but a jmp that seams to be fine.
// Ther for that we need to use this functions stack, hence those many 0 args.
//
// this also works but is less efficient
//#define ARG(idx) (entry->param_count > idx ? stack[idx] : 0)
//status = Sbie_InvokeSyscall_jmp(
// ARG(0), ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6), ARG(7), ARG(8), ARG(9),
// ARG(10), ARG(11), ARG(12), ARG(13), ARG(14), ARG(15), ARG(16), ARG(17), ARG(18),
// entry->ntos_func);
//#undef ARG
status = Sbie_InvokeSyscall_hack(entry->ntos_func, entry->param_count, stack, 0, // args 1-4 shadow space
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); // reserve stack for args 5-19
#else
status = Sbie_InvokeSyscall_asm(entry->ntos_func, entry->param_count, stack);
#endif
/*if (entry->param_count == 0) {
P_SystemService00 nt = (P_SystemService00)entry->ntos_func;
status = nt();
@ -748,7 +792,7 @@ _FX NTSTATUS Syscall_Invoke(SYSCALL_ENTRY *entry, ULONG_PTR *stack)
} else {
status = STATUS_INVALID_SYSTEM_SERVICE;
}
}*/
} __except (EXCEPTION_EXECUTE_HANDLER) {
status = GetExceptionCode();

View File

@ -444,36 +444,6 @@ _FX BOOLEAN Syscall_Init_Table32(void)
}
//---------------------------------------------------------------------------
// Syscall_InvokeNew
//---------------------------------------------------------------------------
_FX NTSTATUS Sbie_InvokeSyscall_asm(void* func, int count, void* args);
_FX NTSTATUS Syscall_InvokeNew(SYSCALL_ENTRY *entry, ULONG_PTR *stack)
{
NTSTATUS status;
//
// Note: when directly calling win32k functions with "Core Isolation" (HVCI) enabled
// the nt!guard_dispatch_icall will cause a bugcheck!
// Hence we use a call proxy Sbie_InvokeSyscall_asm instead of a direct call
//
__try {
//DbgPrint("[syscall] request param count = %d\n", entry->param_count);
status = Sbie_InvokeSyscall_asm(entry->ntos_func, entry->param_count, stack);
} __except (EXCEPTION_EXECUTE_HANDLER) {
status = GetExceptionCode();
}
return status;
}
//---------------------------------------------------------------------------
// Syscall_Api_Invoke32
//---------------------------------------------------------------------------

View File

@ -271,12 +271,70 @@ endif
ifdef _WIN64
Sbie_InvokeSyscall_jmp PROC
jmp qword ptr [rsp+0A0h] ; 20th argument
Sbie_InvokeSyscall_jmp ENDP
Sbie_InvokeSyscall_hack 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:
; 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
push rsi
push rdi
mov rsi, r11 ; source
add rsi, 20h
mov rdi, rsp ; destination
add rdi, 38h ; 28h + 8h + 8h
mov rcx, r10 ; arg count
sub rcx, 4 ; skip the register passed args
rep movsq
pop rdi
pop rsi
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
jmp rax
Sbie_InvokeSyscall_hack ENDP
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
;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