Giter Club home page Giter Club logo

simplesvmhook's Introduction

SimpleSvmHook

Introduction

SimpleSvmHook is a research purpose hypervisor for Windows on AMD processors. It hooks kernel mode functions and protects them from being detected using Nested Page Tables (NPT), part of AMD Virtualization (AMD-V) technology.

This project is meant to serve as an example implementation of virtual machine introspection (VMI) on AMD processors and highlight differences from similar VMI implementations on Intel processors.

If you already know about DdiMon, this is an AMD counterpart of it from the functionality perspective except few things described below.

Overview of Stealth Hook Implementation

A stealth hook is a type of hook that is not visible from the outside of the monitor or inspector component. In the context of VMI, stealth hook is installed and managed by a hypervisor into guest code to redirect execution of specified addresses while being not easily detectable by the guest.

One of common ways to implement stealth hook within a hypervisor is to split “view” of memory for read/write and execute access from the guest using Second Level Address Translation (SLAT), namely, Extended Page Table (EPT) on Intel and Nested Page Tables (NPT) for AMD processors.

SLAT introduces one more address translation step, that is, translation from the guest physical address (GPA) to the system physical address (SPA). This essentially allows a hypervisor to set up a mapping of a virtual address in the guest and a backing physical memory address. The below diagram illustrates how SLAT can be configured and address translation will result in.

GPA              SPA     Memory Contents
-----------------------------------------
0x1000 –(SLAT)-> 0xa000  ...
0x2000 –(SLAT)-> 0xb000  48 89 54 24 10
...

SLAT can also configure permission of the GPA against the guest; for instance, GPA:0x2000 can be configured as readable/writable but not executable. When the guest attempts to access a GPA in a way not permitted by SLAT, the processor triggers VM-exit so that a hypervisor can take necessary actions, such as updating the permission or inject #GP into the guest.

Stealth hook is often implemented by leveraging those capabilities. Take DdiMon as an example, when the hypervisor installs stealth hook, it creates a copy of the target page, sets 0xCC into the address to hook, then sets up EPT to make the page execute-only (0xb000 in the below example).

GPA                 SPA     Memory Contents
--------------------------------------------
0x2000 –(EPT --X)-> 0xb000  CC 89 54 24 10
                    0xf000  48 89 54 24 10  (The copied page. Unused yet)
...

When the guest attempts to execute the address, the hypervisor:

  1. traps #BP
  2. changes the instruction pointer of the guest to our handler function
  3. lets the guest run

and when the guest attempts to read from or write to the address, the hypervisor:

  1. traps VM-exit caused due to access violation
  2. updates EPT to associate the address with the copied page, which does not contain 0xCC, with the readable/writable permission
GPA                 SPA     Memory Contents
--------------------------------------------
0x2000 –(EPT RW-)\  0xb000  CC 89 54 24 10
                  ->0xf000  48 89 54 24 10  (The copied page)
...
  1. single steps and lets the guest complete the read or write operation
  2. updates EPT to revert the settings
GPA                 SPA     Memory Contents
--------------------------------------------
0x2000 –(EPT --X)-> 0xb000  CC 89 54 24 10
                    0xf000  48 89 54 24 10  (The copied page)
...
  1. lets the guest run

Those operations allow the hypervisor to redirect execution of the guest while keeping the hook invisible from the guest. Also, notice that EPT configurations are reverted to the original state, and the next execute or read/write access can be handled in the same way.

However, this cannot be implemented directly on AMD processors.

Implementation on AMD Processors and Limitations

The previously described technique cannot be implemented on AMD processors due to lack the execute-only permission.

NPT, the AMD implementation of SLAT, does not permit a hypervisor to configure the permission as execute-only because there is no bit to indicate whether the page is readable. To make the page executable, it must also be readable at the same time. This limitation requires significant changes in a way to hide hooks.

Firstly, a hypervisor needs to set the unmodified readable/writable page as the default association of the target page (0xb000 in the below example).

GPA                 SPA     Memory Contents
--------------------------------------------
0x2000 –(NPT RW-)-> 0xb000  48 89 54 24 10
                    0xf000  CC 89 54 24 10  (The copied page. Unused yet)
...

This introduces additional performance cost due to more frequent VM-exit (recall that the address being hooked is code and much more likely accessed for execution).

Secondly, the hook has to remain visible in some situation. Let us see why.

When the guest attempts to execute the address, the hypervisor:

  1. traps VM-exit caused due to access violation
  2. updates NPT to associate the address with the copied page, which contains 0xCC, with the readable/writable/executable permission.
GPA                 SPA     Memory Contents
--------------------------------------------
0x2000 –(NPT RWX)\  0xb000  48 89 54 24 10
                  ->0xf000  CC 89 54 24 10  (The copied page)
...
  1. lets the guest run
  2. traps #BP
  3. changes the instruction pointer of the guest to our handler function

Notice that while hook was executed, the hooked page remains readable with 0xCC.

This is a critical issue yet resolution is challenging because:

  • the page cannot be non-readable while being executable because of the limitation of NPT,
  • the page contents cannot be reverted to the original contents since the guest may execute the hooked address while 0xCC is removed, and
  • AMD-V lacks the Monitor Trap Flag equivalent feature that could have been used to overcome the second point.

The partial solution to this issue is to trap the guest when it attempts to execute the outside of the hooked page, and then, hide 0xCC. This can be achieved by setting all pages but the hooked page non-executable, then, when the guest jumps out to the outside of the hooked page, the hypervisor:

  1. traps VM-exit caused due to access violation
  2. updates NPT to make all pages but the hooked page executable again
  3. updates NPT to associate the hooked page with the unmodified page with the readable/writable permission
GPA                 SPA     Memory Contents
--------------------------------------------
0x2000 –(NPT RW-)-> 0xb000  48 89 54 24 10
                    0xf000  CC 89 54 24 10  (The copied page)
...
  1. lets the guest run

This way, the hook remains invisible while the guest is executing any code outside of the hooked page. In other words, the guest can still see the hook while it is executing the same page as the hooked page. This may be a significant limitation if hook must be installed on code that may perform a self-integrity check, but it is unlikely a real issue if hook is installed against known kernel code such as NTOSKRNL and Win32k.

The other downside of this design is overhead of NTP manipulation. VM-exit, when the guest jumps into and out from the hooked page, has non-negligible performance penalty because the hypervisor must update multiple NPT entries to change the executable permission of all pages.

Delay in Windows boot time measured by Windows Performance Analyzer with the current implementation was 20% on HP EliteBook 725 G4 (AMD A12 PRO-8830B), while it was only 9% with DdiMon on Dell Latitude E6410 (Intel Core i7-620M). Given that the tested AMD processor is almost the 7 years newer model than the tested Intel processor and expected to have much more optimized implementation of AMD-V than that of VT-x on the old Intel processor, this high number (20%) is likely because of the heavyweight VM-exit handling.

While this overhead did not appear to be noticeable on normal load, it could be the real issue depending on load, and possibly, the number of hooks installed.

Conclusion

This project demonstrated that implementation of stealth hook on AMD processors was possible with the caveat that hook had to remain visible from code in the same page and that performance overhead introduced by the explained design was considerably higher than that of similar implementation on Intel processors.

Those limitation can be ignored in some use cases such as instrumentation of known kernel API for research, but could prevent researchers from developing highly-stealth VMI tools and tools for performance sensitive environments.

Installation and Uninstallation

To build SimpleSvmHook from source code, clone full source code from GitHub with the below command and compile it on a supported version of Visual Studio.

$ git clone https://github.com/tandasat/SimpleSvmHook.git

You have to enable test signing to install the driver before installing it. To do that, open the command prompt with the administrator privilege and run the following command, and then restart the system to activate the change:

>bcdedit /set testsigning on

To install and uninstall the SimpleSvmHook driver, use the sc command. For installation and start:

>sc create SimpleSvmHook type= kernel binPath= C:\Users\user\Desktop\SimpleSvmHook.sys
>sc start SimpleSvmHook

Note that the driver may fail to start due to failure to disassemble code for hooking. SimpleSvmHook can only handle known byte patterns (instructions) and does not attempt to disassemble unknown byte patterns. You can resolve such errors by adding new patterns to the "FindFirstInstruction" function and recompiling the driver.

For uninstallation:

>sc stop SimpleSvmHook
>sc delete SimpleSvmHook
>bcdedit /deletevalue testsigning

Output

All debug output are saved in C:\Windows\SimpleSvmHook.log.

This screenshot shows example output from installed hooks as well as that those hooks are not visible from the system (the local kernel debugger).

HookInstalled

Supported Platforms

  • Windows 10 x64 and Windows 7 x64
  • AMD Processors with SVM and NPT support
  • Visual Studio 15.7.5 or later for compilation

Note that emulation of NTP in VMware is significantly slow. To try out SimpleSvmHook on VMware, set SIMPLESVMHOOK_SINGLE_HOOK to 1 and recompile the driver.

Resources

simplesvmhook's People

Contributors

tandasat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

simplesvmhook's Issues

Win19041 R5-3500X BugCheck

It run into a bugcheck.

Microsoft (R) Windows Debugger Version 10.0.22621.755 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.


Loading Dump File [C:\Windows\Minidump\012323-13015-01.dmp]
Mini Kernel Dump File: Only registers and stack trace are available

Symbol search path is: srv*
Executable search path is: 
Windows 10 Kernel Version 19041 MP (6 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Machine Name:
Kernel base = 0xfffff804`10400000 PsLoadedModuleList = 0xfffff804`1102a310
Debug session time: Mon Jan 23 00:23:18.773 2023 (UTC + 8:00)
System Uptime: 0 days 0:22:39.505
Loading Kernel Symbols
..

Press ctrl-c (cdb, kd, ntsd) or ctrl-break (windbg) to abort symbol loads that take too long.
Run !sym noisy before .reload to track down problems loading symbols.

.............................................................
................................................................
................................................................
.......
Loading User Symbols
Loading unloaded module list
.....
For analysis of this file, run !analyze -v
3: kd> !analyze -v
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

KERNEL_SECURITY_CHECK_FAILURE (139)
A kernel component has corrupted a critical data structure.  The corruption
could potentially allow a malicious user to gain control of this machine.
Arguments:
Arg1: 0000000000000004, The thread's stack pointer was outside the legal stack
	extents for the thread.
Arg2: ffffd200a22f7510, Address of the trap frame for the exception that caused the BugCheck
Arg3: ffffd200a22f7468, Address of the exception record for the exception that caused the BugCheck
Arg4: 0000000000000000, Reserved

Debugging Details:
------------------

*** WARNING: Unable to verify timestamp for SimpleSvmHook.sys

KEY_VALUES_STRING: 1

    Key  : Analysis.CPU.mSec
    Value: 1718

    Key  : Analysis.DebugAnalysisManager
    Value: Create

    Key  : Analysis.Elapsed.mSec
    Value: 4457

    Key  : Analysis.Init.CPU.mSec
    Value: 1015

    Key  : Analysis.Init.Elapsed.mSec
    Value: 52591

    Key  : Analysis.Memory.CommitPeak.Mb
    Value: 89

    Key  : FailFast.Name
    Value: INCORRECT_STACK

    Key  : FailFast.Type
    Value: 4


FILE_IN_CAB:  012323-13015-01.dmp

DUMP_FILE_ATTRIBUTES: 0x8
  Kernel Generated Triage Dump

BUGCHECK_CODE:  139

BUGCHECK_P1: 4

BUGCHECK_P2: ffffd200a22f7510

BUGCHECK_P3: ffffd200a22f7468

BUGCHECK_P4: 0

TRAP_FRAME:  48bc75de3b490005 -- (.trap 0x48bc75de3b490005)
Unable to read trap frame at 48bc75de`3b490005

EXCEPTION_RECORD:  ffffd200a22f7468 -- (.exr 0xffffd200a22f7468)
ExceptionAddress: fffff8041084ea79 (nt!RtlpGetStackLimitsEx+0x00000000001c9dd9)
   ExceptionCode: c0000409 (Security check failure or stack buffer overrun)
  ExceptionFlags: 00000001
NumberParameters: 1
   Parameter[0]: 0000000000000004
Subcode: 0x4 FAST_FAIL_INCORRECT_STACK 

BLACKBOXBSD: 1 (!blackboxbsd)


BLACKBOXNTFS: 1 (!blackboxntfs)


BLACKBOXWINLOGON: 1

CUSTOMER_CRASH_COUNT:  1

PROCESS_NAME:  crossfire.exe

ERROR_CODE: (NTSTATUS) 0xc0000409 - The system detected an overrun of a stack-based buffer in this application. This overrun could potentially allow a malicious user to gain control of this application.

EXCEPTION_CODE_STR:  c0000409

EXCEPTION_PARAMETER1:  0000000000000004

EXCEPTION_STR:  0xc0000409

STACK_TEXT:  
ffffd200`a22f71e8 fffff804`10805e69     : 00000000`00000139 00000000`00000004 ffffd200`a22f7510 ffffd200`a22f7468 : nt!KeBugCheckEx
ffffd200`a22f71f0 fffff804`10806290     : 89481024`6c894808 20ec8348`57182474 33002b8d`c90d8d48 8b48ff98`3fe2e8db : nt!KiBugCheckDispatch+0x69
ffffd200`a22f7330 fffff804`10804623     : 840f07e8`83c38b00 7401e883`0000008e e8835674`01e88372 1e7401e8`833a7401 : nt!KiFastFailDispatch+0xd0
ffffd200`a22f7510 fffff804`1084ea79     : ffffd200`a22f7920 ffffbc0e`8c5f7bd8 ffffd200`a22f7710 00000000`00000000 : nt!KiRaiseSecurityCheckFailure+0x323
ffffd200`a22f76a0 fffff804`10684e71     : ffffd200`a22f7920 00000000`00000000 00000000`00000000 00000000`00000003 : nt!RtlpGetStackLimitsEx+0x1c9dd9
ffffd200`a22f76d0 fffff804`10683ce6     : ffffbc0e`8c5f7bd8 ffffd200`a22f7e20 ffffbc0e`8c5f7bd8 ffffbc0e`8ee5bec0 : nt!RtlDispatchException+0xe1
ffffd200`a22f78f0 fffff804`107f4d32     : 6857baff`fffc77e8 6c4ee8cf`8b486165 48bc75de`3b490005 246c8b48`30245c8b : nt!KiDispatchException+0x186
ffffd200`a22f7fb0 fffff804`107f4d00     : fffff804`10805fa5 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KxExceptionDispatchOnExceptionStack+0x12
ffffbc0e`8c5f7a98 fffff804`10805fa5     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiExceptionDispatchOnExceptionStackContinue
ffffbc0e`8c5f7aa0 fffff804`10801ce0     : 00000000`02bf0000 00000000`00000001 00000007`fb279000 fffff804`206018f2 : nt!KiExceptionDispatch+0x125
ffffbc0e`8c5f7c80 fffff804`20606488     : ffffbc0e`8903ca50 fffff804`206033af fffff804`10db2030 fffff804`206067fc : nt!KiGeneralProtectionFault+0x320
ffffbc0e`8c5f7e10 ffffbc0e`8903ca50     : fffff804`206033af fffff804`10db2030 fffff804`206067fc 40000001`00000000 : SimpleSvmHook+0x6488
ffffbc0e`8c5f7e18 fffff804`206033af     : fffff804`10db2030 fffff804`206067fc 40000001`00000000 00000001`00870f10 : 0xffffbc0e`8903ca50
ffffbc0e`8c5f7e20 fffff804`10db202f     : fffff804`206067fc 40000001`00000000 00000001`00870f10 fffff804`20609060 : SimpleSvmHook+0x33af
ffffbc0e`8c5f7e28 fffff804`206067fc     : 40000001`00000000 00000001`00870f10 fffff804`20609060 00000001`00000015 : nt!ExFreePool+0x1f
ffffbc0e`8c5f7e30 40000001`00000000     : 00000001`00870f10 fffff804`20609060 00000001`00000015 00000000`0000020c : SimpleSvmHook+0x67fc
ffffbc0e`8c5f7e38 00000001`00870f10     : fffff804`20609060 00000001`00000015 00000000`0000020c fffff804`20606641 : 0x40000001`00000000
ffffbc0e`8c5f7e40 fffff804`20609060     : 00000001`00000015 00000000`0000020c fffff804`20606641 ffffbc0e`8c5f2000 : 0x00000001`00870f10
ffffbc0e`8c5f7e48 00000001`00000015     : 00000000`0000020c fffff804`20606641 ffffbc0e`8c5f2000 ffffbc0e`8c5f7eb0 : SimpleSvmHook+0x9060
ffffbc0e`8c5f7e50 00000000`0000020c     : fffff804`20606641 ffffbc0e`8c5f2000 ffffbc0e`8c5f7eb0 00000000`00000000 : 0x00000001`00000015
ffffbc0e`8c5f7e58 fffff804`20606641     : ffffbc0e`8c5f2000 ffffbc0e`8c5f7eb0 00000000`00000000 00000000`00000000 : 0x20c
ffffbc0e`8c5f7e60 ffffbc0e`8c5f2000     : ffffbc0e`8c5f7eb0 00000000`00000000 00000000`00000000 00000000`00000000 : SimpleSvmHook+0x6641
ffffbc0e`8c5f7e68 ffffbc0e`8c5f7eb0     : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : 0xffffbc0e`8c5f2000
ffffbc0e`8c5f7e70 00000000`00000000     : 00000000`00000000 00000000`00000000 00000000`00000000 00000001`00000000 : 0xffffbc0e`8c5f7eb0


SYMBOL_NAME:  SimpleSvmHook+6488

MODULE_NAME: SimpleSvmHook

IMAGE_NAME:  SimpleSvmHook.sys

STACK_COMMAND:  .cxr; .ecxr ; kb

BUCKET_ID_FUNC_OFFSET:  6488

FAILURE_BUCKET_ID:  0x139_MISSING_GSFRAME_SimpleSvmHook!unknown_function

OSPLATFORM_TYPE:  x64

OSNAME:  Windows 10

FAILURE_ID_HASH:  {fc016bc3-df79-ffa1-17aa-7b22dbcf9962}

Followup:     MachineOwner
---------

It seems that it crashed at [VmmMain.cpp][Line:250]

SYSTEM_THREAD_EXCEPTION_NOT_HANDLED Win10 20H2 Ryzen5 3600

Just tried to run the driver with no modifications at all and got BSOD. According to log file it stops at "Start virtualizing the all processors."

SYSTEM_THREAD_EXCEPTION_NOT_HANDLED_M (1000007e)
This is a very common bugcheck. Usually the exception address pinpoints
the driver/function that caused the problem. Always note this address
as well as the link date of the driver/image that contains this address.
Some common problems are exception code 0x80000003. This means a hard
coded breakpoint or assertion was hit, but this system was booted
/NODEBUG. This is not supposed to happen as developers should never have
hardcoded breakpoints in retail code, but ...
If this happens, make sure a debugger gets connected, and the
system is booted /DEBUG. This will let us see why this breakpoint is
happening.
Arguments:
Arg1: ffffffffc0000005, The exception code that was not handled
Arg2: fffff804174112cb, The address that the exception occurred at
Arg3: fffffe0aaa85a338, Exception Record Address
Arg4: fffffe0aaa859b70, Context Record Address
Debugging Details:
WARNING: Unable to verify timestamp for SimpleSvmHook.sys
WARNING: Unable to verify checksum for win32k.sys
KEY_VALUES_STRING: 1
Key : AV.Dereference
Value: NullPtr
Key : AV.Fault
Value: Read
Key : Analysis.CPU.mSec
Value: 4780
Key : Analysis.DebugAnalysisProvider.CPP
Value: Create: 8007007e on DESKTOP-5RJB31R
Key : Analysis.DebugData
Value: CreateObject
Key : Analysis.DebugModel
Value: CreateObject
Key : Analysis.Elapsed.mSec
Value: 27611
Key : Analysis.Memory.CommitPeak.Mb
Value: 83
Key : Analysis.System
Value: CreateObject
Key : WER.OS.Branch
Value: vb_release
Key : WER.OS.Timestamp
Value: 2019-12-06T14:06:00Z
Key : WER.OS.Version
Value: 10.0.19041.1
ADDITIONAL_XML: 1
OS_BUILD_LAYERS: 1
BUGCHECK_CODE: 7e
BUGCHECK_P1: ffffffffc0000005
BUGCHECK_P2: fffff804174112cb
BUGCHECK_P3: fffffe0aaa85a338
BUGCHECK_P4: fffffe0aaa859b70
EXCEPTION_RECORD: fffffe0aaa85a338 -- (.exr 0xfffffe0aaa85a338)
ExceptionAddress: fffff804174112cb (SimpleSvmHook+0x00000000000012cb)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 0000000000000000
Parameter[1]: 0000000000000000
Attempt to read from address 0000000000000000
CONTEXT: fffffe0aaa859b70 -- (.cxr 0xfffffe0aaa859b70)
rax=0000000000000000 rbx=0000000000001000 rcx=0000000000000000
rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000
rip=fffff804174112cb rsp=fffffe0aaa85a570 rbp=000ffffffffff000
r8=ffffd70000000000 r9=0000007ffffffff8 r10=0000000000000001
r11=ffffd76bb5dae000 r12=ffffc701f98c9fec r13=ffffc701f98c9e50
r14=ffffc701f80ff000 r15=ffffc701f5e023a0
iopl=0 nv up ei pl zr na po nc
cs=0010 ss=0000 ds=002b es=002b fs=0053 gs=002b efl=00050246
SimpleSvmHook+0x12cb:
fffff804174112cb f604c801 test byte ptr [rax+rcx*8],1 ds:002b:0000000000000000=??
Resetting default scope
BLACKBOXBSD: 1 (!blackboxbsd)
BLACKBOXNTFS: 1 (!blackboxntfs)
BLACKBOXPNP: 1 (!blackboxpnp)
BLACKBOXWINLOGON: 1
CUSTOMER_CRASH_COUNT: 1
PROCESS_NAME: System
READ_ADDRESS: fffff8040a4fb390: Unable to get MiVisibleState
Unable to get NonPagedPoolStart
Unable to get NonPagedPoolEnd
Unable to get PagedPoolStart
Unable to get PagedPoolEnd
fffff8040a40f340: Unable to get Flags value from nt!KdVersionBlock
fffff8040a40f340: Unable to get Flags value from nt!KdVersionBlock
unable to get nt!MmSpecialPagesInUse
0000000000000000
ERROR_CODE: (NTSTATUS) 0xc0000005 - 0x%p 0x%p. %s.
EXCEPTION_CODE_STR: c0000005
EXCEPTION_PARAMETER1: 0000000000000000
EXCEPTION_PARAMETER2: 0000000000000000
EXCEPTION_STR: 0xc0000005
STACK_TEXT:
fffffe0aaa85a570 0000000000001000 : 000000004d565353 ffffc70100000000 0000000000000000 ffffc701f5e023a0 : SimpleSvmHook+0x12cb
fffffe0aaa85a578 000000004d565353 : ffffc70100000000 0000000000000000 ffffc701f5e023a0 fffffe0aaa85a760 : 0x1000
fffffe0aaa85a580 ffffc70100000000 : 0000000000000000 ffffc701f5e023a0 fffffe0aaa85a760 0000000000000001 : 0x4d565353
fffffe0aaa85a588 0000000000000000 : ffffc701f5e023a0 fffffe0aaa85a760 0000000000000001 fffff80417411ab3 : 0xffffc701`00000000
SYMBOL_NAME: SimpleSvmHook+12cb
MODULE_NAME: SimpleSvmHook
IMAGE_NAME: SimpleSvmHook.sys
STACK_COMMAND: .cxr 0xfffffe0aaa859b70 ; kb
BUCKET_ID_FUNC_OFFSET: 12cb
FAILURE_BUCKET_ID: AV_SimpleSvmHook!unknown_function
OS_VERSION: 10.0.19041.1
BUILDLAB_STR: vb_release
OSPLATFORM_TYPE: x64
OSNAME: Windows 10
FAILURE_ID_HASH: {6486c827-0461-632e-3e20-f9875ce0c768}
Followup: MachineOwner

Performance problem

hi, do you have any suggestions how to improve the performance?
it make me very lag even on a real computer
i think its VM exits make lag, any idea?

Remove trapping #BP for handler?

On the page with hook code, you used a byte CC to result trapping #BP to VMM. This comes to extra cost by unnecessary VM-Exit. The hook code can be jmp instruction to improve performance, decreasing the times of VM-Exit.
On Win64, you may use push-mov-xchg-ret as hook code. The opcode looks like the following:
50 48 B8 XX XX XX XX XX XX XX XX 48 87 04 24 C3
The opcodes are exactly:

push rax 
mov rax, proxy
xchg [rsp],rax
ret

On Win32, you may use jmp rel32 as hook code (E9 XX XX XX XX).

This hook code seems long (16 bytes on Win64, 5 bytes on Win32) but does not matter if we are hooking functions compiled by Microsoft Compilers because function addresses are normally 16-byte aligned.

This may also apply on EPT-protected stealth hook on Intel processors. As read-violation comes, set to be readable but not executable. As execute-violation comes, set to be executable but unreadable.

Checkout my project NoirVisor. I made this come alive since January 2019, but Intel EPT only. I have not ported this to AMD machines yet.
https://github.com/Zero-Tang/NoirVisor/blob/master/src/xpf_core/windows/hooks.c#L136
https://github.com/Zero-Tang/NoirVisor/blob/master/src/svm_core/readme.md#stealth-inline-hook-algorithm

Hello, my senior

Hello, my senior, after reading the NPT part of your simplesvmhook source code, I found that memory hiding is different from Intel's EPT. Intel uses read bit to partition. I checked the AMD manual and found that read bit cannot be set to control read. You added NPT when dealing with NPT_ Is the state ntpstate structure increased because amd has no read bit?

Windows 2004 - Ryzen 7 2700X - BugCheck

Hi, I am experiencing something similar to #2.

Context:

  • I am manually mapping a kernel driver based on SimpleSvmHook (nearly no modification except adding stuff in entry point).
  • I use a physical machine
  • If I run the driver on a VMware vm, no bugcheck is occuring
  • QUITE STRANGE: If I build the driver with NO optimizations, it work 3/5 times (I can get in windows and monitor QuerySys calls, and a similar bugcheck occur randomly after some time).

Below is the Windbg summary of the memory dump you can download by clicking this link

Microsoft (R) Windows Debugger Version 10.0.19528.1000 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.


Loading Dump File [C:\WINDOWS\MEMORY.DMP]
Kernel Bitmap Dump File: Kernel address space is available, User address space may not be available.


************* Path validation summary **************
Response                         Time (ms)     Location
Deferred                                       srv*
Deferred                                       SRV*\C:\Symbols*http://msdl.microsoft.com/download/symbols
Symbol search path is: srv*;SRV*\C:\Symbols*http://msdl.microsoft.com/download/symbols
Executable search path is: 
Windows 10 Kernel Version 19041 MP (16 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS Personal
19041.1.amd64fre.vb_release.191206-1406
Machine Name:
Kernel base = 0xfffff806`62800000 PsLoadedModuleList = 0xfffff806`6342a310
Debug session time: Fri Sep  4 18:39:47.481 2020 (UTC + 2:00)
System Uptime: 0 days 0:00:11.128
Loading Kernel Symbols
...............................................................
................................................................
................................................................
...........
Loading User Symbols
PEB is paged out (Peb.Ldr = 00000000`00227018).  Type ".hh dbgerr001" for details
Loading unloaded module list
.........
For analysis of this file, run !analyze -v
nt!KeBugCheckEx:
fffff806`62bddb60 48894c2408      mov     qword ptr [rsp+8],rcx ss:0018:ffffd787`7a0dad30=0000000000000139
3: kd> !analyze -v
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

KERNEL_SECURITY_CHECK_FAILURE (139)
A kernel component has corrupted a critical data structure.  The corruption
could potentially allow a malicious user to gain control of this machine.
Arguments:
Arg1: 0000000000000004, The thread's stack pointer was outside the legal stack
	extents for the thread.
Arg2: ffffd7877a0db050, Address of the trap frame for the exception that caused the bugcheck
Arg3: ffffd7877a0dafa8, Address of the exception record for the exception that caused the bugcheck
Arg4: 0000000000000000, Reserved

Debugging Details:
------------------


KEY_VALUES_STRING: 1

    Key  : Analysis.CPU.Sec
    Value: 2

    Key  : Analysis.DebugAnalysisProvider.CPP
    Value: Create: 8007007e on DESKTOP-JQK4JE6

    Key  : Analysis.DebugData
    Value: CreateObject

    Key  : Analysis.DebugModel
    Value: CreateObject

    Key  : Analysis.Elapsed.Sec
    Value: 2

    Key  : Analysis.Memory.CommitPeak.Mb
    Value: 61

    Key  : Analysis.System
    Value: CreateObject


ADDITIONAL_XML: 1

BUGCHECK_CODE:  139

BUGCHECK_P1: 4

BUGCHECK_P2: ffffd7877a0db050

BUGCHECK_P3: ffffd7877a0dafa8

BUGCHECK_P4: 0

TRAP_FRAME:  ffffd7877a0db050 -- (.trap 0xffffd7877a0db050)
NOTE: The trap frame does not contain all registers.
Some register values may be zeroed or incorrect.
rax=0000000000000000 rbx=0000000000000000 rcx=0000000000000000
rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000
rip=0000000000000000 rsp=0000000000000000 rbp=0000000000000000
 r8=0000000000000000  r9=0000000000000000 r10=0000000000000000
r11=0000000000000000 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0         nv up di pl nz na pe nc
00000000`00000000 ??              ???
Resetting default scope

EXCEPTION_RECORD:  ffffd7877a0dafa8 -- (.exr 0xffffd7877a0dafa8)
ExceptionAddress: fffff80662c87e85 (nt!RtlpGetStackLimitsEx+0x000000000014acc5)
   ExceptionCode: c0000409 (Security check failure or stack buffer overrun)
  ExceptionFlags: 00000001
NumberParameters: 1
   Parameter[0]: 0000000000000004
Subcode: 0x4 FAST_FAIL_INCORRECT_STACK 

BLACKBOXBSD: 1 (!blackboxbsd)


BLACKBOXNTFS: 1 (!blackboxntfs)


BLACKBOXWINLOGON: 1

PROCESS_NAME:  svchost.exe

WATSON_BKT_EVENT:  BEX

ERROR_CODE: (NTSTATUS) 0xc0000409 - Le syst me a d tect  la saturation de la m moire tampon dans cette application. Cette saturation pourrait permettre   un utilisateur mal intentionn  de prendre le contr le de cette application.

EXCEPTION_CODE_STR:  c0000409

EXCEPTION_PARAMETER1:  0000000000000004

EXCEPTION_STR:  0xc0000409

BAD_STACK_POINTER:  ffffd7877a0dad28

STACK_TEXT:  
ffffd787`7a0dad28 fffff806`62befa29 : 00000000`00000139 00000000`00000004 ffffd787`7a0db050 ffffd787`7a0dafa8 : nt!KeBugCheckEx
ffffd787`7a0dad30 fffff806`62befe50 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiBugCheckDispatch+0x69
ffffd787`7a0dae70 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiFastFailDispatch+0xd0


SYMBOL_NAME:  nt!KiFastFailDispatch+d0

MODULE_NAME: nt

IMAGE_NAME:  ntkrnlmp.exe

STACK_COMMAND:  .thread ; .cxr ; kb

BUCKET_ID_FUNC_OFFSET:  d0

FAILURE_BUCKET_ID:  0x139_MISSING_GSFRAME_STACKPTR_ERROR_nt!KiFastFailDispatch

OS_VERSION:  10.0.19041.1

BUILDLAB_STR:  vb_release

OSPLATFORM_TYPE:  x64

OSNAME:  Windows 10

FAILURE_ID_HASH:  {7b0febb5-6007-4f2b-3d38-57fef278d8d5}

Followup:     MachineOwner
---------

In my case, the memory dump doesn't give the full stack trace. But I managed to have some insight:

  • following the stack here is what I extracted

  • nt!RtlpGetStackLimitsEx

  • nt!nt!MiSetNonPagedPoolNoSteal

  • ??????????? wtf is MiQueuePinDriverAddressLong also? patchguard???

  • nt!MmGetPhysicalAddress

  • SimpleSvmHook!BuildNestedPageTableEntry

I really have no idea of what's going on and why this is happening from time to time.

Windows 1903 - Ryzen 3600 - Bugcheck issue

Hello Satoshi,

I've been trying to get SimpleSvmHook working with Windows 1903 with my Ryzen 3600. It seems after the system virtualizes, that it runs into an error:

For some reason it's not being set to:
NT_ASSERT(GuestContext->VpRegs->Rcx == IA32_MSR_EFER);

I think this is because an error is coming up. I ended up figure out which value GuestContext->VpRegs->Rcx contained:

0xc0002001

If we look at the AMD Manual:
image
image

So I'm thinking this is a MCA_STATUS error of some sort?

Here's a copy paste of the dump analysis:

Use !analyze -v to get detailed debugging information.

BugCheck 139, {4, fffff8028227c4f0, fffff8028227c448, 0}

*** WARNING: Unable to verify timestamp for win32k.sys
*** ERROR: Module load completed but symbols could not be loaded for win32k.sys
Probably caused by : memory_corruption

Followup: memory_corruption
---------

0: kd> !analyze -v
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

KERNEL_SECURITY_CHECK_FAILURE (139)
A kernel component has corrupted a critical data structure.  The corruption
could potentially allow a malicious user to gain control of this machine.
Arguments:
Arg1: 0000000000000004, The thread's stack pointer was outside the legal stack
	extents for the thread.
Arg2: fffff8028227c4f0, Address of the trap frame for the exception that caused the bugcheck
Arg3: fffff8028227c448, Address of the exception record for the exception that caused the bugcheck
Arg4: 0000000000000000, Reserved

Debugging Details:
------------------


TRAP_FRAME:  fffff8028227c4f0 -- (.trap 0xfffff8028227c4f0)
NOTE: The trap frame does not contain all registers.
Some register values may be zeroed or incorrect.
rax=ffff970419216000 rbx=0000000000000000 rcx=0000000000000004
rdx=ffff97041921c000 rsi=0000000000000000 rdi=0000000000000000
rip=fffff8027c64e2d3 rsp=fffff8028227c680 rbp=fffff8028227c6f0
 r8=ffff97041921c000  r9=fffff8028227c710 r10=ffff9889c9113080
r11=ffff9889d0efbe10 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0         nv up ei pl zr na po nc
nt!RtlpGetStackLimitsEx+0x12e557:
fffff802`7c64e2d3 cd29            int     29h
Resetting default scope

EXCEPTION_RECORD:  fffff8028227c448 -- (.exr 0xfffff8028227c448)
ExceptionAddress: fffff8027c64e2d3 (nt!RtlpGetStackLimitsEx+0x000000000012e557)
   ExceptionCode: c0000409 (Security check failure or stack buffer overrun)
  ExceptionFlags: 00000001
NumberParameters: 1
   Parameter[0]: 0000000000000004

CUSTOMER_CRASH_COUNT:  1

PROCESS_NAME:  System

CURRENT_IRQL:  2

ERROR_CODE: (NTSTATUS) 0xc0000409 - The system detected an overrun of a stack-based buffer in this application. This overrun could potentially allow a malicious user to gain control of this application.

EXCEPTION_CODE: (NTSTATUS) 0xc0000409 - The system detected an overrun of a stack-based buffer in this application. This overrun could potentially allow a malicious user to gain control of this application.

EXCEPTION_PARAMETER1:  0000000000000004

BUGCHECK_STR:  0x139

DEFAULT_BUCKET_ID:  CODE_CORRUPTION

ANALYSIS_VERSION: 6.3.9600.17336 (debuggers(dbg).150226-1500) amd64fre

EXCEPTION_STR:  0x0

LAST_CONTROL_TRANSFER:  from fffff8027c5d1ae9 to fffff8027c5bfcc0

FAULTING_THREAD:  0000000000000000

STACK_TEXT:  
fffff802`8227c1c8 fffff802`7c5d1ae9 : 00000000`00000139 00000000`00000004 fffff802`8227c4f0 fffff802`8227c448 : nt!KeBugCheckEx
fffff802`8227c1d0 fffff802`7c5d1f10 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiBugCheckDispatch+0x69
fffff802`8227c310 fffff802`7c5d02a5 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiFastFailDispatch+0xd0
fffff802`8227c4f0 fffff802`7c64e2d3 : fffff802`8227c930 ffff9889`d0efbbd8 00000001`00000010 00000000`00000000 : nt!KiRaiseSecurityCheckFailure+0x325
fffff802`8227c680 fffff802`7c4c2a11 : fffff802`8227c930 ffff9889`d0efbbd8 000004e8`fffffb30 000004d0`00000003 : nt!RtlpGetStackLimitsEx+0x12e557
fffff802`8227c6b0 fffff802`7c4c738e : ffff9889`d0efbbd8 fffff802`8227ce30 ffff9889`d0efbbd8 00000000`00000000 : nt!RtlDispatchException+0xc1
fffff802`8227c900 fffff802`7c5c0b42 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiDispatchException+0x16e
fffff802`8227cfb0 fffff802`7c5c0b10 : fffff802`7c5d1c16 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KxExceptionDispatchOnExceptionStack+0x12
ffff9889`d0efba98 fffff802`7c5d1c16 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiExceptionDispatchOnExceptionStackContinue
ffff9889`d0efbaa0 fffff802`7c5d05de : 00000000`02d6d000 00000000`00000001 00000001`e2afd000 fffff802`7d5f1892 : nt!KiExceptionDispatch+0x116
ffff9889`d0efbc80 fffff802`7d5f6251 : 00000001`cdd72900 fffff802`7d5f309f fffff802`7c76d0a0 fffff802`7d5f663b : nt!KiRaiseAssertion+0x31e
ffff9889`d0efbe10 fffff802`7d5f6480 : ffff9889`d0ef6000 ffff9889`d0efbeb0 00000000`00000000 00000000`00000000 : SimpleSvmHook!HandleMsrAccess+0x21 [C:\Code\SimpleSvmHook\SimpleSvmHook\VmmMain.cpp @ 176]
ffff9889`d0efbe60 fffff802`7d5f105e : ffff9889`d0ef6000 ffff9889`d0efbf50 00000000`00000000 00000000`00000000 : SimpleSvmHook!HandleVmExit+0xd0 [C:\Code\SimpleSvmHook\SimpleSvmHook\VmmMain.cpp @ 308]
ffff9889`d0efbed0 ffff9889`d0ef6000 : ffff9889`d0efbf50 00000000`00000000 00000000`00000000 00000000`00000000 : SimpleSvmHook!SvLaunchVm+0x5e [C:\Code\SimpleSvmHook\SimpleSvmHook\x64.asm @ 175]
ffff9889`d0efbed8 ffff9889`d0efbf50 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : 0xffff9889`d0ef6000
ffff9889`d0efbee0 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : 0xffff9889`d0efbf50


CHKIMG_EXTENSION: !chkimg -lo 50 -d !hal
    fffff8027c3602ca - hal!HalPerformEndOfInterrupt+1a
	[ 00:90 ]
    fffff8027c3603a7-fffff8027c3603a8  2 bytes - hal!HalPutScatterGatherList+67 (+0xdd)
	[ 48 ff:4c 8b ]
    fffff8027c3603ae-fffff8027c3603b1  4 bytes - hal!HalPutScatterGatherList+6e (+0x07)
	[ 0f 1f 44 00:e8 ed cc 40 ]
    fffff8027c3df8ec-fffff8027c3df8ed  2 bytes - hal!HalpCmcWorkerRoutine+3c
	[ 48 ff:4c 8b ]
    fffff8027c3df8f3-fffff8027c3df8f6  4 bytes - hal!HalpCmcWorkerRoutine+43 (+0x07)
	[ 0f 1f 44 00:e8 e8 85 0c ]
    fffff8027c3df90a-fffff8027c3df90b  2 bytes - hal!HalpCmcWorkerRoutine+5a (+0x17)
	[ 48 ff:4c 8b ]
    fffff8027c3df911-fffff8027c3df914  4 bytes - hal!HalpCmcWorkerRoutine+61 (+0x07)
	[ 0f 1f 44 00:e8 aa 17 15 ]
    fffff8027c3df928-fffff8027c3df929  2 bytes - hal!HalpCmcWorkerRoutine+78 (+0x17)
	[ 48 ff:4c 8b ]
    fffff8027c3df92f-fffff8027c3df932  4 bytes - hal!HalpCmcWorkerRoutine+7f (+0x07)
	[ 0f 1f 44 00:e8 7c df 07 ]
    fffff8027c3df977-fffff8027c3df978  2 bytes - hal!HalpCmcWorkerRoutine+c7 (+0x48)
	[ 48 ff:4c 8b ]
    fffff8027c3df97e-fffff8027c3df981  4 bytes - hal!HalpCmcWorkerRoutine+ce (+0x07)
	[ 0f 1f 44 00:e8 8d dc 07 ]
31 errors : !hal (fffff8027c3602ca-fffff8027c3df981)

MODULE_NAME: memory_corruption

IMAGE_NAME:  memory_corruption

FOLLOWUP_NAME:  memory_corruption

DEBUG_FLR_IMAGE_TIMESTAMP:  0

MEMORY_CORRUPTOR:  LARGE

STACK_COMMAND:  ~0s ; kb

FAILURE_BUCKET_ID:  MEMORY_CORRUPTION_LARGE

BUCKET_ID:  MEMORY_CORRUPTION_LARGE

ANALYSIS_SOURCE:  KM

FAILURE_ID_HASH_STRING:  km:memory_corruption_large

FAILURE_ID_HASH:  {e29154ac-69a4-0eb8-172a-a860f73c0a3c}

Followup: memory_corruption
---------

Seems that Rcx is set to something other than IA32_MSR_EFER (as talked about above)

image

image

I wasn't sure if there was some new changes with Ryzen 3000 series that need some tweaking or Ryzen Master on my system causing some issues etc.

Any suggestions? I appreciate any advice you give me, thank you.

CPUID-Interception minor problem

registers[3] |= CPUID_FN0000_0001_ECX_HYPERVISOR_PRESENT;

The problem is minor that highest bit was mistakenly set on edx. It is supposed to be placed on ecx register. You might want to fix your "SimpleSvm" repository as well: https://github.com/tandasat/SimpleSvm/blob/457259cf864937c0932b7482d696f5c1264d454b/SimpleSvm/SimpleSvm.cpp#L508
It should be corrected as registers[2] |= CPUID_FN0000_0001_ECX_HYPERVISOR_PRESENT;

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.