{"id":13508778,"url":"https://github.com/changeofpace/VivienneVMM","last_synced_at":"2025-03-30T11:32:50.042Z","repository":{"id":47117683,"uuid":"142777667","full_name":"changeofpace/VivienneVMM","owner":"changeofpace","description":"VivienneVMM is a stealthy debugging framework implemented via an Intel VT-x hypervisor.","archived":false,"fork":false,"pushed_at":"2020-09-07T19:17:54.000Z","size":8137,"stargazers_count":797,"open_issues_count":3,"forks_count":181,"subscribers_count":44,"default_branch":"master","last_synced_at":"2025-03-13T12:37:09.283Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/changeofpace.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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-07-29T16:40:47.000Z","updated_at":"2025-03-11T00:38:03.000Z","dependencies_parsed_at":"2022-08-12T13:11:40.963Z","dependency_job_id":null,"html_url":"https://github.com/changeofpace/VivienneVMM","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/changeofpace%2FVivienneVMM","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/changeofpace%2FVivienneVMM/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/changeofpace%2FVivienneVMM/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/changeofpace%2FVivienneVMM/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/changeofpace","download_url":"https://codeload.github.com/changeofpace/VivienneVMM/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246314015,"owners_count":20757453,"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":[],"created_at":"2024-08-01T02:00:58.283Z","updated_at":"2025-03-30T11:32:48.641Z","avatar_url":"https://github.com/changeofpace.png","language":"C++","readme":"VivienneVMM\n===========\n\nVivienneVMM is a stealthy debugging framework implemented via an Intel VT-x hypervisor. The VMM driver implements multiple breakpoint control managers which allow a user mode client to set, clear, and inspect the logs of VMM-backed breakpoints. These breakpoints are invisible to the guest.\n\nThis project is an extension of the [HyperPlatform](https://github.com/tandasat/HyperPlatform) framework by [tandasat](https://github.com/tandasat).\n\n\nWhat's New\n----------\n### [1.0.0] - 2020-08-02\n\nVivienneVMM 1.0.0 released. :birthday:\n\n#### Added\n- **Ept breakpoints**: a new breakpoint type with many advantages over the now deprecated Vivienne hardware breakpoint type.\n- New VivienneCL commands: **GetProcessInformation**, **QueryEptBpInfo**, **SetEptBpBasic**, **SetEptBpRegisters**, **SetEptBpKeyed**, **DisableEptBp**, **ClearEptBp**, **PrintEptBpLogHeader**, and **PrintEptBpLogElements**. See the VivienneCL [README](./VivienneCL/README.md) for more information.\n- Add extended information for many VivienneCL commands. Type 'help command_name' in the VivienneCL console to see a command's extended information.\n- Most VivienneCL commands now have an additional short name for ease of use.\n- New config options: **CFG_VIVIENNE_DEVICE_NAME**, **CFG_LOG_NUMBER_OF_PAGES**, **CFG_LOG_FLUSH_INTERVAL_MS**, and **CFG_LOG_APPEND_DATA_TO_EXISTING_LOG_FILE**. See the [config header file](./common/config.h) for more information.\n- Add a [CHANGELOG](./CHANGELOG.md) file.\n\n\nBreakpoint Control Manager\n--------------------------\nThe VivienneVMM driver contains two breakpoint control manager modules which implement their own style of breakpoint:\n\n#### Ept Breakpoint Manager\n* Implements **ept breakpoints** using extended page tables.\n* \\+ Ept breakpoints are undetectable by user mode processes in the guest.\n* \\+ Supports unlimited number of ept breakpoints.\n* \\- Only execution and data breakpoints are supported.\n* \\~ Data breakpoint events are processed as **faults** instead of **traps**.\n\n#### Hardware Breakpoint Manager\n* Implements **hardware breakpoints** by hooking the debug exception IDT vector and monitoring debug register accesses.\n* \\+ Faster than ept breakpoints.\n* \\- Susceptible to certain anti-debug techniques by user mode processes in the guest.\n\n\nEpt Breakpoint Manager\n----------------------\nThe ept breakpoint manager module implements ept breakpoints using Intel VT-x extended page tables (ept) and the monitor trap flag VM execution control.\n\n### Ept Breakpoints\n\nEpt breakpoints are effectively hardware breakpoints with the following differences:\n\n* Each processor can have an unlimited number of active ept breakpoints.\n* Only execution and data (read / write) breakpoints are supported.\n* Data breakpoint events are processed as **faults** instead of **traps**. i.e., When a data ept breakpoint condition is triggered the VMM logs the event before the read or write occurs in the guest.\n* Ept breakpoints cannot be detected by user mode processes in the guest. (See 'Warnings and Limitations')\n\nEach ept breakpoint has a corresponding ept breakpoint log.\n\n### Ept Breakpoint Log\nAn ept breakpoint log contains the \"breakpoint hit history\" for its corresponding ept breakpoint. The contents of the log depend on the ept breakpoint log type:\n\n#### Basic\nRecords each unique guest virtual address that triggers the breakpoint condition and its hit count. i.e., Traditional hardware breakpoint functionality. Can be used to discover addresses which read, write, and execute a target breakpoint address.\n\n#### General Register Context\nRecords the general purpose register context each time the guest triggers the breakpoint condition.\n\n#### Keyed Register Context\nSimilar to **General Register Context**, except that guest state is only recorded when the value in the **key register** is not already in the log.\n\n### Using Ept Breakpoints\n\nVivienneCL contains several commands for setting, disabling, clearing, and viewing the logs of ept breakpoints. The **SetEptBp\\*** commands install an ept breakpoint on all processors and return a log handle. This log handle is the primary input argument for the other ept breakpoint commands.\n\n#### Example\nThe following example uses ept breakpoint commands to recover decrypted data from a target process.\n\nGiven the following function, we want to know all possible values of the **DecryptedValue** variable:\n\n```C\nVOID\nEptBreakpointExample(\n    _In_ ULONG_PTR EncryptedValue\n)\n{\n    ULONG_PTR DecryptedValue = 0;\n\n    DecryptedValue = Decrypt(EncryptedValue);\n\n    // ...\n}\n```\n\nDisassembly:\n\n```\n;\n; ImageBase = 0x140000000\n;\n.text:0000000140001030     mov     [rsp+EncryptedValue], rcx\n.text:0000000140001035     sub     rsp, 38h\n.text:0000000140001039     mov     [rsp+38h+var_18], 0\n.text:0000000140001042     mov     rcx, [rsp+38h+EncryptedValue] ; EncryptedValue\n.text:0000000140001047     call    Decrypt(unsigned __int64)\n.text:0000000140001047\n.text:0000000140001047     ; rax contains the decrypted value\n.text:0000000140001047\n.text:000000014000104C     mov     [rsp+38h+var_18], rax\n;                          ...\n```\n\nSuppose that process \"Z\" is executing this function randomly. Assume that the process id of process Z is **5600** and the image base is **0x140000000**. We can use the **SetEptBpKeyed** command to log guest state whenever a unique value is returned from the **Decrypt** routine at **000000014000104C**:\n\nSet the ept breakpoint with **rax** as the **register key**:\n\n```\n\u003e SetEptBpKeyed 5600 e1 14000104C 10000 1 rax\nLog Handle: 1\n```\n\nWait a few seconds for process Z to execute the function then print the log elements.\n\n```\n\u003e PrintEptBpLogElements 1\nEPTBP Log #1 | PID: 5600, Address: 000000014000104C, BP: X , Status: Active, KeyedRegister RAX\n    NumberOfElements: 4, MaxIndex: 409\n    Elements:\n        0   rip: 000000014000104C flg: 0000000000010202\n            rax: 138582AFE1835301 rbx: 000007FEF03369F8 rbp: 0000000000000000 rsp: 000000000012FE70\n            rcx: FFFFFFFFFFFFFF7F rdx: 0000000000000000 r8:  000007FFFFFDE000 r9:  000007FEF0303BD0\n            rdi: 0000000000368120 rsi: 0000000000000000 r10: B0003A0D060A5F66 r11: 00003A0D067C9178\n            r12: 0000000000000000 r13: 0000000000000000 r14: 0000000000000000 r15: 0000000000000000\n\n        1   rip: 000000014000104C flg: 0000000000010202\n            rax: FFF83815FA800890 rbx: 000007FEF03369F8 rbp: 0000000000000000 rsp: 000000000012FE70\n            rcx: FFFFFFFFFFFFB123 rdx: 0000000000000000 r8:  000007FFFFFDE000 r9:  000007FEF0303BD0\n            rdi: 0000000000368120 rsi: 0000000000000000 r10: B0003A0D060A5F66 r11: 00003A0D067C9178\n            r12: 0000000000000000 r13: 0000000000000000 r14: 0000000000000000 r15: 0000000000000000\n\n        2   rip: 000000014000104C flg: 0000000000010202\n            rax: FFFFFFFFFFFFFFFF rbx: 000007FEF03369F8 rbp: 0000000000000000 rsp: 000000000012FE70\n            rcx: FFFFFFFFFFFFEDED rdx: 0000000000000000 r8:  000007FFFFFDE000 r9:  000007FEF0303BD0\n            rdi: 0000000000368120 rsi: 0000000000000000 r10: B0003A0D060A5F66 r11: 00003A0D067C9178\n            r12: 0000000000000000 r13: 0000000000000000 r14: 0000000000000000 r15: 0000000000000000\n\n        3   rip: 000000014000104C flg: 0000000000010202\n            rax: 00103350308F80CD rbx: 000007FEF03369F8 rbp: 0000000000000000 rsp: 000000000012FE70\n            rcx: FFFFFFFFFFFFDB89 rdx: 0000000000000000 r8:  000007FFFFFDE000 r9:  000007FEF0303BD0\n            rdi: 0000000000368120 rsi: 0000000000000000 r10: B0003A0D060A5F66 r11: 00003A0D067C9178\n            r12: 0000000000000000 r13: 0000000000000000 r14: 0000000000000000 r15: 0000000000000000\n```\n\nThe log output above contains a breakpoint header and an array of keyed register context log elements. Each element corresponds to an instance where process Z executed the instruction at **000000014000104C** with a unique value in the **rax** register.\n\nFrom this log, we can see that process Z used four unique decrypted values while our breakpoint was active: **138582AFE1835301**, **FFF83815FA800890**, **FFFFFFFFFFFFFFFF**, and **00103350308F80CD**.\n\nNow suppose that we are finished monitoring this function, but we want to continue debugging process Z. We can use the **DisableEptBp** command to uninstall the breakpoint while keeping the breakpoint log valid:\n\n```\n\u003e DisableEptBp 1\n\n```\n\nIf we print the log elements again then we see that the breakpoint is inactive:\n\n```\n\u003e PrintEptBpLogElements 1\nEPTBP Log #1 | PID: 5600, Address: 000000014000104C, BP: X , Status: Inactive, KeyedRegister RAX\n    NumberOfElements: 4, MaxIndex: 409\n    Elements:\n        0   rip: 000000014000104C flg: 0000000000010202\n            rax: 138582AFE1835301 rbx: 000007FEF03369F8 rbp: 0000000000000000 rsp: 000000000012FE70\n            rcx: FFFFFFFFFFFFFF7F rdx: 0000000000000000 r8:  000007FFFFFDE000 r9:  000007FEF0303BD0\n            rdi: 0000000000368120 rsi: 0000000000000000 r10: B0003A0D060A5F66 r11: 00003A0D067C9178\n            r12: 0000000000000000 r13: 0000000000000000 r14: 0000000000000000 r15: 0000000000000000\n\n        1   rip: 000000014000104C flg: 0000000000010202\n            rax: FFF83815FA800890 rbx: 000007FEF03369F8 rbp: 0000000000000000 rsp: 000000000012FE70\n            rcx: FFFFFFFFFFFFB123 rdx: 0000000000000000 r8:  000007FFFFFDE000 r9:  000007FEF0303BD0\n            rdi: 0000000000368120 rsi: 0000000000000000 r10: B0003A0D060A5F66 r11: 00003A0D067C9178\n            r12: 0000000000000000 r13: 0000000000000000 r14: 0000000000000000 r15: 0000000000000000\n\n        2   rip: 000000014000104C flg: 0000000000010202\n            rax: FFFFFFFFFFFFFFFF rbx: 000007FEF03369F8 rbp: 0000000000000000 rsp: 000000000012FE70\n            rcx: FFFFFFFFFFFFEDED rdx: 0000000000000000 r8:  000007FFFFFDE000 r9:  000007FEF0303BD0\n            rdi: 0000000000368120 rsi: 0000000000000000 r10: B0003A0D060A5F66 r11: 00003A0D067C9178\n            r12: 0000000000000000 r13: 0000000000000000 r14: 0000000000000000 r15: 0000000000000000\n\n        3   rip: 000000014000104C flg: 0000000000010202\n            rax: 00103350308F80CD rbx: 000007FEF03369F8 rbp: 0000000000000000 rsp: 000000000012FE70\n            rcx: FFFFFFFFFFFFDB89 rdx: 0000000000000000 r8:  000007FFFFFDE000 r9:  000007FEF0303BD0\n            rdi: 0000000000368120 rsi: 0000000000000000 r10: B0003A0D060A5F66 r11: 00003A0D067C9178\n            r12: 0000000000000000 r13: 0000000000000000 r14: 0000000000000000 r15: 0000000000000000\n```\n\nEpt breakpoints can have a significant performance cost because an ept violation VM exit occurs whenever the guest accesses the target page in a manner which matches the ept breakpoint condition. e.g., If we set an execute ept breakpoint on a system call stub in ntdll.dll then the guest will VM exit each time a processor executes an instruction inside the page that contains the breakpointed address, regardless of process context. Disabling an ept breakpoint removes its performance cost.\n\nWe can use the **QueryEptBpInfo** command to get a list of all ept breakpoints on the system:\n\n```\n\u003e QueryEptBpInfo\nEpt Breakpoint Information\n    0 active breakpoints.\n    1 inactive breakpoints.\n    0 locked pages.\n    0 hooked pages.\n    Breakpoints:\n        Handle   PID           Address  BP      Status          LogType   #Elements    MaxIndex\n        ---------------------------------------------------------------------------------------\n             1  5600  000000014000104C  X     Inactive    KeyedRegister           4         409\n```\n\nFinally, we can release the resources for an ept breakpoint log using the **ClearEptBp** command:\n\n```\n\u003e ClearEptBp 1\n\n```\n\nSee the VivienneCL [README](./VivienneCL/README.md) for more command information.\n\n### Warnings and Limitations\n\n* Currently only user mode clients are supported. Kernel support is in development.\n* Unhandled edge cases may reveal the presence of ept breakpoints to user mode processes in the guest. If this occurs then please create an issue on github so that we can fix it.\n\n\nHardware Breakpoint Manager\n---------------------------\nThe hardware breakpoint manager is deprecated since the release of the ept breakpoint manager. Developers can enable the hardware breakpoint manager by modifying the [config header](./common/config.h).\n\nLegacy documentation can be found [here](./Documentation/HardwareBreakpointManager.md).\n\n\nProject Structure\n-----------------\n\n### VivienneVMM\nThe core driver project containing the Vivienne virtual machine monitor.\n\n### VivienneCL\nA command line VivienneVMM client which makes use of the breakpoint control interfaces. A simple debugger.\n\n### VivienneTests\nVivienneVMM test cases.\n\nThis project uses [HyperPlatform](https://github.com/tandasat/HyperPlatform) as a git subtree with prefix='VivienneVMM/HyperPlatform'. We subtree the project instead of using a git submodule because we must modify HyperPlatform files to implement VivienneVMM features. This allows us to merge HyperPlatform updates from upstream with minimal merge conflicts.\n\nThe following list of console commands are an example of how to pull HyperPlatform updates into a local VivienneVMM repository:\n\n    # Remote configuration.\n    cd VivienneVMM/\n    git checkout master\n    git remote add upstream https://github.com/tandasat/HyperPlatform.git\n    git remote set-url --push upstream DISABLED\n\n    # Pulling updates.\n    cd VivienneVMM/\n    git fetch upstream\n    git subtree pull --prefix=VivienneVMM/HyperPlatform upstream master\n\n\nRelated Projects\n----------------\n\n* HyperPlatform\n* https://github.com/tandasat/HyperPlatform\n\nHyperPlatform is an Intel VT-x based hypervisor (a.k.a. virtual machine monitor) aiming to provide a thin platform for research on Windows. HyperPlatform is capable of monitoring a wide range of events, including but not limited to, access to virtual/physical memory and system registers, occurrences of interrupts and execution of certain instructions.\n\n* DdiMon\n* https://github.com/tandasat/DdiMon\n\nDdiMon is a hypervisor performing inline hooking that is invisible to a guest (ie, any code other than DdiMon) by using extended page table (EPT).\n\n\nNotes\n-----\n\n* This project was developed and tested on Windows 7 x64 SP1.\n* All binaries are PatchGuard safe on Windows 7.\n* x86 is not supported and WoW64 is untested.\n\n\nSpecial Thanks\n--------------\n\n* [tandasat](https://github.com/tandasat)\n* [dude719](https://github.com/dude719)\n","funding_links":[],"categories":["Research Projects","C++","others","Reverse Engineering"],"sub_categories":["AMD","Malware Articles and Sources"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchangeofpace%2FVivienneVMM","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchangeofpace%2FVivienneVMM","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchangeofpace%2FVivienneVMM/lists"}