{"id":21437087,"url":"https://github.com/tandasat/simplesvmhook","last_synced_at":"2025-04-07T09:18:37.922Z","repository":{"id":42077953,"uuid":"139285079","full_name":"tandasat/SimpleSvmHook","owner":"tandasat","description":"SimpleSvmHook is a research purpose hypervisor for Windows on AMD processors.","archived":false,"fork":false,"pushed_at":"2021-02-18T04:38:01.000Z","size":449,"stargazers_count":378,"open_issues_count":4,"forks_count":74,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-03-31T07:09:10.407Z","etag":null,"topics":["amd","driver","hypervisor","svm","virtual-machine","windows-kernel"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tandasat.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-06-30T22:40:24.000Z","updated_at":"2025-03-27T10:41:21.000Z","dependencies_parsed_at":"2022-09-17T06:42:15.460Z","dependency_job_id":null,"html_url":"https://github.com/tandasat/SimpleSvmHook","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tandasat%2FSimpleSvmHook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tandasat%2FSimpleSvmHook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tandasat%2FSimpleSvmHook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tandasat%2FSimpleSvmHook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tandasat","download_url":"https://codeload.github.com/tandasat/SimpleSvmHook/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247622983,"owners_count":20968575,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["amd","driver","hypervisor","svm","virtual-machine","windows-kernel"],"created_at":"2024-11-23T00:17:45.066Z","updated_at":"2025-04-07T09:18:37.900Z","avatar_url":"https://github.com/tandasat.png","language":"C++","readme":"SimpleSvmHook\n==============\n\nIntroduction\n-------------\n\nSimpleSvmHook is a research purpose hypervisor for Windows on AMD processors.\nIt hooks kernel mode functions and protects them from being detected using\nNested Page Tables (NPT), part of AMD Virtualization (AMD-V) technology.\n\nThis project is meant to serve as an example implementation of virtual machine\nintrospection (VMI) on AMD processors and highlight differences from similar\nVMI implementations on Intel processors.\n\nIf you already know about [DdiMon](https://github.com/tandasat/DdiMon), this is\nan AMD counterpart of it from the functionality perspective except few things\ndescribed below.\n\n\nOverview of Stealth Hook Implementation\n----------------------------------------\nA stealth hook is a type of hook that is not visible from the outside of the\nmonitor or inspector component. In the context of VMI, stealth hook is installed\nand managed by a hypervisor into guest code to redirect execution of specified\naddresses while being not easily detectable by the guest.\n\nOne of common ways to implement stealth hook within a hypervisor is to split\n“view” of memory for read/write and execute access from the guest using Second\nLevel Address Translation (SLAT), namely, Extended Page Table (EPT) on Intel\nand Nested Page Tables (NPT) for AMD processors.\n\nSLAT introduces one more address translation step, that is, translation from the\nguest physical address (GPA) to the system physical address (SPA). This\nessentially allows a hypervisor to set up a mapping of a virtual address in the\nguest and a backing physical memory address. The below diagram illustrates how\nSLAT can be configured and address translation will result in.\n\n    GPA              SPA     Memory Contents\n    -----------------------------------------\n    0x1000 –(SLAT)-\u003e 0xa000  ...\n    0x2000 –(SLAT)-\u003e 0xb000  48 89 54 24 10\n    ...\n\nSLAT can also configure permission of the GPA against the guest; for instance,\nGPA:0x2000 can be configured as readable/writable but not executable. When the\nguest attempts to access a GPA in a way not permitted by SLAT, the processor\ntriggers VM-exit so that a hypervisor can take necessary actions, such as\nupdating the permission or inject #GP into the guest.\n\nStealth hook is often implemented by leveraging those capabilities. Take DdiMon\nas an example, when the hypervisor installs stealth hook, it creates a copy of\nthe target page, sets 0xCC into the address to hook, then sets up EPT to make\nthe page execute-only (0xb000 in the below example).\n\n    GPA                 SPA     Memory Contents\n    --------------------------------------------\n    0x2000 –(EPT --X)-\u003e 0xb000  CC 89 54 24 10\n                        0xf000  48 89 54 24 10  (The copied page. Unused yet)\n    ...\n\nWhen the guest attempts to execute the address, the hypervisor:\n  1. traps #BP\n  2. changes the instruction pointer of the guest to our handler function\n  3. lets the guest run\n\nand when the guest attempts to read from or write to the address, the hypervisor:\n  1. traps VM-exit caused due to access violation\n  2. updates EPT to associate the address with the copied page, which does *not*\n     contain 0xCC, with the readable/writable permission\n\n    GPA                 SPA     Memory Contents\n    --------------------------------------------\n    0x2000 –(EPT RW-)\\  0xb000  CC 89 54 24 10\n                      -\u003e0xf000  48 89 54 24 10  (The copied page)\n    ...\n\n  3. single steps and lets the guest complete the read or write operation\n  4. updates EPT to revert the settings\n\n    GPA                 SPA     Memory Contents\n    --------------------------------------------\n    0x2000 –(EPT --X)-\u003e 0xb000  CC 89 54 24 10\n                        0xf000  48 89 54 24 10  (The copied page)\n    ...\n\n  5. lets the guest run\n\nThose operations allow the hypervisor to redirect execution of the guest while\nkeeping the hook invisible from the guest. Also, notice that EPT configurations\nare reverted to the original state, and the next execute or read/write access\ncan be handled in the same way.\n\nHowever, this cannot be implemented directly on AMD processors.\n\n\nImplementation on AMD Processors and Limitations\n-------------------------------------------------\n\nThe previously described technique cannot be implemented on AMD processors due\nto lack the execute-only permission.\n\nNPT, the AMD implementation of SLAT, does not permit a hypervisor to configure\nthe permission as execute-only because there is no bit to indicate whether the\npage is readable. To make the page executable, it must also be readable at the\nsame time. This limitation requires significant changes in a way to hide hooks.\n\nFirstly, a hypervisor needs to set the unmodified readable/writable page as the\ndefault association of the target page  (0xb000 in the below example).\n\n    GPA                 SPA     Memory Contents\n    --------------------------------------------\n    0x2000 –(NPT RW-)-\u003e 0xb000  48 89 54 24 10\n                        0xf000  CC 89 54 24 10  (The copied page. Unused yet)\n    ...\n\nThis introduces additional performance cost due to more frequent VM-exit (recall\nthat the address being hooked is code and much more likely accessed for\nexecution).\n\nSecondly, the hook has to remain visible in some situation. Let us see why.\n\nWhen the guest attempts to execute the address, the hypervisor:\n  1. traps VM-exit caused due to access violation\n  2. updates NPT to associate the address with the copied page, which contains\n     0xCC, with the readable/writable/executable permission.\n\n    GPA                 SPA     Memory Contents\n    --------------------------------------------\n    0x2000 –(NPT RWX)\\  0xb000  48 89 54 24 10\n                      -\u003e0xf000  CC 89 54 24 10  (The copied page)\n    ...\n\n  3. lets the guest run\n  4. traps #BP\n  5. changes the instruction pointer of the guest to our handler function\n\nNotice that while hook was executed, the hooked page remains readable with 0xCC.\n\nThis is a critical issue yet resolution is challenging because:\n  - the page cannot be non-readable while being executable because of the\n    limitation of NPT,\n  - the page contents cannot be reverted to the original contents since the\n    guest may execute the hooked address while 0xCC is removed, and\n  - AMD-V lacks the Monitor Trap Flag equivalent feature that could have been\n    used to overcome the second point.\n\nThe partial solution to this issue is to trap the guest when it attempts to\nexecute the outside of the hooked page, and then, hide 0xCC. This can be\nachieved by setting all pages but the hooked page non-executable, then, when the\nguest jumps out to the outside of the hooked page, the hypervisor:\n  1. traps VM-exit caused due to access violation\n  2. updates NPT to make all pages but the hooked page executable again\n  3. updates NPT to associate the hooked page with the unmodified page with the\n     readable/writable permission\n\n    GPA                 SPA     Memory Contents\n    --------------------------------------------\n    0x2000 –(NPT RW-)-\u003e 0xb000  48 89 54 24 10\n                        0xf000  CC 89 54 24 10  (The copied page)\n    ...\n\n  4. lets the guest run\n\nThis way, the hook remains invisible while the guest is executing any code\noutside of the hooked page. In other words, the guest can still see the hook\nwhile it is executing the same page as the hooked page. This may be a\nsignificant limitation if hook must be installed on code that may perform a\nself-integrity check, but it is unlikely a real issue if hook is installed\nagainst known kernel code such as NTOSKRNL and Win32k.\n\nThe other downside of this design is overhead of NTP manipulation. VM-exit, when\nthe guest jumps into and out from the hooked page, has non-negligible\nperformance penalty because the hypervisor must update multiple NPT entries to\nchange the executable permission of all pages.\n\nDelay in Windows boot time measured by Windows Performance Analyzer with the\ncurrent implementation was 20% on HP [EliteBook 725 G4](http://www8.hp.com/ca/en/products/laptops/product-detail.html?oid=11084766#!tab=models)\n(AMD A12 PRO-8830B), while it was only 9% with DdiMon on [Dell Latitude E6410](http://www.dell.com/us/en/business/notebooks/latitude-e6410/pd.aspx?refid=latitude-e6410\u0026cs=04\u0026s=bsd)\n(Intel Core i7-620M). Given that the tested AMD processor is almost the 7 years\nnewer model than the tested Intel processor and expected to have much more\noptimized implementation of AMD-V than that of VT-x on the old Intel processor,\nthis high number (20%) is likely because of the heavyweight VM-exit handling.\n\nWhile this overhead did not appear to be noticeable on normal load, it could be\nthe real issue depending on load, and possibly, the number of hooks installed.\n\n\nConclusion\n-----------\n\nThis project demonstrated that implementation of stealth hook on AMD processors\nwas possible with the caveat that hook had to remain visible from code in the\nsame page and that performance overhead introduced by the explained design was\nconsiderably higher than that of similar implementation on Intel processors.\n\nThose limitation can be ignored in some use cases such as instrumentation of\nknown kernel API for research, but could prevent researchers from developing\nhighly-stealth VMI tools and tools for performance sensitive environments.\n\n\nInstallation and Uninstallation\n--------------------------------\n\nTo build SimpleSvmHook from source code, clone full source code from GitHub with\nthe below command and compile it on a supported version of Visual Studio.\n\n    $ git clone https://github.com/tandasat/SimpleSvmHook.git\n\nYou have to enable test signing to install the driver before installing it. To\ndo that, open the command prompt with the administrator privilege and run the\nfollowing command, and then restart the system to activate the change:\n\n    \u003ebcdedit /set testsigning on\n\nTo install and uninstall the SimpleSvmHook driver, use the `sc` command. For\ninstallation and start:\n\n    \u003esc create SimpleSvmHook type= kernel binPath= C:\\Users\\user\\Desktop\\SimpleSvmHook.sys\n    \u003esc start SimpleSvmHook\n\nNote that the driver may fail to start due to failure to disassemble code for\nhooking. SimpleSvmHook can only handle known byte patterns (instructions) and\ndoes not attempt to disassemble unknown byte patterns. You can resolve such\nerrors by adding new patterns to the \"FindFirstInstruction\" function and\nrecompiling the driver.\n\nFor uninstallation:\n\n    \u003esc stop SimpleSvmHook\n    \u003esc delete SimpleSvmHook\n    \u003ebcdedit /deletevalue testsigning\n\n\nOutput\n-------\n\nAll debug output are saved in `C:\\Windows\\SimpleSvmHook.log`.\n\nThis screenshot shows example output from installed hooks as well as that those\nhooks are not visible from the system (the local kernel debugger).\n\n![HookInstalled](/Images/HookInstalled.png)\n\n\nSupported Platforms\n--------------------\n\n- Windows 10 x64 and Windows 7 x64\n- AMD Processors with SVM and NPT support\n- Visual Studio 15.7.5 or later for compilation\n\nNote that emulation of NTP in VMware is significantly slow. To try out\nSimpleSvmHook on VMware, set `SIMPLESVMHOOK_SINGLE_HOOK` to 1 and recompile the\ndriver.\n\n\nResources\n----------\n\n- SimpleSvm\n  - https://github.com/tandasat/SimpleSvm\n\n- DdiMon\n  - https://github.com/tandasat/DdiMon\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftandasat%2Fsimplesvmhook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftandasat%2Fsimplesvmhook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftandasat%2Fsimplesvmhook/lists"}