{"id":13546098,"url":"https://github.com/quarkslab/rewind","last_synced_at":"2026-02-03T10:38:44.311Z","repository":{"id":46627715,"uuid":"384121683","full_name":"quarkslab/rewind","owner":"quarkslab","description":"Snapshot-based coverage-guided windows kernel fuzzer","archived":false,"fork":false,"pushed_at":"2021-12-16T14:06:29.000Z","size":6350,"stargazers_count":309,"open_issues_count":2,"forks_count":30,"subscribers_count":10,"default_branch":"main","last_synced_at":"2024-11-03T14:35:02.586Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/quarkslab.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":"2021-07-08T12:46:23.000Z","updated_at":"2024-10-10T16:37:49.000Z","dependencies_parsed_at":"2022-09-09T13:01:16.542Z","dependency_job_id":null,"html_url":"https://github.com/quarkslab/rewind","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/quarkslab%2Frewind","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quarkslab%2Frewind/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quarkslab%2Frewind/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quarkslab%2Frewind/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/quarkslab","download_url":"https://codeload.github.com/quarkslab/rewind/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246860271,"owners_count":20845635,"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-01T12:00:31.469Z","updated_at":"2026-02-03T10:38:44.281Z","avatar_url":"https://github.com/quarkslab.png","language":"Rust","funding_links":[],"categories":["Vulnerability Assessment"],"sub_categories":["Fuzzing"],"readme":"# README\r\n\r\nRewind is a snapshot-based coverage-guided fuzzer targeting\r\nWindows kernel components.\r\n\r\nThe idea is to start from a snapshot of a live running system. This\r\nsnapshot is composed of the physical memory pages along with the state\r\nof the cpu.\r\n\r\nThis state is used to setup the initial state of a virtual cpu. By leveraging on-demand\r\npaging only the pages needed for the execution of the target function are read from the snapshot.\r\n\r\nBecause we use a dedicated virtual machine with only the physical memory pages useful for the execution of the target function, restoring a snapshot is fast.\r\n\r\nAs of now 2 backends are available:\r\n\r\n-  ``WHVP`` backend leverages WHVP (Windows Hypervisor Platform) API to\r\n   provide access to a Hyper-V partition. See\r\n   https://docs.microsoft.com/en-us/virtualization/api/hypervisor-platform/hypervisor-platform\r\n   for more details.\r\n-  ``Bochs`` backend leverages the Bochs emulator\r\n   (https://bochs.sourceforge.io/)\r\n\r\nA `KVM` backend is being developed and should be available soon.\r\n\r\nRewind provides 2 main features:\r\n- the ability to trace an arbitrary function\r\n- the ability to fuzz an arbitrary function\r\n\r\nIt also provides a basic TUI (Terminal User Interface) to report useful information regarding the fuzzing.\r\n\r\nIt has been tested on Windows and Linux (only bochs backend for linux for now).\r\n\r\n## Motivation\r\n\r\nI always enjoyed doing kernel vulnerability research specially on Windows kernel. The process\r\nalways involve a mix of static and dynamic analysis. Doing dynamic analysis can quickly become\r\ntedious. The cycle debug / crash / reboot / reset all breakpoints is slow and painful. When you\r\nwant to do some fuzzing, it often requires you to setup one or several virtual machines plus a\r\nkernel debugger and craft some ghetto scripts to handle crash detection...\r\n\r\nDoing snapshot with virtual machines helps but it's slow.\r\n\r\nDuring 2018, Microsoft introduced a new set of API named Windows Hypervisor Platform (WHVP). These\r\nAPI allow to setup a partition (VM in hyper-V lingua) with some virtual processors and to have a\r\ncontrol on the VM exits occurring in the virtual machine. It's almost like having your own\r\nVM-exit handler in userland. Quite handy to do useful things, for example\r\n[Simpleator](https://github.com/ionescu007/Simpleator)\r\nor [applepie](https://github.com/gamozolabs/applepie).\r\n\r\nSo I started to play with WHVP and made a first PoC allowing me to execute\r\nin a Hyper-V partition some shellcode. It was written in Python and quite slow. This first PoC\r\nevolved quite quickly to some kind of snapshot-based tracer. I wanted to have something to\r\nbootstrap the virtual CPU and quite easy to setup. So since I was already using a kernel debugger\r\nto play with my target, I decided to use kernel dumps made with WinDbg as my snapshot. With that I just\r\nneeded to setup a partition with a virtual cpu. The virtual cpu context is set with the context\r\ntaken from the dump. Whenever the virtual cpu needs a physical page I use the ones from the dump.\r\n\r\nWith this I was able to fork the state of the dump into a partition and then resume execution. \r\nIt allowed me to easily trace the execution of my target function. By modifying the arguments and\r\nreverting the memory state of the partition it was also really easy to fuzz the target.\r\n\r\nThis work was presented at SSTIC conference in [2020](https://www.sstic.org/2020/presentation/fuzz_and_profit_with_whvp/) and\r\nreleased on [github](https://github.com/quarkslab/whvp).\r\n\r\nThe tool implements 2 possibilities to obtain the coverage. The first one leverages the classical TF (Trap Flag) to have INT1 interruptions on every instruction. \r\nIt requires to modify the target and it's slow. I would have preferred to use [MONITOR](http://hypervsir.blogspot.com/2014/11/monitor-trap-flag-mtf-usage-in-ept.html) trap flag. But WHVP doesn't offer this possibility.\r\n\r\nIn order to have proper performances (required for fuzzing), I decided to reduce the precision of\r\nthe coverage and add a mode when you only know when an instruction is executed for the first time.\r\n\r\nTo do that I patch the pages fetched from the snapshot with 0xcc bytes (only for executable pages).\r\nWhen the cpu will execute these patched instructions the hypervisor will trap the exception and\r\nrewrite the instructions with the original code.\r\n\r\nIt's like having a unique software breakpoint set on every instruction. It works 95% of the time but\r\nin particular piece of code (ones with jump tables for example) it will fail because data will be\r\nreplaced.\r\n\r\nTo overcome this one option would be to disassemble the code before mapping it and only patch what\r\nis needed (maybe next time).\r\n\r\nDuring my experiment I encountered several limitations when using WHVP. It's slow, like really slow.\r\n[VirtualBox](https://www.virtualbox.org/browser/vbox/trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp)\r\nsource code have some interesting comments :)\r\n\r\nSo to have proper performance you really need to limit VM exits and it's incompatible if you want to\r\nuse Hyper-V as a tracing hypervisor (since it requires a lot of VM exits).\r\n\r\nDuring the same time I started to use\r\n[bochs](https://bochs.sourceforge.io/cgi-bin/lxr/source/instrument/instrumentation.txt) (specially\r\nthe instrumentation part) to check if the traces obtained by the tool were correct. Bochs was some\r\nkind of oracle to see if I had divergent traces.\r\n\r\nBochs is faster than WHVP when doing full trace and you also have the benefits of having memory accesses plus other useful goodies.\r\n\r\nI decided to add bochs as another backend. ``whvp`` was not a proper name anymore and I settled on ``rewind``.\r\n\r\n![](examples/CVE-2020-17087/images/rewind.png)\r\n\r\n## Typical usage\r\n\r\n``rewind`` was designed around my own workflow when I’m conducting\r\nsecurity assessments for kernel drivers on Windows platform.\r\n\r\nThe first step is to install the target software inside a virtual\r\nmachine. Since I’m using a mix of static and dynamic analysis I will\r\nalso setup a kernel debugger.\r\n\r\nAfter having opened some random drivers in IDA, I’ll quickly begin to\r\ntarget some functions. To do that I usually put some breakpoints with\r\n``windbg`` and combined with [ret-sync](https://github.com/bootleg/ret-sync)\r\nI can start to play.\r\n\r\nThat’s where ``rewind`` comes into play. Instead of editing random\r\nbuffer in memory and singlestep and annotate the IDB to have a rough\r\nidea of what’s is going on. I’ll take a snapshot with ``windbg`` and use\r\n``rewind`` instead.\r\n\r\nIt will ease the process a lot. Having a snapshot offers a lot of\r\nadvantages. Everything is deterministic. You can replay ad nauseum a\r\nfunction call. You can launch a fuzzer if the target function looks\r\ninteresting. You can even close the VM since it’s not needed anymore.\r\n\r\n## Prerequisites\r\n\r\nObviously you need Rust (installation tested on Windows and Linux with Rust 1.50). CMake is also\r\nneeded by some dependencies.\r\n\r\n## Git\r\n\r\nFirst clone the repository:\r\n\r\n```\r\n$ git clone git@github.com:quarkslab/rewind.git\r\n```\r\n\r\nContinue with the installation of bochs backend\r\n\r\n### Bochs\r\n\r\nClone bochscpu (https://github.com/yrp604/bochscpu) repository in the ``vendor`` directory:\r\n\r\n```\r\n$ cd vendor\r\n$ git clone https://github.com/yrp604/bochscpu\r\n```\r\n\r\nDownload the prebuilt bochs artifacts from bochscpu-build (https://github.com/yrp604/bochscpu-build)\r\n\r\n```\r\n$ curl.exe -L --output bochs-x64-win.zip [artifact_url]\r\n```\r\n\r\nExtract the ``lib`` and ``bochs`` folders into the bochscpu checkout.\r\n\r\n```\r\n$ Expand-Archive -Path .\\bochs-x64-win.zip -DestinationPath .\\\r\n$ copy -Recurse .\\bochs-x64-win\\msvc\\* .\\bochscpu\\\r\n```\r\n\r\n### WHVP\r\n\r\nOn Windows WHVP will also be built as backend. \r\n\r\nIn a elevated powershell session, use the following command to check if WHVP is enabled:\r\n\r\n```\r\nGet-WindowsOptionalFeature -FeatureName HypervisorPlatform -Online\r\n\r\nFeatureName      : HypervisorPlatform\r\nDisplayName      : Windows Hypervisor Platform\r\nDescription      : Enables virtualization software to run on the Windows hypervisor\r\nRestartRequired  : Possible\r\nState            : Enabled\r\nCustomProperties :\r\n```\r\n\r\nIf it is not enabled you can use `Set-WindowsOptionalFeature` cmdlet to enable. You'll also need to enable Hyper-V.\r\n\r\nYou also need to have a Windows SDK (10.0.19041.0) installed. You can download it from https://developer.microsoft.com/fr-fr/windows/downloads/windows-10-sdk/.\r\n\r\n\r\n### Build from master branch\r\n\r\nYou need to install LLVM and set the `LIBCLANG_PATH` environment variable (required by `bindgen`)\r\nSee https://rust-lang.github.io/rust-bindgen/requirements.html for a detailed explanation.\r\n\r\n```\r\n$ $env:LIBCLANG_PATH=\"C:\\Program Files\\LLVM\\bin\"\r\n```\r\n\r\nFrom there you should be able to build ``rewind`` (nightly required because of ``unwind_attributes`` in ``bochscpu`` crate):\r\n\r\n```\r\n$ cd rewind_cli\r\n$ cargo +nightly build --release\r\n```\r\n\r\n``rewind`` binary will be available in the ``target/release`` directory.\r\n\r\nYou could also use cargo to install locally:\r\n\r\n```\r\n$ cd rewind_cli\r\n$ cargo +nightly install --path .\r\n```\r\n\r\n### Common build issues\r\n\r\n-  if cmake is not in path, you will have an error when building zydis\r\n\r\n```\r\n\u003e error: failed to run custom build command for `zydis v3.1.1`\r\n```\r\n\r\n- if Windows SDK is different of the supported ones, `whvp-sys` will fail to build\r\n\r\n\r\n## Examples\r\n\r\nA basic tutorial leveraging CVE-2020-17087 is provided in the [examples](/examples/CVE-2020-17087) directory\r\n\r\n## Roadmap\r\n\r\nSee [TODO.md](/TODO.md)\r\n\r\n## Known Bugs/Limitations\r\n\r\n- This software is in a very early stage of development and an ongoing experiment.\r\n- Sometimes the tracer is unable to trace the target function (most common issue is invalid virtual cpu state).\r\n- When using `hit` coverage mode, the tracer will misbehave on some functions (it is the case with some switch tables). The reason is that each byte is replaced by software breakpoints (including data if they are present in a executable page). A better way to do that would be to obtain the list of all the basic blocks from a disassembler for example.\r\n- The target function will be executed with a unique virtual processor, you have no support for hardware so it's probable something will be wrong if you trace hardware related functions\r\n- This tool is best used for targetting specific functions\r\n- To have best performances, minimize VM exits and modified pages because they can be really costly and will increase the time needed to execute the function. \r\n- Don't use hyper-V to do snapshots. Windows Hyper-V are \"enlightened\" meaning they are using paravirtualization, it's currently not handled\r\n- Some symbols are not resolved properly\r\n\r\n## License\r\n\r\nThis tool is currently developed and sponsored by Quarkslab under the Apache 2.0 license.\r\n\r\n## Greetz\r\n\r\nHail to @yrp604, @0vercl0k, Alexandre Gazet for their help, feedbacks and thoughts. Thanks also to all my colleagues at Quarkslab!\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquarkslab%2Frewind","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fquarkslab%2Frewind","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquarkslab%2Frewind/lists"}