• Stars
    star
    351
  • Rank 120,906 (Top 3 %)
  • Language
    C++
  • License
    MIT License
  • Created over 6 years ago
  • Updated over 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

SimpleSvmHook is a research purpose hypervisor for Windows on AMD processors.

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

More Repositories

1

HyperPlatform

Intel VT-x based hypervisor aiming to provide a thin VM-exit filtering platform on Windows.
C++
1,519
star
2

DdiMon

Monitoring and controlling kernel API calls with stealth hook using EPT
C++
1,146
star
3

Hypervisor-101-in-Rust

The materials of "Hypervisor 101 in Rust", a one-day long course, to quickly learn hardware-assisted virtualization technology and its application for high-performance fuzzing on Intel/AMD processors.
Rust
981
star
4

MiniVisorPkg

The research UEFI hypervisor that supports booting an operating system.
C
546
star
5

SimpleSvm

A minimalistic educational hypervisor for Windows on AMD processors.
C++
317
star
6

PgResarch

PatchGuard Research
C++
288
star
7

ExploitCapcom

This is a standalone exploit for a vulnerable feature in Capcom.sys
C++
280
star
8

MemoryMon

Detecting execution of kernel memory where is not backed by any image file
C++
252
star
9

DotNetHooking

Sample use cases of the .NET native code hooking technique
C#
201
star
10

barevisor

A bare minimum hypervisor on AMD and Intel processors for learners.
Rust
189
star
11

scripts_for_RE

Python scripts for reverse engineering.
Python
178
star
12

GuardMon

Hypervisor based tool for monitoring system register accesses.
C++
140
star
13

UefiVarMonitor

The runtime DXE driver monitoring access to the UEFI variables by hooking the runtime service table.
C
136
star
14

SmmExploit

The report and the exploit of CVE-2021-26943, the kernel-to-SMM local privilege escalation vulnerability in ASUS UX360CA BIOS version 303.
133
star
15

hvext

The Windbg extension that implements commands helpful to study Hyper-V on Intel processors.
JavaScript
126
star
16

EopMon

Elevation of privilege detector based on HyperPlatform
C++
117
star
17

Sushi

a Japanese food keeps you sane
C++
117
star
18

findpg

Windbg extension to find PatchGuard pages
C++
116
star
19

UEFI-BIOS-Security

Security Camp 2021 & GCC 2022
111
star
20

WinIoCtlDecoder

IDA Plugin which decodes Windows Device I/O control code into DeviceType, FunctionCode, AccessType and MethodType.
Python
106
star
21

FU_Hypervisor

A hypervisor hiding user-mode memory using EPT
C
104
star
22

WPBT-Builder

The simple UEFI application to create a Windows Platform Binary Table (WPBT) from the UEFI shell.
C
100
star
23

HelloSmm

This is an instruction to run your own SMM code.
C
100
star
24

DebugLogger

A software driver that lets you log kernel-mode debug output into a file on Windows.
C++
97
star
25

Hello-VT-rp

A simple hypervisor demonstrating the use of the Intel VT-rp (redirect protection) technology.
Rust
91
star
26

kraft_dinner

Tool to dump UEFI runtime drivers implementing runtime services for Windows
C
90
star
27

HelloAmdHvPkg

HelloAmdHvPkg is a type-1 research hypervisor for AMD processors.
C
86
star
28

CVE-2023-36427

Report and exploit of CVE-2023-36427
C++
86
star
29

Scavenger

A minifilter driver preserves all modified and deleted files.
C
77
star
30

RemoteWriteMonitor

A tool to help malware analysts tell that the sample is injecting code into other process.
C++
74
star
31

meow

nyā
C++
70
star
32

HelloIommuPkg

The sample DXE runtime driver demonstrating how to program DMA remapping.
C
57
star
33

DumpVTable

Generates a Python script to give public interface names in an ActiveX file to an IDB file.
C++
47
star
34

DrvLoader

A command line tool to load and unload a device driver.
C++
42
star
35

CVE-2022-25949

A years-old exploit of a local EoP vulnerability in Kingsoft Antivirus KWatch Driver version 2009.3.17.77.
C++
35
star
36

cs_driver

A sample project for using Capstone from a driver in Visual Studio 2015
C
34
star
37

CVE-2024-21305

Report and exploit of CVE-2024-21305.
C++
30
star
38

CVE-2014-0816

CVE-2014-0816
C++
24
star
39

tandasat.github.io

HTML
17
star
40

hyperplatform_log_parser

User-mode program parsing logs created by HyperPlatform
C++
17
star
41

ProjectLoadTimeMonitor

The Visual Studio extension that measures load time of each project when a solution file is opened.
C#
16
star
42

recon2024_demo

Provides commands to read from and write to arbitrary kernel-mode memory for users with the Administrator privilege. HVCI compatible. No test signing mode is required.
C++
14
star
43

CheckSDL

A tool evaluates security configurations of a given PE based on SDL without source code
C++
12
star
44

ListWorkItems

Lists work items being queued currently.
C++
12
star
45

DeviceOpener

A command line tool to check if a specified device is accessible.
C++
10
star
46

List-UEFI-Configuration-Tables

List UEFI Configuration Tables
Rust
10
star
47

windbg_init

Windbg Init Script
9
star
48

ScopedResource

Scoped Resource - Generic RAII Wrapper for the Standard Library by Peter Sommerlad and Andrew L. Sandoval
C++
8
star
49

win32_debugout

Shows debug strings on DebubView from an attached process by win32_remote.exe.
C++
8
star
50

ping_vmm

A user-mode program knocking at HyperPlatform's "backdoor"
C++
7
star
51

SecRuntimeSample

A sample usege of SecRuntime.dll on Windows Phone
C++
4
star
52

blog

Ruby
4
star
53

CopyFiles

Copy files onto the IsolatedStorage so that you can download them using IsoStoreSpy.
C#
3
star
54

mylight

Using LED of Samsung Galaxy Ace S5830
Java
2
star
55

tandasat

2
star
56

shared

Manages files that are shared with multiple boxes.
Vim Script
1
star