Contents

KVM Malware Lab Guide

This is my guide for setting up your very own malware lab using KVM.

Before you start, this guide assumes you have an AirVPN subscription or another equivalent one, which provides a .ovpn file.

NOTE: I like to have internet enabled on my analysis VMs and this comes with extra security considerations and potential risk if you do not perform the setup correctly. It is recommended that you have your KVM host machine on a DMZ. Most home routers do have DMZ settings, just consult your manual. This guide is not intended for beginners.

If you have used VirtualBox or VMWare Workstation in the past, Spice is just like the guest tools for these but for KVM, which allows you to copy/paste and copy samples to your VMs from your host machine.

NOTE: This is not a very stealthy setup as of yet, so do expect some malware to detect your VMs. I will continue to update this guide for stealth once I have a server or workstation. This requires forking the qemu code and modifying it.

Once this guide is completed, you should have networking that looks like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  ┌────────┐
  │Internet│
  └───┬────┘
┌─────┴──────┐
│Host Machine│ Kernel Virtual Machine (KVM) on DMZ
└─────┬──────┘
    ┌─┴─┐
    │NAT│ (default)
    └─┬─┘
  ┌───┴───┐ ┌────────┐
  │PFSense├─┤Isolated│ LAN 10.0.1.1/24 (vmbr0)
  └───────┘ └───┬────┘
             ┌──┴───┐
             │Remnux│ Static Analysis and Interception
             └──┬───┘
            ┌───┴────┐
            │Isolated│ Analysis LAN 10.0.2.1/24 (vmbr1)
            └─┬──────┤
              │      │
      ┌───────┴───┐ ┌┴──────┐
      │Analysis VM│ │Windows│ Dynamic Analysis
      └───────────┘ └───────┘

Install KVM

This section of the guide will show you how to install KVM on your Linux host.

  • Verify you have virtualization enabled
1
2
3
grep -Po '(vmx|svm)[^\x20]+' /proc/cpuinfo | sort | uniq # For Host Machine
cat /sys/module/kvm_intel/parameters/nested              # Nested Virtualization Only (intel)
cat /sys/module/kvm_amd/parameters/nested                # Nested Virtualization Only (amd)
  • Enable Nested Virtualization (optional)
1
2
3
4
5
6
sudo nano /etc/modprobe.d/kvm.conf # Nested Virtualization Configuration File
# Add the following configuration
: '
options kvm_intel nested=1
' # save then reboot
sudo reboot
  • If there is any output from the previous command then virtualization is enabled, otherwise, enable it in your bios and try again NOTE: Using nested virtualization will come with significant performance costs, it is much more advisable to use Linux with KVM on bare metal
  • Install dependencies
1
2
sudo apt update
sudo apt install -y virt-manager qemu-kvm build-essential python-is-python3
  • Verify that libvirtd service is running
1
2
sudo systemctl enable libvirtd
sudo systemctl start libvirtd
  • Add current user to the libvirt group
1
sudo usermod -a -G libvirt $USER
  • Install modified version of SeaBios (modifies src/config.h to more realistic values)
1
2
3
4
5
git clone https://github.com/c3rb3ru5d3d53c/seabios.git
cd seabios/
make
sudo cp /usr/share/seabios/bios.bin /usr/share/seabios/bios.bin.bak
sudo cp out/bios.bin /usr/share/seabios/bios.bin
  • If you want virt-manager to be able to access your home directory, you may need to set upstream permissions (this step is optional)
1
sudo setfacl -m u:libvirt-qemu:rx /home/$USER
  • Once all has been completed do a reboot
1
sudo reboot

Create VMS

This section will guide you through the creation of the malware lab with KVM using virt-manager.

Create Virtual Networks

  • Edit -> Connection Details -> + -> vmbr0 Isolated (PFSense LAN)
    • Disable both IPV4 and IPv6 (Provided by PFSense)
  • Edit -> Connection Details -> + -> vmbr1 Isolated (Analysis LAN)
    • Disable both IPV4 and IPv6 (Provided by Remnux)

Create PFSense VM

The primary purpose of the PFSense VM is to provide an easy way to manage firewall rules between your home or work network and the internet. I know most people disable their internet when analyzing malware. However, I like to use an anonymous VPN and with that comes additional risk and considerations.

1
qemu-img create -f qcow2 pfsense.qcow2 16G
  • Create a new virtual machine
    • Import Existing Disk Image
    • Select pfsense.qcow2 as the storage path
    • Select FreeBSD as the OS
    • Name: pfsense
    • Customize configuration before install
    • Set first NIC to NAT
    • Add Hardware -> Network -> vmbr0 (PFSense Network)
    • Add Hardware -> Network -> CDROM Device -> Manager -> PFSense ISO
    • Boot Options -> Set CDROM device as first in boot order
  • Start the VM
  • Set LAN as 10.0.1.1/24 in PFSense setup

Create Remnux VM (Ubuntu 22.04)

The primary purpose of this VM is to allow you to perform static analysis of binaries using IDA, Ghidra or Cutter but also acts as the gateway for your entire analysis subnet. This gives you full control over the DNS and DHCP server for traffic interception and more.

NOTE: The official remnux distribution OS is quite outdated, to solve this it is recommended to use the latest LTS image from Ubuntu as the VM and instead use remnux within that VM as a container.

1
qemu-img create -f qcow2 remnux.qcow2 40G
  • Create a new virtual machine
    • Import existing disk image
    • Select remnux.qcow2 as the storage path
    • Select Ubuntu as the OS
    • Name: remnux
    • Customize configuration before install
    • Set first NIC to vmbr0 (PFSense Network)
    • Add Hardware -> Network -> vmbr1 (Analysis Network)
    • Add Hardware -> Storage -> CDROM Device-> Manage -> Ubuntu ISO Image
    • Boot Options -> Set CDROM device as first in boot order
  • Start VM
  • Install dependancies
1
2
3
4
5
6
sudo apt update
sudo apt install dnsmasq isc-dhcp-server openvpn docker.io spice-vdagent
sudo systemctl enable spice-vdagent
sudo systemctl enable docker
sudo usermod -a -G docker $USER
# logout and login again
  • Create your remnux docker container
1
docker run --rm -it -v $(pwd):$HOME -u remnux remnux/remnux-distro:focal bash
  • Set up the interfaces
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
sudo nano /etc/netplan/01-network-manager-all.yaml
# Replace it with the following contents
: 'network:
  version: 2
  renderer: networkd
  ethernets:
    enp1s0:
      dhcp4: yes
    enp7s0:
      addresses:
        - 10.0.2.1/24
'
  • Disable dnsmasq conflicts with systemd-resolved
1
2
3
4
5
sudo nano /etc/systemd/resolved.conf
# Append DNSStubListener=no to the end of the file and save
sudo systemctl restart systemd-resolved
sudo systemctl enable dnsmasq
sudo systemctl restart dnsmasq
  • Setup the dhcp server
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
sudo nano /etc/dhcp/dhcpd.conf
# Add the following content to the configuration
: 'subnet 10.0.2.0 netmask 255.255.255.0 {
   option domain-name "malware.wtf";
   default-lease-time 600;
   max-lease-time 7200;
   option routers 10.0.2.1;
   option subnet-mask 255.255.255.0;
   option broadcast-address 10.0.2.255;
   option domain-name-servers 10.0.2.1;
   range 10.0.2.2 10.0.2.254;
}'
sudo systemctl enable isc-dhcp-server
sudo systemctl restart isc-dhcp-server
  • Browse to https://10.0.1.1 and login with admin:pfsense and setup your own password for PFSense.
    • Add firewall rules to block your local network, in my case it was to block everything from LAN net to 192.168.0.1/24.
    • Apply the changes
  • Setup internet forwarding
1
2
3
4
sudo iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
sudo apt install iptables-persistent # Say yes to both prompts
sudo nano /etc/sysctl.conf # Uncomment the line with net.ipv4.ip_forward=1
sudo sysctl -w net.ipv4.ip_forward=1
  • Create a script to allow to you start your VPN
1
2
3
4
5
6
7
8
nano vpn.sh
# Add the following contents and save
: '
#!/usr/bin/env bash
openvpn --daemon --config AirVPN_All-servers_UDP-443.ovpn
'
chmod +x vpn.sh
sudo ./vpn.sh
  • Setup TLS Decryption with MITMProxy
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
sudo apt update
sudo apt install -y wireshark tshark # Say yes to non-super user packet capture
sudo usermod -a -G wireshark $USER   # logout then login again
wget https://snapshots.mitmproxy.org/8.1.0/mitmproxy-8.1.0-linux.tar.gz
tar -xzvf mitmproxy-8.1.0-linux.tar.gz
sudo mv mitmdump /usr/bin/
sudo mv mitmproxy /usr/bin/
sudo mv mitmweb /usr/bin/
wget https://gist.githubusercontent.com/c3rb3ru5d3d53c/d9eb9d752882fcc630d338a6b2461777/raw/f56cbef4b98c7bad8f265534eabf696923b649a2/mitmpcap
chmod +x mitmpcap
sudo mv mitmpcap /usr/bin/
wget https://gist.githubusercontent.com/c3rb3ru5d3d53c/3bc8041a182467ccae0207394c1e16b3/raw/33bf201da721ae8f8dc057480221a3c6612e7c11/mitmhttp
chmod +x mitmhttp
sudo mv mitmhttp /usr/bin/
sudo mkdir /root/.mitmproxy

Once completed, you should be able to reboot and run sudo ./vpn.sh to get connected to the internet. NOTE: The internet will not work on the Analysis LAN unless you have VPN enabled as we set the internet to be forwarded through tun0 for openvpn. This is a good thing, this means it will force you to use an anonymous VPN and reduce risk of leaking your actual IP address.

Create Windows VM

This VM will sit on the Analysis LAN, its main purpose is to dynamically analyze malware by executing it. This includes debugging, tracing API calls and more.

NOTE: With a Windows VM it is very important to ensure your boot drive is using the VirtIO drivers.

1
qemu-img create -f qcow2 windows.qcow2 128G
  • Create a new virtual machine
    • Import existing disk image
    • Select windows.qcow2 as the storage path
    • Select Windows as the OS
    • Name: windows
    • Customize configuration before install
    • Set first NIC to vmbr1 (Analysis LAN)
    • Add Hardware -> Storage -> CDROM Device-> Manage -> Windows ISO Image
    • Add Hardware -> Storage CDROM Device -> Manage -> VirtIO ISO
    • Boot Options -> Set CDROM device for Windows ISO to boot first
    • Remove the SATA Disk and replace with one for VirtIO pointing to windows.qcow2
    • Start installation
  • During the Windows install the VirtIO disk will not show unless you browse to the VirtIO ISO and select the folder with the drivers for your version of Windows. Once completed, you can proceed with the installation.
  • Once Windows is installed, open Device Manager and identify all the drivers with question marks and update them using the VirtIO ISO CDROM.
  • Download and install Spice Guest Tools
  • Reboot the VM

If you are unable to boot using the VirtIO driver, try the following troubleshooting steps:

  • Open an elevated command prompt and set the VM to boot into safe mode by typing
    • bcdedit /set {current} safeboot minimal
  • shut-down the VM and change the boot device type to virtio
  • boot the VM. It will enter in safe mode.
  • in the booted VM reset the bcdedit settings to allow the machine to boot into the Normal mode by typing (in an elevated command prompt again):
    • bcdedit /deletevalue {current} safeboot

Reference: Windows 10 in KVM: change boot disk to Virtio

Once you have completed all necessary steps, it is recommended to remove the CDROM drive for the VirtIO drivers.

Installing TLS Decryption Certificates

This section of the guide will discuss how to get TLS decryption working on your Remnux VM so you can transparently decrypt TLS and capture secrets and pcaps from the analysis network as long as the devices have the root CA installed.

  • On your Remnux machine do the following commands
1
2
sudo mitmhttp -i <analysis-network-interface> --enable
mitmproxy --mode transparent --listen-host 0.0.0.0 --listen-port 8080
  • On your Windows VM open a browser and go to mitm.it then follow either the Manual or Automated install instructions
    • Manual Install
      • On the webpage download the certificate for Windows
      • Double click the P12 file to start the import wizard
      • Select a certificate store location. This determines who will trust the certificate – only the current Windows user or everyone on the machine. Click Next.
      • Click Next again
      • Leave Password blank and click Next
      • Select Place all certificates in the following store, then click Browse, and select Trusted Root Certification Authorities. Click OK and Next
      • Click Finish
      • Click Yes to confirm the warning dialog.
    • Automated Install
      • certutil.exe -addstore root mitmproxy-ca-cert.cer
    • In your browser visit https://example.com to verify a successful decryption in the mitmproxy interface

If the above steps were successful, you can now use the tool mitmpcap to view traffic live with mitmproxy but also use it to capture TLS secrets and a pcap for analysis later.

1
mitmpcap -i enp7s0 -w dump.pcap -m transparent -p 8080 -s secrets.txt -v 1 -f libpcap

Once you have finished your capture, press Q then Y to exit mitmproxy. You should then notice you have the files dump.pcap and secrets.txt. The following steps will show you how to use Wireshark to analyze your capture.

  • Open dump.pcap with Wireshark
  • Edit -> Preferences -> Protocols -> TLS -> (Pre)-Master-Secret log filename Browse -> select secrets.txt
  • In the filter bar type http and press Enter
  • You should now have decrypted TLS traffic

Once you have completed capturing your traffic and no longer wish to perform interception, disable the redirection by executing the following.

1
sudo mitmhttp -i <analysis-network-interface> --disable

Install Malware Analysis Tools

Once you have completed the networking and VM creation, you can install your favorite malware analysis tools!

You can get a list of my favorite tools here.

Establishing a Clean Environment

Once you have completed installing your favorite tools, establish a clean environment by taking snapshots of every VM. This will ensure you can go back to those clean states after you have completed an analysis.

Sharing Files Between Host and Remnux VM

Sometimes we wish to move files that are safe from our Remnux VM to our host machine. To do this, we can use the file system pass-through in KVM. Please note, it is not recommended to have your host and guest tied together at all times, to reduce your risk only mount this when needed and unmount when done.

  • Memory
    • Enable Shared Memory (checkmark)
  • Add Hardware
  • Filesytem hostfs
    • Driver -> virtiofs
    • Source path -> Browse Local -> Select Source Folder to Share
    • Target path -> hostfs
    • XML Tab -> under the filesystem tag put accessmode=passthrough Example XML:
1
2
3
4
5
6
7
8
<filesystem type="mount" accessmode="passthrough">
  <driver type="virtiofs"/>
  <binary path="/usr/lib/qemu/virtiofsd"/>
  <source dir="/home/<username>/analysis"/>
  <target dir="hostfs"/>
  <alias name="fs0"/>
  <address type="pci" domain="0x0000" bus="0x08" slot="0x00" function="0x0"/>
</filesystem>
  • Boot Remnux VM
  • Mount the folder
1
2
3
4
5
cd ~/
mkdir hostfs
sudo mount -t virtiofs hostfs hostfs/
# do things here
sudo umount hostfs/

Forwarding Ports

Using virt-manager you can edit XML by enabling Edit->Preferences->General->Enable XML editing.

Using this, ensure the <domain> XML is <domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>.

Host to Guest

To forward ports from your host machine to your guest machine, you can use QEMU command-line with -netdev and -device.

The id and netdev options must be the same unique string.

The guestfwd option by default uses the net option of 10.0.2.0/24 for the subnet.

To change this we set our own net option to 10.0.3.0/24, using the IP address 10.0.3.1.

We are forwarding, in this case, 11434 from the host machine, to 10.0.3.1:11434 on a guest interface.

The XML for this is provided below.

1
2
3
4
5
6
<qemu:commandline>
    <qemu:arg value='-netdev'/>
    <qemu:arg value='user,id=hosttoguest,net=10.0.3.0/24,guestfwd=tcp:10.0.3.1:11434-tcp:127.0.0.1:11434'/>
    <qemu:arg value='-device'/>
    <qemu:arg value='rtl8139,netdev=hosttoguest'/>
</qemu:commandline>

This example, uses the ollama port for working with LLMs, now we can access the port by doing curl http://10.0.3.1:11434.

This usecase is for those who may want to use LLMs for static reversing but do not have two available graphics cards for PCI passthrough.

NOTE: It is important to know that forwarding ports to your host machine can pose additional risks

Guest to Host

Similar to forwarding ports from the host machine to the guest machine, we use the netdev option.

However, this time we are forwarding port 2222 on the host to 22 on the guest.

If SSH is enabled on the guest machine, from your host machine you can do ssh -p 2222 username@127.0.0.1 to get a shell.

1
2
3
4
5
6
<qemu:commandline>
	<qemu:arg value='-netdev'/>
	<qemu:arg value='user,id=guesttohost,net=10.0.3.0/24,hostfwd=tcp::2222-:22'/>
	<qemu:arg value='-device'/>
	<qemu:arg value='rtl8139,netdev=guesttohost'/>
</qemu:commandline>

NOTE: It is important to note that accessing your guest machines directly using additional applications on your host can pose additional risks.

Workflow

When working with malware it is important to establish a general workflow, please refer to my guide here.

Conclusion

Once you have the PFSense and Remnux VMs setup, you can create additional VMs on your Analysis LAN to suit your needs.

Creating a malware lab using KVM can be a daunting task for beginners compared to using VMWare Workstation or VirtualBox. However, it can benefit your lab in the following ways.

  • Access to source code you can edit to make your VMs super stealthy
  • CPU Emulated VMs (MIPS, ARM, etc.) for IoT malware
  • PCI pass through of hardware

Again I cannot recommend KVM enough, it is great for malware analysis!