Git Product home page Git Product logo

libvmi's Introduction


KVM-VMI

KVM-based Virtual Machine Instrospection.

Slack

Table of Contents

Overview

This project adds virtual machine introspection to the KVM hypervisor.

Virtual Machine Introspection is a technology that aims to understand the guest's execution context, solely based on the VM's hardware state, for various purposes:

  • Debugging
  • Malware Analysis
  • Live-Memory Analysis
  • OS Hardening
  • Monitoring
  • Fuzzing

See the presentations section for more information.

This project is divided into 4 components:

  • kvm: linux kernel with vmi patches for KVM
  • qemu: patched to allow introspection
  • nitro (legacy): userland library which receives events, introspects the virtual machine state, and fills the semantic gap
  • libvmi: virtual machine instrospection library with unified API across Xen and KVM

At the moment, 2 versions of VMI patches are available for QEMU/KVM in this repository:

Installation

Follow the Setup guide

Presentations

References

The legacy VMI system contained in this repo (Nitro) is based on Jonas Pfoh's work:

Maintainers

@Wenzel

License

GNU General Public License v3.0

libvmi's People

Contributors

0xarash avatar aisaila avatar awsaba avatar azizulhakim avatar bdpayne avatar chivay avatar disaykin avatar dl9rdz avatar dlevy022 avatar dongphuong2410 avatar flyn-org avatar icedevml avatar k-mayer avatar lehmannro avatar mattshockl avatar mbushou avatar mleinhos avatar mneilsen avatar mtarral avatar mzguanglin avatar namidairo avatar npc1054657282 avatar rageagainsthepc avatar redspot avatar skvl avatar smaresca avatar ssentanoe avatar tklengyel avatar ufo95 avatar wenzel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

libvmi's Issues

Setting memory events with VMI_MEMACCESS_N causes the VM to pause indefinetly

I was trying to understand how the vmi_clear_event() function works and noticed in case of an especific event it sets the page permission to VMI_MEMACCESS_N. Apparently this enforces the original page permissions (i'm really not sure if this is truly the case or it enforces the current permissions), but anyway i though this could apply to generic events, so looking at:
status_t vmi_set_mem_event(vmi_instance_t vmi, addr_t gfn, vmi_mem_access_t access, uint16_t slat_id) {

It makes a check if the permission is VMI_MEMACCESS_N:
if ( VMI_MEMACCESS_N != access ) {
Inside this condition it seeks for a generic event with the same permissions, so i though maybe that permission is supposed to be used to remove specific pages from a generic event, but when i set any memory event through vmi_set_mem_event or even a specific event with SETUP_MEM_EVENT macro with VMI_MEMACCESS_N the guest stops indefinetly

Here's how i thought i could remove a specific page from a generic event upon callback

event_response_t mm_callback(vmi_instance_t vmi, vmi_event_t *event)
{
    printf("called\n");
    printf("removing event\n");
    vmi_set_mem_event(vmi, event->mem_event.gfn, VMI_MEMACCESS_N, 0);
    printf("removed event\n");
    return 0;
}

The event is setted normally but the guest is paused forever, even with vmi_resume_vm() it doesn't respond

This is the debug log when the callback is called:

--Received pagefault event
called
removing event
--Done setting memaccess on GPFN: 0xa60e6
removed event

undefined reference to errors

Hello:

When I build with
cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/programs/mylibvmi -DENABLE_KVM=ON -DENABLE_XEN=OFF -DENABLE_BAREFLANK=OFF
and then run make -j6, there are so many undefined references errors:

/usr/bin/ld: CMakeFiles/vmifs.dir/vmifs.c.o: in function `vmifs_read':
/home/qzt/fuzzers/kvm-vmi/libvmi/tools/vmifs/vmifs.c:94: undefined reference to `g_try_malloc0'
/usr/bin/ld: /home/qzt/fuzzers/kvm-vmi/libvmi/tools/vmifs/vmifs.c:99: undefined reference to `g_free'
/usr/bin/ld: /home/qzt/fuzzers/kvm-vmi/libvmi/tools/vmifs/vmifs.c:102: undefined reference to `g_free'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_direct_hash'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_slist_free_full'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_malloc'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_queue_unlink'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_hash_table_remove'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_str_equal'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_slist_free'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_hash_table_remove_all'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_int64_equal'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_hash_table_lookup'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_queue_get_length'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_queue_find_custom'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_queue_pop_tail'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_strconcat'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_hash_table_new'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_slist_find_custom'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_slist_prepend'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_hash_table_iter_next'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_direct_equal'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_queue_foreach'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_hash_table_new_full'
/usr/bin/ld: ../../libvmi/libvmi.so.0.0.15: undefined reference to `g_hash_table_size'

After many tries, I found that this code (line 33 in [ROOT]/CMakeLists.txt) is doing the bad thing:
string(REGEX REPLACE "-l" "" GLIB_LDFLAGS ${GLIB_LDFLAGS})
when i comment out this line, everything works fine.

I don't know if there will be some other problems, so I made this issue.

How to trigger INT3 events repeatedly

I successfully used in3 bp (in interrupt_event_example. c) in KVM environment,However In in3_cb function it will modified interrupt instruction to changed to the original instruction, it is not guaranteed to trigger next time.And I found that using emulate instead of change to original instruction can realize repeated triggering, But breakpoint-emulate-example.c is xen only,So how to realization on kvm?Thanks.

Makefile:129: recipe for target 'all' failed

Hi, I got this error when I tried to make libvmi, how to fix?

CMakeFiles/vmi-win-offsets.dir/win-offsets.c.o: In function `main':
/home/r11t/Desktop/kvm-vmi/libvmi/examples/win-offsets.c:310: undefined reference to `vmi_get_kernel_json'
/home/r11t/Desktop/kvm-vmi/libvmi/examples/win-offsets.c:312: undefined reference to `vmi_get_struct_member_offset_from_json'
/home/r11t/Desktop/kvm-vmi/libvmi/examples/win-offsets.c:314: undefined reference to `vmi_get_struct_member_offset_from_json'
/home/r11t/Desktop/kvm-vmi/libvmi/examples/win-offsets.c:320: undefined reference to `vmi_get_struct_member_offset_from_json'
/home/r11t/Desktop/kvm-vmi/libvmi/examples/win-offsets.c:325: undefined reference to `vmi_get_struct_member_offset_from_json'
/home/r11t/Desktop/kvm-vmi/libvmi/examples/win-offsets.c:330: undefined reference to `vmi_get_struct_member_offset_from_json'
collect2: error: ld returned 1 exit status
examples/CMakeFiles/vmi-win-offsets.dir/build.make:95: recipe for target 'examples/vmi-win-offsets' failed
make[2]: *** [examples/vmi-win-offsets] Error 1
CMakeFiles/Makefile2:1149: recipe for target 'examples/CMakeFiles/vmi-win-offsets.dir/all' failed
make[1]: *** [examples/CMakeFiles/vmi-win-offsets.dir/all] Error 2

KVM-v7 error in vagrant provisioning

Hi @Wenzel ,
libvmi got error during build with bellow strerr:
/vagrant/libvmi/libvmi/driver/kvm/kvm.c: In function ‘init_kvmi’:\n/vagrant/libvmi/libvmi/driver/kvm/kvm.c:383:12: error: variable ‘features’ has initializer but incomplete type\n struct kvmi_features features = {0};

Do I suppose to to checkout to specific commit which determined in kvm-vmi repository? Because I think all of the submodules are on kvmi-v7 branch now.

Thanks a lot.

KVM: handle instruction emulation response for any kind of events

Instruction emulation response is currently only available as a kvmi_event_pf_reply response:
https://github.com/KVM-VMI/kvm/blob/kvmi-v7/Documentation/virt/kvm/kvmi.rst#10-kvmi_event_pf

Libvmi has the VMI_EVENT_RESPONSE_SET_EMUL_INSN event response that could be implemented for the KVM driver.
An example already demonstrate how to use it:
https://github.com/KVM-VMI/libvmi/blob/master/examples/breakpoint-emulate-example.c#L87

It would be handy for the instruction emulation response in KVM to not be limited only for pagefaults.

The use case behind this is to return the original opcode when breakpoint was hit, previously replaced by an int 3 opcode.
This allows to have relatively cheap race condition free breakpoints with Libvmi / KVM.

The fallback solution right now is to use recoiling:
https://github.com/KVM-VMI/libvmi/blob/master/examples/breakpoint-recoil-example.c

cc @mdontu, @adlazar, @tklengyel

Implementing vmi_events_listen(0)

Hi,

I would like to start a discussion about how vmi_events_listen(vmi, 0) should be implementing with the APIs available in KVMi.

As we know, the API definition is the following:
https://github.com/libvmi/libvmi/blob/master/libvmi/events.h#L760

  • Listen for events until one occurs or a timeout.
  • If the timeout is given as 0, it will process leftover events
  • in the ring-buffer (if there are any).

The current implementation I gave in my first PR on v5 events is not handling the case where timeout=0, to process leftover events.

Simple implementation

We could consider the following implementation, with a do ... while() loop

status_t
kvm_events_listen(
    vmi_instance_t vmi,
    uint32_t timeout)
{
#ifdef ENABLE_SAFETY_CHECKS
    if (!vmi)
        return VMI_FAILURE;
#endif
    struct kvmi_dom_event *event = NULL;
    unsigned int ev_reason = 0;
    // if timeout is 0, we have to process all leftover events on the ring
    bool process_all_events = (timeout == 0) ? true : false;

    kvm_instance_t *kvm = kvm_get_instance(vmi);
#ifdef ENABLE_SAFETY_CHECKS
    if (!kvm || !kvm->kvmi_dom)
        return VMI_FAILURE;
#endif

    do {
        // wait next event
        if (kvmi_wait_event(kvm->kvmi_dom, (kvmi_timeout_t)timeout)) {
            if (errno == ETIMEDOUT) {
                // no events !
                break;
            }
            errprint("%s: kvmi_wait_event failed: %s\n", __func__, strerror(errno));
            return VMI_FAILURE;
        }

        // pop event from queue
        if (kvmi_pop_event(kvm->kvmi_dom, &event)) {
            errprint("%s: kvmi_pop_event failed: %s\n", __func__, strerror(errno));
            return VMI_FAILURE;
        }

        // handle event
        ev_reason = event->event.common.event;
#ifdef ENABLE_SAFETY_CHECKS
        if ( ev_reason >= KVMI_NUM_EVENTS || !kvm->process_event[ev_reason] ) {
            errprint("Undefined handler for %u event reason\n", ev_reason);
            goto error_exit;
        }
#endif
        // call handler
        if (VMI_FAILURE == kvm->process_event[ev_reason](vmi, event))
            goto error_exit;

        if (event) {
            free(event);
            event = NULL;
        }
    } while (process_all_events);

    return VMI_SUCCESS;
error_exit:
    if (event)
        free(event);
    return VMI_FAILURE;
} 

Problematic use case

Considering this simple use-case:

vmi_pause_vm(vmi);
...
vmi_events_listen(vmi, 0); <--- This call should clean the ring and process leftover events, while keeping the VM paused.

Pause events ?

With the API available today in KVMi, it is quite challenging to honor the behavior expected by the user.

The main problem lies in the fact that pausing the VM in KVMi means that a KVMI_EVENT_PAUSE_VCPU event will be queued in the event ring.

Therefore our implementation will remove these events from the ring.
From the moment where we remove them, we have to give a reply to the VCPU with the event sequence number.

I'm puzzled by how we can handle this implementation correctly and I would like your advices.

ideas:

  • pop the pause events anyway, reply continue and call vmi_pause_vm to reque the pause events at the end (if we encountered pause events) ? not doable, the vcpu will be running anyway since we sent a reply.
  • pop the next event, if it's a pause events, store it for the next vmi_resume_vm call ? 🤔

cc @mdontu, @adlazar, @tklengyel, @smaresca

Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.