_Use_decl_annotations_
BOOLEAN
SyscallHookHandleUD(PGUEST_REGS Regs, UINT32 CoreIndex)
{
CR3_TYPE GuestCr3;
UINT64 OriginalCr3;
UINT64 Rip;
VIRTUAL_MACHINE_STATE
*
CurrentVmState
=
&g_GuestState[CoreIndex];
/
/
/
/
Reading guest's RIP
/
/
__vmx_vmread(VMCS_GUEST_RIP, &Rip);
if
(g_IsUnsafeSyscallOrSysretHandling)
{
/
/
/
/
In some computers, we realized that safe accessing to memory
/
/
is
problematic. It means that our syscall approach might
not
/
/
working properly.
/
/
Based on our tests, we realized that system doesn't generate
/
/
regularly. So, we can imagine that only kernel addresses are SYSRET
/
/
instruction
and
SYSCALL
is
on a user
-
mode RIP.
/
/
It's faster than our safe methods but
if
the system generates a
/
/
then a BSOD will happen. But
if
the system
is
working regularly, then
/
/
no BSOD happens. For more information, see documentation at !syscall2
/
/
or
!sysret2 commands
/
/
if
(Rip &
0xff00000000000000
)
{
goto EmulateSYSRET;
}
else
{
goto EmulateSYSCALL;
}
}
else
{
/
/
/
/
Get the guest
's running process'
s cr3
/
/
GuestCr3.Flags
=
GetRunningCr3OnTargetProcess().Flags;
/
/
/
/
No, longer needs to be checked because we're sticking to system process
/
/
and
we have to change the cr3
/
/
/
/
if
((GuestCr3.Flags & PCID_MASK) !
=
PCID_NONE)
OriginalCr3
=
__readcr3();
__writecr3(GuestCr3.Flags);
/
/
/
/
Read the memory
/
/
UCHAR InstructionBuffer[
3
]
=
{
0
};
if
(MemoryMapperCheckIfPageIsPresentByCr3(Rip, GuestCr3))
{
/
/
/
/
The page
is
safe to read (present)
/
/
It's
not
necessary to use MemoryMapperReadMemorySafeOnTargetProcess
/
/
because we already switched to the process's cr3
/
/
MemoryMapperReadMemorySafe(Rip, InstructionBuffer,
3
);
}
else
{
/
/
/
/
The page
is
not
present, we have to inject a
/
/
CurrentVmState
-
>IncrementRip
=
FALSE;
/
/
/
/
For testing purpose
/
/
/
/
LogInfo(
"#PF Injected"
);
/
/
/
/
Inject
/
/
EventInjectPageFault(Rip);
/
/
/
/
We should
not
inject
/
/
return
FALSE;
}
__writecr3(OriginalCr3);
/
/
SYSCALL_INSTRUCTION
if
(InstructionBuffer[
0
]
=
=
0x0F
&&
InstructionBuffer[
1
]
=
=
0x05
)
{
goto EmulateSYSCALL;
}
/
/
SYSRET_INSTRUCTION
if
(InstructionBuffer[
0
]
=
=
0x48
&&
InstructionBuffer[
1
]
=
=
0x0F
&&
InstructionBuffer[
2
]
=
=
0x07
)
{
goto EmulateSYSRET;
}
return
FALSE;
}
/
/
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/
/
/
/
Emulate SYSRET instruction
/
/
EmulateSYSRET:
/
/
/
/
Test
/
/
/
/
LogInfo(
"SYSRET instruction => 0x%llX"
, Rip);
/
/
/
/
/
/
Perform the dispatching
and
the emulation of the SYSRET event
/
/
DispatchEventEferSysret(CoreIndex, Regs, Rip);
return
TRUE;
/
/
/
/
Emulate SYSCALL instruction
/
/
EmulateSYSCALL:
/
/
/
/
Test
/
/
/
/
LogInfo(
"SYSCALL instruction => 0x%llX , Process Id : 0x%x"
, Rip, PsGetCurrentProcessId());
/
/
/
/
/
/
Perform the dispatching
and
the emulation of the SYSCAKK event
/
/
DispatchEventEferSyscall(CoreIndex, Regs, Rip);
return
TRUE;
}