Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Need code and/or instruction to take a new snapshot of other UEFI code #6

Open
tandasat opened this issue Apr 27, 2023 · 2 comments
Open

Comments

@tandasat
Copy link
Owner

tandasat commented Apr 27, 2023

Currently, the repo does not include code or instructions to take a new snapshot on your own. Add this so that users can get a better idea of how that code or workflow look like.

The reason behind not including that code or instructions is that this project's top focus is learning virtualization technologies and not using it for fuzzing (it is solely a mean), and our hypervisor is only capable of fuzzing UEFI code (due to missing paging handling), making it fairly useless as a fuzzer for many.

The format of a snapshot this project consumes is custom, so combining with limited usefulness of the project as a fuzzer, I do not have an impression that such code and instruction is going to be helpful for many. Let me know if you are interested. I can take time at some point as I see interest.

To make it somewhat more useful and interesting, it would be nice if the project can consume snapshots of existing hypervisor products such as VMware, but I do not think I am going to take time for that.

@r3bb1t
Copy link

r3bb1t commented Apr 27, 2023

There are not many projects availible on the internet which can fuzz or get coverage from .efi binaries.

I understand that the main goal of the project is to show how the virtualization technologies work, but I also think that it would be really useful to add support for creating the snapshots, so the people, who are insterested on building their own blackbox .efi fuzzers/instrumentators would not spend unnecessary big amounts of time searching for the ways to get their target binaries to work.

It will also help with reverse engineering stuff as well, by allowing the reverse engineers examinig the execution paths of the UEFI binaries. Just like running user mode binaries with dynamorio and then highlighting it's execution history in Ida with the lighthouse. Personally, i don't know the projects which can assist in black-box coverage tracking like this one.

@tandasat
Copy link
Owner Author

tandasat commented Apr 29, 2023

Let me share notes on how I took snapshots. I have some motivation to add this officially, but it is definitely not going to happen anytime in the next few months, so hopefully this note works as a starting point.

The high-level idea is to have another hypervisor that is capable of taking a snapshot, and run your target under the hypervisor.

Here is more detailed steps:

  1. Have a VMware VM to run the target and take a snapshot. It must:
    • have an IDE disk
    • be a single core
    • enable nested HW VT
    • have 512 MB or less of RAM
  2. Have your own hypervisor that is capable of virtualizing the UEFI environment and run your target.
  3. Integrate the following code into the hypervisor.
    https://gist.github.com/tandasat/960653187242cf4615f373f3d0853225
    This code is to capture all physical memory and register values and write it into the IDE disk, ie, creating a snapshot. I integrated this as a VMCALL handler. The idea is, whenever you want to take a snapshot, you simply execute VMCALL.
  4. Start the VM and install your HV.
  5. Plan where and how you want to execute VMCALL. One way is to directly modify the target EFI's file (code) to execute VMCALL.
  6. Do it.
  7. The VMware disk image should contain the snapshot starting with 0x544F485350414E53 (IIRC, it will be at offset 0 of the file). Extract the contents as a snapshot file with a hex editor.
  8. Restore bytes at RIP to the original, ie, the snapshot contains VMCALL, which needs to be replaced.
  9. rhv expects a slightly different format of the snapshot. At least the SNAPSHOT_HEADER structure needs to be placed at the end of snapshot, instead of at the beginning.
  10. Depends on state of the guest (snapshot), make changes in rhv such that you can "inject" fuzzy input. (see: adjust_registers for the current implementation).

Expect this is a bumpy load to try it by yourself. I am almost certain that the steps are incomplete, and even after successful snapshot taking, rhv does not have robust enough implementation to handle another snapshot (ie, some VM exit handling may be missing, deadlock detection may not be functional etc).

Again, the more generic approach / improvement would be using Bochs. Run the target with Bochs, either with a debugger or some Bochs patches to trigger snapshot generation. Then, update rhv to be able to consume a Bochs snapshot. I have seen this work somewhere so it is not stretch to implement this for anyone sufficiently motivated (which is not me).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants