From 2502d549dad6492bd775bab5ca15790f9e15b5ee Mon Sep 17 00:00:00 2001 From: Mathieu Tarral Date: Wed, 27 Jun 2018 16:40:20 +0300 Subject: [PATCH 1/3] remove nitro/libvmi --- nitro/libvmi/__init__.py | 5 - nitro/libvmi/glib_build.py | 44 --- nitro/libvmi/libvmi.py | 668 -------------------------------- nitro/libvmi/libvmi_build.py | 26 -- nitro/libvmi/libvmi_cdef.h | 717 ----------------------------------- 5 files changed, 1460 deletions(-) delete mode 100644 nitro/libvmi/__init__.py delete mode 100755 nitro/libvmi/glib_build.py delete mode 100644 nitro/libvmi/libvmi.py delete mode 100755 nitro/libvmi/libvmi_build.py delete mode 100644 nitro/libvmi/libvmi_cdef.h diff --git a/nitro/libvmi/__init__.py b/nitro/libvmi/__init__.py deleted file mode 100644 index d2e7a9e..0000000 --- a/nitro/libvmi/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# public interface -from nitro.libvmi.libvmi import INIT_DOMAINNAME, INIT_DOMAINID, INIT_EVENTS, INIT_SHM -from nitro.libvmi.libvmi import Libvmi, LibvmiError, VMIConfig -from nitro.libvmi.libvmi import VMIStatus, LibvmiInitError, PageMode -from nitro.libvmi.libvmi import VMIArch, VMIOS, VMIWinVer diff --git a/nitro/libvmi/glib_build.py b/nitro/libvmi/glib_build.py deleted file mode 100755 index c4fc53c..0000000 --- a/nitro/libvmi/glib_build.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env python3 - - -from cffi import FFI -import pkgconfig - -cdef = """ -typedef int gint; -typedef gint gboolean; -typedef void* gpointer; -typedef const void *gconstpointer; -typedef unsigned int guint; -typedef struct _GHashTable GHashTable; - -typedef guint (*GHashFunc)(gconstpointer key); -typedef gboolean (*GEqualFunc)(gconstpointer a, gconstpointer b); - -GHashTable* g_hash_table_new (GHashFunc hash_func, - GEqualFunc key_equal_func); - -gboolean g_hash_table_insert (GHashTable *hash_table, - gpointer key, - gpointer value); - -void g_hash_table_destroy (GHashTable *hash_table); - -guint g_str_hash (gconstpointer v); -gboolean g_str_equal (gconstpointer v1, gconstpointer v1); -""" - - -ffi = FFI() -includes = pkgconfig.cflags('glib-2.0').replace('-I', '').split(' ') -# set source -ffi.set_source("_glib", - """ - #include - """, - libraries=['glib-2.0'], include_dirs=includes) - -ffi.cdef(cdef) - -if __name__ == "__main__": - ffi.compile(verbose=True) diff --git a/nitro/libvmi/libvmi.py b/nitro/libvmi/libvmi.py deleted file mode 100644 index 81ecbe6..0000000 --- a/nitro/libvmi/libvmi.py +++ /dev/null @@ -1,668 +0,0 @@ -from enum import Enum - -from _libvmi import ffi, lib -from _glib import lib as glib - - -# export libvmi defines -INIT_DOMAINNAME = lib.VMI_INIT_DOMAINNAME -INIT_DOMAINID = lib.VMI_INIT_DOMAINID -INIT_EVENTS = lib.VMI_INIT_EVENTS -INIT_SHM = lib.VMI_INIT_SHM - - -class LibvmiError(Exception): - pass - - -class VMIConfig(Enum): - GLOBAL_FILE_ENTRY = 0 - STRING = 1 - DICT = 2 - - -class VMIStatus(Enum): - SUCCESS = 0 - FAILURE = 1 - - -class LibvmiInitError(Enum): - NONE = 0 # No error - DRIVER_NOT_DETECTED = 1 # Failed to auto-detect hypervisor - DRIVER = 2 # Failed to initialize hypervisor-driver - VM_NOT_FOUND = 3 # Failed to find the specified VM - PAGING = 4 # Failed to determine or initialize paging functions - OS = 5 # Failed to determine or initialize OS functions - EVENTS = 6 # Failed to initialize events - SHM = 7 # Failed to initialize SHM - NO_CONFIG = 8 # No configuration was found for OS initialization - NO_CONFIG_ENTRY = 9 # Configuration contained no valid entry for VM - - -class PageMode(Enum): - UNKNOWN = 0 # page mode unknown - LEGACY = 1 # x86 32-bit paging - PAE = 2 # x86 PAE paging - IA32E = 3 # x86 IA-32e paging - AARCH32 = 4 # ARM 32-bit paging - AARCH64 = 5 # ARM 64-bit paging - - -class VMIArch(Enum): - VMI_ARCH_UNKNOWN = 0 # Unknown architecture - VMI_ARCH_X86 = 1 # x86 32-bit architecture - VMI_ARCH_X86_64 = 2 # x86 64-bit architecture - VMI_ARCH_ARM32 = 3 # ARM 32-bit architecture - VMI_ARCH_ARM64 = 4 # ARM 64-bit architecture - -class VMIOS(Enum): - UNKNOWN = 0 - LINUX = 1 - WINDOWS = 2 - -class VMIWinVer(Enum): - OS_WINDOWS_NONE = 0 # TODO 0 ? Not Windows - OS_WINDOWS_UNKNOWN = 1 # TODO 1 ? Is Windows, not sure which - OS_WINDOWS_2000 = 0x0208 # Magic value for Windows 2000 - OS_WINDOWS_XP = 0x0290 # Magic value for Windows XP - OS_WINDOWS_2003 = 0x0318 # Magic value for Windows 2003 - OS_WINDOWS_VISTA = 0x0328 # Magic value for Windows Vista - OS_WINDOWS_2008 = 0x0330 # Magic value for Windows 2008 - OS_WINDOWS_7 = 0x0340 # Magic value for Windows 7 - OS_WINDOWS_8 = 0x0360 # Magic value for Windows 8 - OS_WINDOWS_10 = 0x0361 # TODO last + 1 ? - - -def check(status, error='VMI_FAILURE'): - if VMIStatus(status) != VMIStatus.SUCCESS: - raise LibvmiError(error) - -class Libvmi: - - __slots__ = ( - 'opaque_vmi', - 'vmi', - ) - - def __init__(self, domain, init_flags=INIT_DOMAINNAME, init_data=ffi.NULL, mode=VMIConfig.GLOBAL_FILE_ENTRY, config=ffi.NULL): - self.vmi = None - self.opaque_vmi = ffi.new("vmi_instance_t *") - init_error = ffi.new("vmi_init_error_t *") - ghash = None - # avoid GC to free ghashtable inserted values - ghash_ref = dict() - - # if INIT_DOMAINNAME, we need to encode the string from str to bytes - if init_flags & INIT_DOMAINNAME: - domain = domain.encode() - - # same for VMI_CONFIG_STRING - if mode == VMIConfig.STRING: - config = config.encode() - elif mode == VMIConfig.DICT: - # need to convert config to a GHashTable - g_str_hash_addr = ffi.addressof(glib, "g_str_hash") - g_str_equal_addr = ffi.addressof(glib, "g_str_equal") - ghash = glib.g_hash_table_new(g_str_hash_addr, g_str_equal_addr) - - for k, v in config.items(): - key = k.encode() - if isinstance(v, str): - value = v.encode() - elif isinstance(v, int): - value = ffi.new("int*", v) - else: - raise RuntimeError() - glib.g_hash_table_insert(ghash, key, value) - # keep a reference to avoid GC - ghash_ref[key] = value - - config = ghash - - # init libvmi - status = lib.vmi_init_complete(self.opaque_vmi, - domain, - init_flags, - init_data, - mode.value, - config, - init_error) - error_msg = LibvmiInitError(init_error[0]).name - check(status, error_msg) - # store handle to real vmi_instance_t - self.vmi = self.opaque_vmi[0] - # destroy ghashtable if necessary - if ghash is not None: - glib.g_hash_table_destroy(ghash) - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, traceback): - self.destroy() - - def destroy(self): - if self.vmi: - status = lib.vmi_destroy(self.vmi) - check(status) - self.opaque_vmi = None - self.vmi = None - - def get_library_arch(self): - arch = lib.vmi_get_library_arch() - return VMIArch(arch) - - def get_rekall_path(self): - value = lib.vmi_get_rekall_path(self.vmi) - if value == ffi.NULL: - return None - return ffi.string(value).decode() - - # memory translations - def translate_kv2p(self, vaddr): - paddr = ffi.new("addr_t *") - status = lib.vmi_translate_kv2p(self.vmi, vaddr, paddr) - check(status) - return paddr[0] - - def translate_uv2p(self, vaddr, pid): - paddr = ffi.new("addr_t *") - status = lib.vmi_translate_uv2p(self.vmi, vaddr, pid, paddr) - check(status) - return paddr[0] - - def translate_ksym2v(self, symbol): - vaddr = ffi.new("addr_t *") - status = lib.vmi_translate_ksym2v(self.vmi, symbol.encode(), vaddr) - check(status) - return vaddr[0] - - def translate_sym2v(self, ctx, symbol): - vaddr = ffi.new("addr_t *") - status = lib.vmi_translate_sym2v(self.vmi, ctx, symbol.encode(), vaddr) - check(status) - return vaddr[0] - - def translate_v2sym(self, ctx, addr): - symbol = lib.vmi_translate_v2sym(self.vmi, ctx, addr) - if symbol == ffi.NULL: - raise LibvmiError('VMI_FAILURE') - return ffi.string(symbol).decode() - - def translate_v2ksym(self, ctx, addr): - symbol = lib.vmi_translate_v2ksym(self.vmi, ctx, addr) - if symbol == ffi.NULL: - raise LibvmiError('VMI_FAILURE') - return ffi.string(symbol).decode() - - def pid_to_dtb(self, pid): - dtb = ffi.new('addr_t *') - status = lib.vmi_pid_to_dtb(self.vmi, pid, dtb) - check(status) - return dtb[0] - - def dtb_to_pid(self, dtb): - pid = ffi.new("vmi_pid_t *") - status = lib.vmi_dtb_to_pid(self.vmi, dtb, pid) - check(status) - return pid[0] - - def pagetable_lookup(self, dtb, vaddr): - paddr = ffi.new("addr_t *") - status = lib.vmi_pagetable_lookup(self.vmi, dtb, vaddr, paddr) - check(status) - return paddr[0] - - def pagetable_lookup_extended(self, dtb, vaddr): - page_info = ffi.new("page_info_t *") - status = lib.vmi_pagetable_lookup_extended(self.vmi, dtb, vaddr, page_info) - check(status) - return page_info - - # read - def read(self, ctx, count): - buffer = ffi.new("char[]", count) - bytes_read = ffi.new("size_t *") - status = lib.vmi_read(self.vmi, ctx, count, buffer, bytes_read) - check(status) - # transform into Python bytes - buffer = ffi.unpack(buffer, bytes_read[0]) - return (buffer, bytes_read[0]) - - def read_8(self, ctx): - value = ffi.new("uint8_t *") - status = lib.vmi_read_8(self.vmi, ctx, value) - check(status) - return value[0] - - def read_16(self, ctx): - value = ffi.new("uint16_t *") - status = lib.vmi_read_16(self.vmi, ctx, value) - check(status) - return value[0] - - def read_32(self, ctx): - value = ffi.new("uint32_t *") - status = lib.vmi_read_32(self.vmi, ctx, value) - check(status) - return value[0] - - def read_64(self, ctx): - value = ffi.new("uint64_t *") - status = lib.vmi_read_64(self.vmi, ctx, value) - check(status) - return value[0] - - def read_addr(self, ctx): - value = ffi.new("addr_t *") - status = lib.vmi_read_addr(self.vmi, ctx, value) - check(status) - return value[0] - - def read_str(self, ctx): - value = lib.vmi_read_str_va(self.vmi, ctx) - if value == ffi.NULL: - raise LibvmiError('VMI_FAILURE') - return ffi.string(value).decode() - - def read_unicode_str(self, ctx): - value = lib.vmi_read_unicode_str(self.vmi, ctx) - if value == ffi.NULL: - raise LibvmiError('VMI_FAILURE') - encoding = ffi.string(value.encoding).decode() - buffer = ffi.string(value.contents, value.length) - self.free_unicode_str(value) - return buffer.decode(encoding) - - def read_ksym(self, symbol, count): - buffer = ffi.new("char[]", count) - bytes_read = ffi.new("size_t *") - status = lib.vmi_read_ksym(self.vmi, symbol.encode(), count, buffer, bytes_read) - check(status) - # transform into Python bytes - buffer = ffi.string(buffer, bytes_read[0]) - return (buffer, bytes_read[0]) - - def read_va(self, vaddr, pid, count): - buffer = ffi.new("char[]", count) - bytes_read = ffi.new("size_t *") - status = lib.vmi_read_va(self.vmi, vaddr, pid, count, buffer, bytes_read) - check(status) - # transform into Python bytes - buffer = ffi.unpack(buffer, bytes_read[0]) - return (buffer, bytes_read[0]) - - def read_pa(self, paddr, count): - buffer = ffi.new("char[]", count) - bytes_read = ffi.new("size_t *") - status = lib.vmi_read_pa(self.vmi, paddr, count, buffer, bytes_read) - check(status) - # transform into Python bytes - buffer = ffi.unpack(buffer, bytes_read[0]) - return (buffer, bytes_read[0]) - - def read_8_ksym(self, symbol): - value = ffi.new("uint8_t *") - status = lib.vmi_read_8_ksym(self.vmi, symbol.encode(), value) - check(status) - return value[0] - - def read_16_ksym(self, symbol): - value = ffi.new("uint16_t *") - status = lib.vmi_read_16_ksym(self.vmi, symbol.encode(), value) - check(status) - return value[0] - - def read_32_ksym(self, symbol): - value = ffi.new("uint32_t *") - status = lib.vmi_read_32_ksym(self.vmi, symbol.encode(), value) - check(status) - return value[0] - - def read_64_ksym(self, symbol): - value = ffi.new("uint64_t *") - status = lib.vmi_read_64_ksym(self.vmi, symbol.encode(), value) - check(status) - return value[0] - - def read_addr_ksym(self, symbol): - value = ffi.new("addr_t *") - status = lib.vmi_read_addr_ksym(self.vmi, symbol.encode(), value) - check(status) - return value[0] - - def read_8_va(self, vaddr, pid): - value = ffi.new("uint8_t *") - status = lib.vmi_read_8_va(self.vmi, vaddr, pid, value) - check(status) - return value[0] - - def read_16_va(self, vaddr, pid): - value = ffi.new("uint16_t *") - status = lib.vmi_read_16_va(self.vmi, vaddr, pid, value) - check(status) - return value[0] - - def read_32_va(self, vaddr, pid): - value = ffi.new("uint32_t *") - status = lib.vmi_read_32_va(self.vmi, vaddr, pid, value) - check(status) - return value[0] - - def read_64_va(self, vaddr, pid): - value = ffi.new("uint64_t *") - status = lib.vmi_read_64_va(self.vmi, vaddr, pid, value) - check(status) - return value[0] - - def read_addr_va(self, vaddr, pid): - value = ffi.new("addr_t *") - status = lib.vmi_read_addr_va(self.vmi, vaddr, pid, value) - check(status) - return value[0] - - def read_str_va(self, vaddr, pid): - value = lib.vmi_read_str_va(self.vmi, vaddr, pid) - if value == ffi.NULL: - raise LibvmiError('VMI_FAILURE') - return ffi.string(value).decode() - - def read_unicode_str_va(self, vaddr, pid): - value = lib.vmi_read_unicode_str_va(self.vmi, vaddr, pid) - if value == ffi.NULL: - raise LibvmiError('VMI_FAILURE') - encoding = ffi.string(value.encoding).decode() - buffer = ffi.string(value.contents, value.length) - self.free_unicode_str(value) - return buffer.decode(encoding) - - # TODO convert_str_encoding - - def free_unicode_str(self, unicode_str): - lib.vmi_free_unicode_str(unicode_str) - - def read_8_pa(self, paddr): - value = ffi.new("uint8_t *") - status = lib.vmi_read_8_pa(self.vmi, paddr, value) - check(status) - return value[0] - - def read_16_pa(self, paddr): - value = ffi.new("uint16_t *") - status = lib.vmi_read_16_pa(self.vmi, paddr, value) - check(status) - return value[0] - - def read_32_pa(self, paddr): - value = ffi.new("uint32_t *") - status = lib.vmi_read_32_pa(self.vmi, paddr, value) - check(status) - return value[0] - - def read_64_pa(self, paddr): - value = ffi.new("uint64_t *") - status = lib.vmi_read_64_pa(self.vmi, paddr, value) - check(status) - return value[0] - - def read_addr_pa(self, paddr): - value = ffi.new("addr_t *") - status = lib.vmi_read_addr_pa(self.vmi, paddr, value) - check(status) - return value[0] - - def read_str_pa(self, paddr): - value = lib.vmi_read_str_pa(self.vmi,paddr) - if value == ffi.NULL: - raise LibvmiError('VMI_FAILURE') - return ffi.string(value).decode() - - # write - def write(self, ctx, buffer): - cffi_buffer = ffi.from_buffer(buffer) - bytes_written = ffi.new("size_t *") - count = len(buffer) - status = lib.vmi_write(self.vmi, ctx, count, cffi_buffer, bytes_written) - check(status) - - def write_ksym(self, symbol, buffer): - cffi_buffer = ffi.from_buffer(buffer) - bytes_written = ffi.new("size_t *") - count = len(buffer) - status = lib.vmi_write_ksym(self.vmi, symbol, count, cffi_buffer, bytes_written) - check(status) - - def write_va(self, vaddr, pid, buffer): - cffi_buffer = ffi.from_buffer(buffer) - bytes_written = ffi.new("size_t *") - count = len(buffer) - status = lib.vmi_write_va(self.vmi, vaddr, pid, count, cffi_buffer, bytes_written) - check(status) - - def write_pa(self, paddr, buffer): - cffi_buffer = ffi.from_buffer(buffer) - bytes_written = ffi.new("size_t *") - count = len(buffer) - status = lib.vmi_write_va(self.vmi, paddr, count, cffi_buffer, bytes_written) - check(status) - - def write_8(self, ctx, value): - cffi_value = ffi.new("uint8_t *", value) - status = lib.vmi_write_8(self.vmi, ctx, cffi_value) - check(status) - - def write_16(self, ctx, value): - cffi_value = ffi.new("uint16_t *", value) - status = lib.vmi_write_16(self.vmi, ctx, cffi_value) - check(status) - - def write_32(self, ctx, value): - cffi_value = ffi.new("uint32_t *", value) - status = lib.vmi_write_32(self.vmi, ctx, cffi_value) - check(status) - - def write_64(self, ctx, value): - cffi_value = ffi.new("uint64_t *", value) - status = lib.vmi_write_64(self.vmi, ctx, cffi_value) - check(status) - - def write_addr(self, ctx, value): - cffi_value = ffi.new("addr_t *", value) - status = lib.vmi_write_addr(self.vmi, ctx, cffi_value) - check(status) - - def write_8_ksym(self, symbol, value): - cffi_value = ffi.new("uint8_t *", value) - status = lib.vmi_write_8_ksym(self.vmi, symbol.encode(), cffi_value) - check(status) - - def write_16_ksym(self, symbol, value): - cffi_value = ffi.new("uint16_t *", value) - status = lib.vmi_write_16_ksym(self.vmi, symbol.encode(), cffi_value) - check(status) - - def write_32_ksym(self, symbol, value): - cffi_value = ffi.new("uint32_t *", value) - status = lib.vmi_write_32_ksym(self.vmi, symbol.encode(), cffi_value) - check(status) - - def write_64_ksym(self, symbol, value): - cffi_value = ffi.new("uint64_t *", value) - status = lib.vmi_write_64_ksym(self.vmi, symbol.encode(), cffi_value) - check(status) - - def write_addr_ksym(self, symbol, value): - cffi_value = ffi.new("addr_t *", value) - status = lib.vmi_write_addr_ksym(self.vmi, symbol.encode(), cffi_value) - check(status) - - def write_8_va(self, vaddr, pid, value): - cffi_value = ffi.new("uint8_t *", value) - status = lib.vmi_write_8_va(self.vmi, vaddr, pid, cffi_value) - check(status) - - def write_16_va(self, vaddr, pid, value): - cffi_value = ffi.new("uint16_t *", value) - status = lib.vmi_write_16_va(self.vmi, vaddr, pid, cffi_value) - check(status) - - def write_32_va(self, vaddr, pid, value): - cffi_value = ffi.new("uint32_t *", value) - status = lib.vmi_write_32_va(self.vmi, vaddr, pid, cffi_value) - check(status) - - def write_64_va(self, vaddr, pid, value): - cffi_value = ffi.new("uint64_t *", value) - status = lib.vmi_write_64_va(self.vmi, vaddr, pid, cffi_value) - check(status) - - def write_addr_va(self, vaddr, pid, value): - cffi_value = ffi.new("addr_t *", value) - status = lib.vmi_write_addr_va(self.vmi, vaddr, pid, cffi_value) - check(status) - - def write_8_pa(self, paddr, value): - cffi_value = ffi.new("uint8_t *", value) - status = lib.vmi_write_8_pa(self.vmi, paddr, cffi_value) - check(status) - - def write_16_pa(self, paddr, value): - cffi_value = ffi.new("uint16_t *", value) - status = lib.vmi_write_16_pa(self.vmi, paddr, cffi_value) - check(status) - - def write_32_pa(self, paddr, value): - cffi_value = ffi.new("uint32_t *", value) - status = lib.vmi_write_32_pa(self.vmi, paddr, cffi_value) - check(status) - - def write_64_pa(self, paddr, value): - cffi_value = ffi.new("uint64_t *", value) - status = lib.vmi_write_64_pa(self.vmi, paddr, cffi_value) - check(status) - - def write_addr_pa(self, paddr, value): - cffi_value = ffi.new("addr_t *", value) - status = lib.vmi_write_addr_pa(self.vmi, paddr, cffi_value) - check(status) - - # print functions - # TODO vmi_print_hex - # TODO vmi_print_hex_ksym - # TODO vmi_print_hex_va - # TODO vmi_print_hex_pa - - # get_* - def get_name(self): - value = lib.vmi_get_name(self.vmi) - if value == ffi.NULL: - raise LibvmiError('VMI_FAILURE') - return ffi.string(value).decode() - - def get_vmid(self): - return lib.vmi_get_vmid(self.vmi) - - # TODO vmi_get_access_mode - - def get_page_mode(self, vcpu): - page_mode = lib.vmi_get_page_mode(self.vmi, vcpu) - return PageMode(page_mode) - - def get_address_width(self): - return lib.vmi_get_address_width(self.vmi) - - def get_ostype(self): - os = lib.vmi_get_ostype(self.vmi) - return VMIOS(os) - - def get_winver(self): - win_ver = lib.vmi_get_winver(self.vmi) - return VMIWinVer(win_ver) - - def get_winver_str(self): - value = lib.vmi_get_winver_str(self.vmi) - if value == ffi.NULL: - raise LibvmiError('VMI_FAILURE') - return ffi.string(value).decode() - - def get_winver_manual(self, kdvb_pa): - win_ver = lib.vmi_get_winver_manual(self.vmi, kdvb_pa) - return VMIWinVer(win_ver) - - def get_offset(self, offset_name): - offset = ffi.new("addr_t *") - status = lib.vmi_get_offset(self.vmi, offset_name.encode(), offset) - check(status) - return offset[0] - - def get_kernel_struct_offset(self, struct_name, member): - value = ffi.new("addr_t *") - status = lib.vmi_get_kernel_struct_offset(self.vmi, struct_name.encode(), member.encode(), value) - check(status) - return value[0] - - def get_memsize(self): - return lib.vmi_get_memsize(self.vmi) - - def get_max_physical_memory_address(self): - return lib.vmi_get_max_physical_memory_address(self.vmi) - - def get_num_vcpus(self): - return lib.vmi_get_num_vcpus(self.vmi) - - # TODO needs a reg_t - def get_vcpu_reg(self, reg, vcpu): - value = ffi.new("uint64_t *") - status = lib.vmi_get_vcpureg(self.vmi, value, reg, vcpu) - check(status) - return value[0] - - # TODO wrapp registers_t - def get_vcpuregs(self, vcpu): - registers = ffi.new("registers_t *") - status = lib.vmi_get_vcpuregs(self.vmi, registers, vcpu) - check(status) - return registers - - # TODO same thing, needs a wrapper - def set_vcpureg(self, value, reg, vcpu): - status = lib.vmi_set_vcpureg(self.vmi, value, reg, vcpu) - check(status) - - # TODO needs a wrapper - def set_vcpuregs(self, regs, vcpu): - status = lib.vmi_set_vcpuregs(regs, vcpu) - check(status) - - def pause_vm(self): - status = lib.vmi_pause_vm(self.vmi) - check(status) - - def resume_vm(self): - status = lib.vmi_resume_vm(self.vmi) - check(status) - - # caches - def v2pcache_flush(self, dtb=0): - lib.vmi_v2pcache_flush(self.vmi, dtb) - - def v2pcache_add(self, va, dtb, pa): - lib.vmi_v2pcache_add(self.vmi, va, dtb, pa) - - def symcache_flush(self): - lib.vmi_symcache_flush(self.vmi) - - def symcache_add(self, base_addr, pid, symbol, va): - lib.vmi_symcache_add(self.vmi, base_addr, pid, symbol.encode(), va) - - def rvacache_flush(self): - lib.vmi_rvacache_flush(self.vmi) - - def rvacache_add(self, base_addr, pid, rva, symbol): - lib.vmi_symcache_add(self.vmi, base_addr, pid, rva, symbol.encode()) - - def pidcache_flush(self): - lib.vmi_pidcache_flush(self.vmi) - - def pidcache_add(self, pid, dtb): - lib.vmi_pidcache_add(self.vmi, pid, dtb) diff --git a/nitro/libvmi/libvmi_build.py b/nitro/libvmi/libvmi_build.py deleted file mode 100755 index 17f0f46..0000000 --- a/nitro/libvmi/libvmi_build.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 - - -import os -from cffi import FFI - -CDEF_FILE = 'libvmi_cdef.h' - - -ffi = FFI() -# set source -ffi.set_source("_libvmi", - """ - #include - """, - libraries=['vmi']) - -script_dir = os.path.dirname(os.path.realpath(__file__)) -# we read our C definitions from an external file -# easier to maintain + C syntax highlighting -with open(os.path.join(script_dir, CDEF_FILE)) as cdef_file: - cdef_content = cdef_file.read() -ffi.cdef(cdef_content) - -if __name__ == "__main__": - ffi.compile(verbose=True) diff --git a/nitro/libvmi/libvmi_cdef.h b/nitro/libvmi/libvmi_cdef.h deleted file mode 100644 index d69fc7f..0000000 --- a/nitro/libvmi/libvmi_cdef.h +++ /dev/null @@ -1,717 +0,0 @@ -#define VMI_INIT_DOMAINNAME 1 /**< initialize using domain name */ - -#define VMI_INIT_DOMAINID 2 /**< initialize using domain id */ - -#define VMI_INIT_EVENTS 4 /**< initialize events */ - -#define VMI_INIT_SHM 8 /**< initialize SHM mode */ - -// vmi_instance_t -typedef struct vmi_instance *vmi_instance_t; - -// addr_t -typedef uint64_t addr_t; - -// vmi_pid_t -typedef int32_t vmi_pid_t; - -// status_t -typedef enum status { - - VMI_SUCCESS, /**< return value indicating success */ - - VMI_FAILURE /**< return value indicating failure */ -} status_t; - -// vmi_config -typedef enum vmi_config { - - VMI_CONFIG_GLOBAL_FILE_ENTRY, /**< config in file provided */ - - VMI_CONFIG_STRING, /**< config string provided */ - - VMI_CONFIG_GHASHTABLE, /**< config GHashTable provided */ -} vmi_config_t; - -// vmi_mode -typedef enum vmi_mode { - - VMI_XEN, /**< libvmi is monitoring a Xen VM */ - - VMI_KVM, /**< libvmi is monitoring a KVM VM */ - - VMI_FILE, /**< libvmi is viewing a file on disk */ -} vmi_mode_t; - -// vmi_init_error_t -typedef enum vmi_init_error { - - VMI_INIT_ERROR_NONE, /**< No error */ - - VMI_INIT_ERROR_DRIVER_NOT_DETECTED, /**< Failed to auto-detect hypervisor */ - - VMI_INIT_ERROR_DRIVER, /**< Failed to initialize hypervisor-driver */ - - VMI_INIT_ERROR_VM_NOT_FOUND, /**< Failed to find the specified VM */ - - VMI_INIT_ERROR_PAGING, /**< Failed to determine or initialize paging functions */ - - VMI_INIT_ERROR_OS, /**< Failed to determine or initialize OS functions */ - - VMI_INIT_ERROR_EVENTS, /**< Failed to initialize events */ - - VMI_INIT_ERROR_SHM, /**< Failed to initialize SHM */ - - VMI_INIT_ERROR_NO_CONFIG, /**< No configuration was found for OS initialization */ - - VMI_INIT_ERROR_NO_CONFIG_ENTRY, /**< Configuration contained no valid entry for VM */ -} vmi_init_error_t; - -// os_t -typedef enum os { - - VMI_OS_UNKNOWN, /**< OS type is unknown */ - - VMI_OS_LINUX, /**< OS type is Linux */ - - VMI_OS_WINDOWS /**< OS type is Windows */ -} os_t; - -/** - * Windows version enumeration. The values of the enum - * represent the size of KDBG structure up to Windows 8. - * At Windows 10 the KDBG based scan is no longer supported - * and thus at that point the value itself has no magic value. - */ -typedef enum win_ver { - - VMI_OS_WINDOWS_NONE, /**< Not Windows */ - VMI_OS_WINDOWS_UNKNOWN, /**< Is Windows, not sure which */ - - VMI_OS_WINDOWS_2000 = 0x0208, /**< Magic value for Windows 2000 */ - VMI_OS_WINDOWS_XP = 0x0290, /**< Magic value for Windows XP */ - VMI_OS_WINDOWS_2003 = 0x0318, /**< Magic value for Windows 2003 */ - VMI_OS_WINDOWS_VISTA = 0x0328, /**< Magic value for Windows Vista */ - VMI_OS_WINDOWS_2008 = 0x0330, /**< Magic value for Windows 2008 */ - VMI_OS_WINDOWS_7 = 0x0340, /**< Magic value for Windows 7 */ - VMI_OS_WINDOWS_8 = 0x0360, /**< Magic value for Windows 8 */ - VMI_OS_WINDOWS_10, -} win_ver_t; - -typedef enum page_mode { - - VMI_PM_UNKNOWN, /**< page mode unknown */ - - VMI_PM_LEGACY, /**< x86 32-bit paging */ - - VMI_PM_PAE, /**< x86 PAE paging */ - - VMI_PM_IA32E, /**< x86 IA-32e paging */ - - VMI_PM_AARCH32, /**< ARM 32-bit paging */ - - VMI_PM_AARCH64 /**< ARM 64-bit paging */ -} page_mode_t; - -typedef enum translation_mechanism { - VMI_TM_INVALID, /**< Invalid translation mechanism */ - VMI_TM_NONE, /**< No translation is required, address is physical address */ - VMI_TM_PROCESS_DTB, /**< Translate addr via specified directory table base. */ - VMI_TM_PROCESS_PID, /**< Translate addr by finding process first to use its DTB. */ - VMI_TM_KERNEL_SYMBOL /**< Find virtual address of kernel symbol and translate it via kernel DTB. */ -} translation_mechanism_t; - -// vmi_arch_t -typedef enum arch { - VMI_ARCH_UNKNOWN, /**< Unknown architecture */ - VMI_ARCH_X86, /**< x86 32-bit architecture */ - VMI_ARCH_X86_64, /**< x86 64-bit architecture */ - VMI_ARCH_ARM32, /**< ARM 32-bit architecture */ - VMI_ARCH_ARM64 /**< ARM 64-bit architecture */ -} vmi_arch_t; - -// page_size_t -typedef enum page_size { - - VMI_PS_UNKNOWN = 0, /**< page size unknown */ - - VMI_PS_1KB = 0x400, /**< 1KB */ - - VMI_PS_4KB = 0x1000, /**< 4KB */ - - VMI_PS_16KB = 0x4000, /**< 16KB */ - - VMI_PS_64KB = 0x10000, /**< 64KB */ - - VMI_PS_1MB = 0x100000, /**< 1MB */ - - VMI_PS_2MB = 0x200000, /**< 2MB */ - - VMI_PS_4MB = 0x400000, /**< 4MB */ - - VMI_PS_16MB = 0x1000000, /**< 16MB */ - - VMI_PS_32MB = 0x2000000, /**< 32MB */ - - VMI_PS_512MB = 0x2000000, /**< 512MB */ - - VMI_PS_1GB = 0x4000000, /**< 1GB */ - -} page_size_t; - -typedef uint64_t reg_t; - -/* - * Commonly used x86 registers - */ -typedef struct x86_regs { - ...; -} x86_registers_t; - -typedef struct arm_registers { - ...; -} arm_registers_t; - -typedef struct registers { - ...; -} registers_t; - -// page_info_t -typedef struct page_info { - ...; -} page_info_t; - -// access_context_t -typedef struct { - ...; -} access_context_t; - -typedef struct _ustring { - size_t length; /**< byte count of contents */ - - uint8_t *contents; /**< pointer to byte array holding string */ - - const char *encoding; /**< holds iconv-compatible encoding of contents; do not free */ - -} unicode_string_t; - -// functions -status_t vmi_init_complete( - vmi_instance_t *vmi, - void *domain, - uint64_t init_flags, - void *init_data, - vmi_config_t config_mode, - void *config, - vmi_init_error_t *error); - -status_t vmi_destroy( - vmi_instance_t vmi); - -vmi_arch_t vmi_get_library_arch(); - -const char *vmi_get_rekall_path( - vmi_instance_t vmi); - -// memory translations -status_t vmi_translate_kv2p( - vmi_instance_t vmi, - addr_t vaddr, - addr_t *paddr); - -status_t vmi_translate_uv2p( - vmi_instance_t vmi, - addr_t vaddr, - vmi_pid_t pid, - addr_t *paddr); - -status_t vmi_translate_ksym2v( - vmi_instance_t vmi, - const char *symbol, - addr_t *vaddr); - -status_t vmi_translate_sym2v( - vmi_instance_t vmi, - const access_context_t *ctx, - const char *symbol, - addr_t *vaddr); - -const char* vmi_translate_v2sym( - vmi_instance_t vmi, - const access_context_t *ctx, - addr_t rva); - -const char* vmi_translate_v2ksym( - vmi_instance_t vmi, - const access_context_t *ctx, - addr_t va); - -status_t vmi_pid_to_dtb( - vmi_instance_t vmi, - vmi_pid_t pid, - addr_t *dtb); - -status_t vmi_dtb_to_pid( - vmi_instance_t vmi, - addr_t dtb, - vmi_pid_t *pid); - -status_t vmi_pagetable_lookup( - vmi_instance_t vmi, - addr_t dtb, - addr_t vaddr, - addr_t *paddr); - -status_t vmi_pagetable_lookup_extended( - vmi_instance_t vmi, - addr_t dtb, - addr_t vaddr, - page_info_t *info); - -status_t vmi_read( - vmi_instance_t vmi, - const access_context_t *ctx, - size_t count, - void *buf, - size_t *bytes_read); - -status_t vmi_read_8( - vmi_instance_t vmi, - const access_context_t *ctx, - uint8_t * value); - -status_t vmi_read_16( - vmi_instance_t vmi, - const access_context_t *ctx, - uint16_t * value); - -status_t vmi_read_32( - vmi_instance_t vmi, - const access_context_t *ctx, - uint32_t * value); - -status_t vmi_read_64( - vmi_instance_t vmi, - const access_context_t *ctx, - uint64_t * value); - -status_t vmi_read_addr( - vmi_instance_t vmi, - const access_context_t *ctx, - addr_t *value); - -char *vmi_read_str( - vmi_instance_t vmi, - const access_context_t *ctx); - -unicode_string_t *vmi_read_unicode_str( - vmi_instance_t vmi, - const access_context_t *ctx); - -status_t vmi_read_ksym( - vmi_instance_t vmi, - const char *sym, - size_t count, - void *buf, - size_t *bytes_read -); - -status_t vmi_read_va( - vmi_instance_t vmi, - addr_t vaddr, - vmi_pid_t pid, - size_t count, - void *buf, - size_t *bytes_read -); - -status_t vmi_read_pa( - vmi_instance_t vmi, - addr_t paddr, - size_t count, - void *buf, - size_t *bytes_read -); - -status_t vmi_read_8_ksym( - vmi_instance_t vmi, - char *sym, - uint8_t * value); - -status_t vmi_read_16_ksym( - vmi_instance_t vmi, - char *sym, - uint16_t * value); - -status_t vmi_read_32_ksym( - vmi_instance_t vmi, - char *sym, - uint32_t * value); - -status_t vmi_read_64_ksym( - vmi_instance_t vmi, - char *sym, - uint64_t * value); - -status_t vmi_read_addr_ksym( - vmi_instance_t vmi, - char *sym, - addr_t *value); - -char *vmi_read_str_ksym( - vmi_instance_t vmi, - char *sym); - -status_t vmi_read_8_va( - vmi_instance_t vmi, - addr_t vaddr, - vmi_pid_t pid, - uint8_t * value); - -status_t vmi_read_16_va( - vmi_instance_t vmi, - addr_t vaddr, - vmi_pid_t pid, - uint16_t * value); - -status_t vmi_read_32_va( - vmi_instance_t vmi, - addr_t vaddr, - vmi_pid_t pid, - uint32_t * value); - -status_t vmi_read_64_va( - vmi_instance_t vmi, - addr_t vaddr, - vmi_pid_t pid, - uint64_t * value); - -status_t vmi_read_addr_va( - vmi_instance_t vmi, - addr_t vaddr, - vmi_pid_t pid, - addr_t *value); - -char *vmi_read_str_va( - vmi_instance_t vmi, - addr_t vaddr, - vmi_pid_t pid); - -unicode_string_t *vmi_read_unicode_str_va( - vmi_instance_t vmi, - addr_t vaddr, - vmi_pid_t pid); - -status_t vmi_convert_str_encoding( - const unicode_string_t *in, - unicode_string_t *out, - const char *outencoding); - -void vmi_free_unicode_str( - unicode_string_t *p_us); - -status_t vmi_read_8_pa( - vmi_instance_t vmi, - addr_t paddr, - uint8_t * value); - -status_t vmi_read_16_pa( - vmi_instance_t vmi, - addr_t paddr, - uint16_t * value); - -status_t vmi_read_32_pa( - vmi_instance_t vmi, - addr_t paddr, - uint32_t * value); - -status_t vmi_read_64_pa( - vmi_instance_t vmi, - addr_t paddr, - uint64_t * value); - -status_t vmi_read_addr_pa( - vmi_instance_t vmi, - addr_t paddr, - addr_t *value); - -char *vmi_read_str_pa( - vmi_instance_t vmi, - addr_t paddr); - -// write -status_t vmi_write( - vmi_instance_t vmi, - const access_context_t *ctx, - size_t count, - void *buf, - size_t *bytes_written); - -status_t vmi_write_ksym( - vmi_instance_t vmi, - char *sym, - size_t count, - void *buf, - size_t *bytes_written); - -status_t vmi_write_va( - vmi_instance_t vmi, - addr_t vaddr, - vmi_pid_t pid, - size_t count, - void *buf, - size_t *bytes_written); - -status_t vmi_write_pa( - vmi_instance_t vmi, - addr_t paddr, - size_t count, - void *buf, - size_t *bytes_written); - -status_t vmi_write_8( - vmi_instance_t vmi, - const access_context_t *ctx, - uint8_t * value); - -status_t vmi_write_16( - vmi_instance_t vmi, - const access_context_t *ctx, - uint16_t * value); - -status_t vmi_write_32( - vmi_instance_t vmi, - const access_context_t *ctx, - uint32_t * value); - -status_t vmi_write_64( - vmi_instance_t vmi, - const access_context_t *ctx, - uint64_t * value); - -status_t vmi_write_addr( - vmi_instance_t vmi, - const access_context_t *ctx, - addr_t * value); - -status_t vmi_write_8_ksym( - vmi_instance_t vmi, - char *sym, - uint8_t * value); - -status_t vmi_write_16_ksym( - vmi_instance_t vmi, - char *sym, - uint16_t * value); - -status_t vmi_write_32_ksym( - vmi_instance_t vmi, - char *sym, - uint32_t * value); - -status_t vmi_write_64_ksym( - vmi_instance_t vmi, - char *sym, - uint64_t * value); - -status_t vmi_write_addr_ksym( - vmi_instance_t vmi, - char *sym, - addr_t * value); - -status_t vmi_write_8_va( - vmi_instance_t vmi, - addr_t vaddr, - vmi_pid_t pid, - uint8_t * value); - -status_t vmi_write_16_va( - vmi_instance_t vmi, - addr_t vaddr, - vmi_pid_t pid, - uint16_t * value); - -status_t vmi_write_32_va( - vmi_instance_t vmi, - addr_t vaddr, - vmi_pid_t pid, - uint32_t * value); - -status_t vmi_write_64_va( - vmi_instance_t vmi, - addr_t vaddr, - vmi_pid_t pid, - uint64_t * value); - -status_t vmi_write_addr_va( - vmi_instance_t vmi, - addr_t vaddr, - vmi_pid_t pid, - addr_t * value); - -status_t vmi_write_8_pa( - vmi_instance_t vmi, - addr_t paddr, - uint8_t * value); - -status_t vmi_write_16_pa( - vmi_instance_t vmi, - addr_t paddr, - uint16_t * value); - -status_t vmi_write_32_pa( - vmi_instance_t vmi, - addr_t paddr, - uint32_t * value); - -status_t vmi_write_64_pa( - vmi_instance_t vmi, - addr_t paddr, - uint64_t * value); - -status_t vmi_write_addr_pa( - vmi_instance_t vmi, - addr_t paddr, - addr_t * value); - -// print util functions -void vmi_print_hex( - unsigned char *data, - unsigned long length); - -void vmi_print_hex_ksym( - vmi_instance_t vmi, - char *sym, - size_t length); - -void vmi_print_hex_va( - vmi_instance_t vmi, - addr_t vaddr, - vmi_pid_t pid, - size_t length); - -void vmi_print_hex_pa( - vmi_instance_t vmi, - addr_t paddr, - size_t length); - -// get functions -char *vmi_get_name( - vmi_instance_t vmi); - -uint64_t vmi_get_vmid( - vmi_instance_t vmi); - -status_t vmi_get_access_mode( - vmi_instance_t vmi, - void *domain, - uint64_t init_flags, - void* init_data, - vmi_mode_t *mode); - -page_mode_t vmi_get_page_mode( - vmi_instance_t vmi, - unsigned long vcpu); - -uint8_t vmi_get_address_width( - vmi_instance_t vmi); - -os_t vmi_get_ostype( - vmi_instance_t vmi); - -win_ver_t vmi_get_winver( - vmi_instance_t vmi); - -const char *vmi_get_winver_str( - vmi_instance_t vmi); - -win_ver_t vmi_get_winver_manual( - vmi_instance_t vmi, - addr_t kdvb_pa); - -status_t vmi_get_offset( - vmi_instance_t vmi, - const char *offset_name, - addr_t *offset); - -status_t vmi_get_kernel_struct_offset( - vmi_instance_t vmi, - const char* struct_name, - const char* member, - addr_t *addr); - -uint64_t vmi_get_memsize( - vmi_instance_t vmi); - -addr_t vmi_get_max_physical_address( - vmi_instance_t vmi); - -unsigned int vmi_get_num_vcpus ( - vmi_instance_t vmi); - -status_t vmi_get_vcpureg( - vmi_instance_t vmi, - uint64_t *value, - reg_t reg, - unsigned long vcpu); - -status_t vmi_get_vcpuregs( - vmi_instance_t vmi, - registers_t *regs, - unsigned long vcpu); - -status_t vmi_set_vcpureg( - vmi_instance_t vmi, - uint64_t value, - reg_t reg, - unsigned long vcpu); - -status_t vmi_set_vcpuregs( - vmi_instance_t vmi, - registers_t *regs, - unsigned long vcpu); - -status_t vmi_pause_vm( - vmi_instance_t vmi); - -status_t vmi_resume_vm( - vmi_instance_t vmi); - -// cache functions -void vmi_v2pcache_flush( - vmi_instance_t vmi, - addr_t dtb); - -void vmi_v2pcache_add( - vmi_instance_t vmi, - addr_t va, - addr_t dtb, - addr_t pa); - -void vmi_symcache_flush( - vmi_instance_t vmi); - -void vmi_symcache_add( - vmi_instance_t vmi, - addr_t base_addr, - vmi_pid_t pid, - char *sym, - addr_t va); - -void vmi_rvacache_flush( - vmi_instance_t vmi); - -void vmi_rvacache_add( - vmi_instance_t vmi, - addr_t base_addr, - vmi_pid_t pid, - addr_t rva, - char *sym); - -void vmi_pidcache_flush( - vmi_instance_t vmi); - -void vmi_pidcache_add( - vmi_instance_t vmi, - vmi_pid_t pid, - addr_t dtb); From 44ef7209330f9fdcb35d419516d34172e061826c Mon Sep 17 00:00:00 2001 From: Mathieu Tarral Date: Wed, 27 Jun 2018 16:40:29 +0300 Subject: [PATCH 2/3] add libvmi in the requirements.txt --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index d33f9ee..8df35d9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,3 +9,4 @@ nose2 libvirt-python six pkgconfig +libvmi From 4c252da29993708c7c4749f3bcadcf5003e25052 Mon Sep 17 00:00:00 2001 From: Mathieu Tarral Date: Wed, 27 Jun 2018 16:45:25 +0300 Subject: [PATCH 3/3] update references to nitro.libvmi module --- main.py | 5 +++-- nitro/backends/backend.py | 2 +- nitro/backends/factory.py | 2 +- nitro/backends/linux/backend.py | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/main.py b/main.py index bf1be87..254d585 100755 --- a/main.py +++ b/main.py @@ -18,16 +18,17 @@ from pprint import pprint import libvirt +from libvmi import LibvmiError from docopt import docopt from nitro.nitro import Nitro -from nitro.libvmi import LibvmiError + def init_logger(): logger = logging.getLogger() logger.addHandler(logging.StreamHandler()) - logger.setLevel(logging.INFO) + logger.setLevel(logging.DEBUG) class NitroRunner: diff --git a/nitro/backends/backend.py b/nitro/backends/backend.py index 247e096..6483495 100644 --- a/nitro/backends/backend.py +++ b/nitro/backends/backend.py @@ -9,7 +9,7 @@ from collections import defaultdict from nitro.event import SyscallDirection -from nitro.libvmi import LibvmiError +from libvmi import LibvmiError class Backend: """ diff --git a/nitro/backends/factory.py b/nitro/backends/factory.py index 8234f7d..854541c 100644 --- a/nitro/backends/factory.py +++ b/nitro/backends/factory.py @@ -1,4 +1,4 @@ -from nitro.libvmi import VMIOS, Libvmi +from libvmi import VMIOS, Libvmi from nitro.backends.linux import LinuxBackend from nitro.backends.windows import WindowsBackend diff --git a/nitro/backends/linux/backend.py b/nitro/backends/linux/backend.py index e35114e..915387b 100644 --- a/nitro/backends/linux/backend.py +++ b/nitro/backends/linux/backend.py @@ -7,9 +7,9 @@ from ctypes import sizeof, c_void_p +from libvmi import LibvmiError from nitro.syscall import Syscall from nitro.event import SyscallDirection -from nitro.libvmi import LibvmiError from nitro.backends.linux.process import LinuxProcess from nitro.backends.backend import Backend from nitro.backends.linux.arguments import LinuxArgumentMap