Skip to content

Commit

Permalink
Add LibVMI VM example with Buildroot
Browse files Browse the repository at this point in the history
Buildroot is used to cross-compile LibVMI with its dependencies and
to produce the bzImage and rootfs.

The following definitions were added:

- `VOLATILITY_PROFILE_PATH`
- `REKALL_PROFILE_PATH`
- `ENABLE_BUILD_EXAMPLES`

To build the LibVMI VM example, one needs to first create a profile of
the host kernel with rekall or volatility and provide its path during
cmake configuration time. Information to generate a profile can be found
in the LibVMI repo or in the DRAKVUF website. e.g.:

```
cmake ../hypervisor -DCACHE_DIR=/tmp/boxy_cache \
	-DENABLE_BUILD_EXAMPLES=ON \
	-DREKALL_PROFILE_PATH=<path_to_profile.json>
make
```

The LibVMI process list example can be run as follows:

```
./prefixes/x86_64-userspace-elf/bin/bfexec \
    --bzimage --path prefixes/vms/buildroot/bzImage \
    --initrd prefixes/vms/buildroot/rootfs.cpio.gz --uart=0x3F8 \
    --verbose --size=0x8000000 \
    --cmdline="vmi=/usr/bin/vmi-process-list,-n,dom0"
```

Notes:

Vmilinux provides vmi-init, an init app that can start an application
with arguments. It does so by parsing the kernel cmdline.

vmi-init can also be compiled with statically in order to be the only
application running as init. In this case, vmi-init does some pre main
work to populate main args and properly calls the linked main, with no
extra work needed from the linked application.

On Windows, Vagrant can be used to generate the guest VM.

To facilitate libvmi development, one can use the following buildroot
options:

- `BR2_LIBVMI_DEBUG=y` enable libvmi debug definitions
- `BR2_LIBVMI_PATH=<path>` use local copy of libvmi directory when set
  • Loading branch information
chp-io committed Aug 4, 2020
1 parent 689943c commit d8e66c9
Show file tree
Hide file tree
Showing 24 changed files with 891 additions and 1 deletion.
23 changes: 23 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ if(ENABLE_BUILD_GUEST)
include_dependency(BOXY_SOURCE_DEPENDS_DIR linux)
endif()

if(ENABLE_BUILD_GUEST AND ENABLE_BUILD_EXAMPLES)
include_dependency(BOXY_SOURCE_DEPENDS_DIR buildroot)
endif()

# ------------------------------------------------------------------------------
# VMM
# ------------------------------------------------------------------------------
Expand Down Expand Up @@ -86,3 +90,22 @@ if(NOT WIN32 AND NOT CYGWIN)
DEPENDS bfintrinsics
)
endif()

# ------------------------------------------------------------------------------
# Examples
# ------------------------------------------------------------------------------

if(ENABLE_BUILD_EXAMPLES AND NOT WIN32 AND NOT CYGWIN)
add_subproject(
vmilinux userspace
SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/examples/vmilinux
DEPENDS bflinux
)
endif()

# ------------------------------------------------------------------------------
# Validate Build
# ------------------------------------------------------------------------------

include(${CMAKE_CURRENT_LIST_DIR}/scripts/cmake/validate.cmake)
validate_build()
2 changes: 2 additions & 0 deletions bfsdk/include/bfhypercall.h
Original file line number Diff line number Diff line change
Expand Up @@ -1930,7 +1930,9 @@ hypercall_uart_ndec_op(uint16_t port, uint64_t val)
#define hypercall_enum_domain_op__ldtr_access_rights 0xBF02000000020730
#define hypercall_enum_domain_op__set_ldtr_access_rights 0xBF02000000020731

#ifndef UART_MAX_BUFFER
#define UART_MAX_BUFFER 0x4000
#endif

static inline domainid_t
hypercall_domain_op__create_domain(void)
Expand Down
5 changes: 4 additions & 1 deletion config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

set(CACHE_DIR ${CMAKE_CURRENT_LIST_DIR}/cache)
if(NOT DEFINED CACHE_DIR)
set(CACHE_DIR ${CMAKE_CURRENT_LIST_DIR}/cache)
endif()

file(MAKE_DIRECTORY ${CACHE_DIR})

set(CMAKE_BUILD_TYPE Release)
Expand Down
2 changes: 2 additions & 0 deletions examples/buildroot/Config.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
source "$BR2_EXTERNAL_vmilinux_PATH/package/libvmi/Config.in"
source "$BR2_EXTERNAL_vmilinux_PATH/package/vmilinux/Config.in"
69 changes: 69 additions & 0 deletions examples/buildroot/common/post-build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/bin/bash -e
#
# Copyright (C) 2020 Assured Information Security, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

# env REKALL_PROFILE_PATH or VOLATILITY_PROFILE_PATH pointing to a json profile

PROFILE_FILES=(${REKALL_PROFILE_PATH} ${VOLATILITY_PROFILE_PATH})

source "${BR2_EXTERNAL_vmilinux_PATH}/../../scripts/util/colors.sh"

if [[ -z "${REKALL_PROFILE_PATH}" && -z "${VOLATILITY_PROFILE_PATH}" ]]; then
echo -e "${BF_COLOR_RED}Error: a profile environment variable is required.${BF_COLOR_RST}"
echo "Please define REKALL_PROFILE_PATH or VOLATILITY_PROFILE_PATH to a json profile"
exit 1;
fi

LIBVMI_CONF="dom0 {"

for JSON_PROFILE in ${PROFILE_FILES}; do
if [ ! -f "${JSON_PROFILE}" ]; then
echo -e "${BF_COLOR_RED}Missing profile file ${JSON_PROFILE}${BF_COLOR_RST}"
echo ""
exit 1;
fi

[[ $JSON_PROFILE = $REKALL_PROFILE_PATH ]] && JSON_FILE="rekall.json" || JSON_FILE="volatility.json"

if [ -f "${TARGET_DIR}/root/${JSON_FILE}" ]; then
echo "removing \${TARGET_DIR}/root/${JSON_FILE})"
rm ${TARGET_DIR}/root/${JSON_FILE}
fi

echo -e "${BF_COLOR_BLU}Copying host profile for libvmi:${BF_COLOR_RST}"
echo "cp \"${JSON_PROFILE}\" \"${TARGET_DIR}/root/${JSON_FILE}\""
cp "${JSON_PROFILE}" "${TARGET_DIR}/root/${JSON_FILE}"

case "${JSON_FILE}" in
rekall.json)
LIBVMI_CONF="${LIBVMI_CONF}\n\trekall_profile = \"/root/rekall.json\";"
;;
volatility.json)
LIBVMI_CONF="${LIBVMI_CONF}\n\tvolatility_ist = \"/root/volatility.json\";"
;;
*)
;;
esac
done

LIBVMI_CONF="${LIBVMI_CONF}\n}"
printf "${LIBVMI_CONF} > \${TARGET_DIR}/etc/libvmi.conf\n"
printf "${LIBVMI_CONF}" > ${TARGET_DIR}/etc/libvmi.conf
21 changes: 21 additions & 0 deletions examples/buildroot/configs/vmilinux_defconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
BR2_x86_64=y
BR2_x86_core2=y
BR2_TOOLCHAIN_BUILDROOT_GLIBC=y
BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_4_20=y
BR2_PACKAGE_GLIBC_UTILS=y
BR2_TOOLCHAIN_BUILDROOT_CXX=y
BR2_INIT_NONE=y
# BR2_TARGET_ENABLE_ROOT_LOGIN is not set
# BR2_TARGET_GENERIC_GETTY is not set
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_TARBALL=y
BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION="https://github.com/Bareflank/linux/archive/boxy_1.01.tar.gz"
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="${BR2_EXTERNAL_vmilinux_PATH}/../../bflinux/config"
# BR2_PACKAGE_BUSYBOX is not set
# BR2_PACKAGE_IFUPDOWN_SCRIPTS is not set
BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_vmilinux_PATH}/common/post-build.sh"
BR2_TARGET_ROOTFS_CPIO=y
BR2_TARGET_ROOTFS_CPIO_GZIP=y
# BR2_TARGET_ROOTFS_TAR is not set
BR2_PACKAGE_VMILINUX=y
2 changes: 2 additions & 0 deletions examples/buildroot/external.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
name: vmilinux
desc: LibVMI examples with Bareflank Boxy
1 change: 1 addition & 0 deletions examples/buildroot/external.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include $(sort $(wildcard $(BR2_EXTERNAL_vmilinux_PATH)/package/*/*.mk))
10 changes: 10 additions & 0 deletions examples/buildroot/package/cpio/cpio.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
################################################################################
#
# cpio to archive target filesystem
#
################################################################################

# Overrides rootfs cpio config from fs/cpio/cpio.mk
# to prevent it from placing /init

ROOTFS_CPIO_PRE_GEN_HOOKS =
16 changes: 16 additions & 0 deletions examples/buildroot/package/libvmi/Config.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
config BR2_PACKAGE_LIBVMI
bool "libvmi"
depends on BR2_TOOLCHAIN_USES_GLIBC
depends on BR2_USE_WCHAR # glib2
depends on BR2_TOOLCHAIN_HAS_THREADS # glib2
depends on BR2_USE_MMU # glib2
select BR2_PACKAGE_LIBGLIB2
select BR2_PACKAGE_JSON_C
# BR2_STATIC_LIBS
help
LibVMI is a C library with Python bindings that makes it easy to monitor the
low-level details of a running virtual machine by viewing its memory, trapping
on hardware events, and accessing the vCPU registers. This is called virtual
machine introspection.

https://github.com/libvmi/libvmi
40 changes: 40 additions & 0 deletions examples/buildroot/package/libvmi/libvmi.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
################################################################################
#
# LibVMI
#
################################################################################

ifeq ($(BR2_LIBVMI_PATH),)
LIBVMI_VERSION = 1dd5a2e48e43b70b50d7ff4a01ad1fcb3b8cbba7
LIBVMI_SITE = $(call github,chp-io,libvmi,$(LIBVMI_VERSION))
LIBVMI_REPO = https://github.com/chp-io/libvmi
else
LIBVMI_SITE = ${BR2_LIBVMI_PATH}
LIBVMI_SITE_METHOD = local
LIBVMI_OVERRIDE_SRCDIR_RSYNC_EXCLUSIONS = --exclude '/deps'
endif

LIBVMI_LICENSE = LGPLv3
LIBVMI_LICENSE_FILES = COPYING

LIBVMI_DEPENDENCIES = json-c libglib2
HOST_LIBVMI_DEPENDENCIES = host-pkgconf host-bison host-flex host-libglib2
LIBVMI_CONF_OPTS = \
-DENABLE_XENSTORE=OFF \
-DENABLE_XEN=OFF \
-DENABLE_FILE=OFF \
-DENABLE_VMIFS=OFF \
-DENABLE_KVM=OFF \
-DBUILD_EXAMPLES=ON \
-DENABLE_FREEBSD=OFF \
-DENABLE_STATIC=OFF \
-DENABLE_PAGE_CACHE=OFF

ifeq ($(BR2_LIBVMI_DEBUG),y)
LIBVMI_CONF_OPTS += -DCMAKE_BUILD_TYPE=Debug \
-DVMI_DEBUG=__VMI_DEBUG_ALL
else
LIBVMI_CONF_OPTS += -DCMAKE_BUILD_TYPE=Release
endif

$(eval $(cmake-package))
7 changes: 7 additions & 0 deletions examples/buildroot/package/vmilinux/Config.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
config BR2_PACKAGE_VMILINUX
bool "vmilinux"
depends on BR2_INSTALL_LIBSTDCPP
select BR2_PACKAGE_LIBVMI
help
vmilinux starts a vmi app with populated cmdline parsed from the kernel's
cmdline.
36 changes: 36 additions & 0 deletions examples/buildroot/package/vmilinux/vmilinux.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
################################################################################
#
# vmilinux
#
################################################################################

VMILINUX_SITE = ${BR2_EXTERNAL_vmilinux_PATH}/../.. # ${BOXY_SOURCE_ROOT_DIR}
VMILINUX_SITE_METHOD = local
VMILINUX_OVERRIDE_SRCDIR_RSYNC_EXCLUSIONS = --exclude build --exclude 'build_*'

VMILINUX_LICENSE = MIT

# VMILINUX_SUBDIR = hypervisor
VMILINUX_SUPPORTS_IN_SOURCE_BUILD = NO
VMILINUX_CONF_OPTS = -DBUILD_SHARED_LIBS=NO
VMILINUX_MAKE_OPTS = vmilinux_x86_64-userspace-elf

define VMILINUX_CONFIGURE_CMDS
(cd $(@D); \
[[ -d buildroot-build ]] || mkdir buildroot-build; \
cd buildroot-build; \
$(TARGET_MAKE_ENV) cmake ../hypervisor \
-DENABLE_BUILD_EXAMPLES=ON \
-DREKALL_PROFILE_PATH=${REKALL_PROFILE_PATH} \
-DVOLATILITY_PROFILE_PATH=${VOLATILITY_PROFILE_PATH} \
-DCACHE_DIR=${CACHE_DIR} \
)
endef

define VMILINUX_INSTALL_TARGET_CMDS
$(INSTALL) -m 0755 \
-D $(@D)/buildroot-build/prefixes/initrd/sbin/init-vmi \
$(TARGET_DIR)/sbin/init
endef

$(eval $(cmake-package))
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
From e621c74f96c7f4093829d7a4b91f91c589bb3949 Mon Sep 17 00:00:00 2001
From: Christopher Pelloux <git@chp.io>
Date: Thu, 4 Jun 2020 21:11:26 -0400
Subject: [PATCH 1/1] package/json-c: bump version to 0.14

Notes:

- json-c now uses cmake instead of autoconf
- This version also brings support to the much welcomed feature for
parsing uint64_t types

Signed-off-by: Christopher Pelloux <git@chp.io>
---
package/json-c/json-c.hash | 2 +-
package/json-c/json-c.mk | 14 +++-----------
2 files changed, 4 insertions(+), 12 deletions(-)

diff --git a/package/json-c/json-c.hash b/package/json-c/json-c.hash
index 0e03007476..93eaff67c3 100644
--- a/package/json-c/json-c.hash
+++ b/package/json-c/json-c.hash
@@ -1,4 +1,4 @@
# From https://github.com/json-c/json-c/wiki
-sha256 b87e608d4d3f7bfdd36ef78d56d53c74e66ab278d318b71e6002a369d36f4873 json-c-0.13.1.tar.gz
+sha256 b377de08c9b23ca3b37d9a9828107dff1de5ce208ff4ebb35005a794f30c6870 json-c-0.14.tar.gz
# Locally calculated
sha256 74c1e6ca5eba76b54d0ad00d4815c8315c1b3bc45ff99de61d103dc92486284c COPYING
diff --git a/package/json-c/json-c.mk b/package/json-c/json-c.mk
index 2788fe563b..3e17effdad 100644
--- a/package/json-c/json-c.mk
+++ b/package/json-c/json-c.mk
@@ -4,19 +4,11 @@
#
################################################################################

-JSON_C_VERSION = 0.13.1
+JSON_C_VERSION = 0.14
JSON_C_SITE = https://s3.amazonaws.com/json-c_releases/releases
JSON_C_INSTALL_STAGING = YES
JSON_C_LICENSE = MIT
JSON_C_LICENSE_FILES = COPYING

-# update config.h.in timestamp to avoid autoheader run
-define JSON_C_UPDATE_CONFIG_TIMESTAMP
- touch $(@D)/config.h.in
-endef
-
-JSON_C_POST_EXTRACT_HOOKS += JSON_C_UPDATE_CONFIG_TIMESTAMP
-HOST_JSON_C_POST_EXTRACT_HOOKS += JSON_C_UPDATE_CONFIG_TIMESTAMP
-
-$(eval $(autotools-package))
-$(eval $(host-autotools-package))
+$(eval $(cmake-package))
+$(eval $(host-cmake-package))
--
2.17.1

63 changes: 63 additions & 0 deletions examples/vmilinux/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#
# Copyright (C) 2019 Assured Information Security, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

cmake_minimum_required(VERSION 3.13)
project(vmilinux C CXX)

init_project(vmilinux INTERFACE)

target_link_libraries(vmilinux INTERFACE userspace::bflinux)

if (${SVMI_STATIC_INIT})
add_executable(init-vmi
${CMAKE_CURRENT_LIST_DIR}/tests/test-init.cpp
${CMAKE_CURRENT_LIST_DIR}/src/init-vmi.cpp
)
target_compile_definitions(init-vmi PUBLIC
SVMI_STATIC_INIT
SVMI_INIT_NO_PROC_MOUNT
SVMI_INIT_NO_PRINTK
SVMI_CMDLINE_PATH="${CMAKE_CURRENT_LIST_DIR}/tests/cmdline.txt"
)
set(INIT_VMI_BIN init-vmi)
else()
add_executable(init-vmi ${CMAKE_CURRENT_LIST_DIR}/src/init-vmi.cpp)
set(INIT_VMI_BIN init-vmi)
endif()
target_link_options(init-vmi PRIVATE -static)
set_target_properties(init-vmi PROPERTIES CXX_STANDARD 20)
target_include_directories(init-vmi PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
$<BUILD_INTERFACE:${BOXY_SOURCE_BFEXEC_DIR}/include>
)
target_link_libraries(${INIT_VMI_BIN} PUBLIC vmilinux)

add_custom_target(
package ALL
COMMAND ${CMAKE_COMMAND} -E copy ${INIT_VMI_BIN} ${PREFIXES_DIR}/initrd/sbin/
COMMAND ${CMAKE_COMMAND} -E chdir ${PREFIXES_DIR}/initrd/ bash ${BOXY_SOURCE_ROOT_DIR}/bflinux/build.sh
COMMAND ${CMAKE_COMMAND} -E echo initrd built for vmilinux
VERBATIM
)

add_dependencies(package init-vmi)

fini_project()
Loading

0 comments on commit d8e66c9

Please sign in to comment.