In this blogpost, I’ll share my notes on the installation of the Cuckoo 3 Sandbox. Cuckoo is the leading open source automated malware analysis system. It is used to launch malware in a secure and isolated environment.
Thanks to folks at Hatching and CERT-EE, we now have a full rewrite of Cuckoo in Python 3! You can find their original setup instructions on the official Estonian CERT repo here .
Note, this guide is intended to be read more like a cookbook than a standalone tutorial and should be fully reproducible (at the time of writing this article). Also, I’ve used vSphere as my main virtualization platform, but it should in theory apply to any other platform as well.
Installation π
Download Ubuntu Server 20.04
Import the Ubuntu image into vSphere with the following specs (yours may change)
- 16 CPUs
- 64 GB Memory
- 120 GB storage (Thin Provision)
Since we are going to be running a VM inside VM, we have to enable the nested virtualization. Go to CPU
section and tick the box Expose hardware assisted virtualization to the guest OS
During the installation:
- Set the hostname to
cuckoo-sandbox
(optionally) - Create non-root user
cuckoo
- Enable
Open-SSH server
for remote access
Network setup π
Setup the system with your network configuration, and ensure it has internet access.
Edit file /etc/netplan/00-installer-config.yaml
accordingly.
network:
version: 2
ethernets:
ens160:
dhcp4: no
addresses:
- 10.7.42.100/24
gateway4: 10.7.42.1
nameservers:
addresses: [8.8.8.8, 1.1.1.1]
Apply changes
sudo netplan apply
Dependency installation π
First, let’s update the system
sudo apt update && sudo apt upgrade -y
The following dependencies are required for successful installation
sudo apt install git build-essential python3-dev python3.8-venv libhyperscan5 libhyperscan-dev libjpeg8-dev zlib1g-dev unzip p7zip-full rar unace-nonfree cabextract yara tcpdump genisoimage qemu-system-x86 qemu-utils qemu-system-common -y
Fix the permissions for KVM access
sudo adduser cuckoo kvm
sudo chmod 666 /dev/kvm
Configuring tcpdump
π
Add existing user cuckoo
to pcap group
sudo groupadd pcap
sudo adduser cuckoo pcap
sudo chgrp pcap /usr/sbin/tcpdump
Allow creation of pcaps for non-root users
sudo setcap cap_net_raw,cap_net_admin=eip /usr/sbin/tcpdump
Ubuntu uses Apparmor, so we need to disable the profile for tcpdump (Alternatively, adding an exception would also do)
sudo ln -s /etc/apparmor.d/usr.sbin.tcpdump /etc/apparmor.d/disable/
sudo apparmor_parser -R /etc/apparmor.d/disable/usr.sbin.tcpdump
Reload the apparmor profile
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.tcpdump
Installing Cuckoo from source π
Fetch the source from github
sudo chown cuckoo /opt && cd /opt
git clone https://github.com/cert-ee/cuckoo3
cd cuckoo3
Create and activate new Python environment for Cuckoo. Ensure package wheel
is installed for later building.
python3 -m venv venv
source venv/bin/activate
pip install wheel
Launch main installer script
./install.sh
Create Cuckoo working directory (CWD)
cuckoo createcwd
Install the stager and monitoring binaries
cuckoo getmonitor monitor.zip
Extract cuckoo signatures to the right location
unzip signatures.zip -d ~/.cuckoocwd/signatures/cuckoo/
Installing vmcloak
π
This utility is not mandatory, however it greatly simplifies the process of VM creation and configuration. For now, let’s just install it.
git clone https://github.com/hatching/vmcloak.git && cd vmcloak
pip install . && cd ..
Configuring QEMU network interface π
Create a new brige with the name br0
and range 192.168.30.1/24
sudo /opt/cuckoo3/venv/bin/vmcloak-qemubridge br0 192.168.30.1/24
Append the line allow br0
to the file bridge.conf
sudo mkdir -p /etc/qemu
echo 'allow br0' | sudo tee /etc/qemu/bridge.conf
Change the permissions for qemu-bridge-helper
script. It needs a special SUID bit for creation of new interfaces.
sudo chmod u+s /usr/lib/qemu/qemu-bridge-helper
VM Setup π
Using vmcloak, download the Windows 10 ISO (build 1703).
vmcloak isodownload --win10x64 --download-to ~/win10x64.iso
Mount the image as read only
sudo mkdir /mnt/win10x64
sudo mount -o loop,ro /home/cuckoo/win10x64.iso /mnt/win10x64
Install Windows as a new base image win10base
with all the specs configured. This base image is going to be used later on to spin up live VMs.
vmcloak --debug init --win10x64 --hddsize 128 --cpus 2 --ramsize 4096 --network 192.168.30.0/24 --vm qemu --ip 192.168.30.2 --iso-mount /mnt/win10x64 win10base br0
Optionally install some basic utilities for better simulation of the real system.
vmcloak --debug install win10base dotnet:4.7.2 java:7u80 vcredist:2013 vcredist:2019 edge carootcert wallpaper disableservices
At this moment, our base image is ready. In the next step, we have to spin up runnable instances from this image. I opted for 5 instances/snapshots, but you can change it to any number. Each VM will have its own IP starting from 192.168.30.20
vmcloak --debug snapshot --count 5 win10base win10vm_ 192.168.30.20
The setup for Window 10 is finished. Similar steps can be applied for Win7 installation.
vmcloak isodownload --win7x64 --download-to ~/win7x64.iso
sudo mkdir /mnt/win7x64
sudo mount -o loop,ro /home/cuckoo/win7x64.iso /mnt/win7x64
vmcloak --debug init --win7x64 --hddsize 128 --cpus 2 --ramsize 4096 --network 192.168.30.0/24 --vm qemu --ip 192.168.30.3 --iso-mount /mnt/win7x64 win7base br0
vmcloak --debug install win7base dotnet:4.7.2 java:7u80 vcredist:2013 vcredist:2019 edge carootcert wallpaper disableservices
vmcloak --debug snapshot --count 5 win7base win7vm_ 192.168.30.30
Now that we have created our VMs, let’s import it in Cuckoo
cuckoo machine import qemu ~/.vmcloak/vms/qemu
Delete default exemplary template
cuckoo machine delete qemu example1
Init cuckoo DB. (At the time of writing this article, this command results in some errors. Just ignore them for now)
cuckoomigrate database all
Configure the correct IP of the result server in the file ~/.cuckoocwd/conf/cuckoo.yaml
# listen IP and port. Make sure the IP is off a network interface that is part of the analysis machine network or
# route/forward traffic between the analysis machines and the resultserver.
resultserver:
- listen_ip: 192.168.30.101
+ listen_ip: 192.168.30.1
listen_port: 2042
MISP integration π
Optionally we can configure MISP by adding the API key and URL of the MISP instance.
The following file has to be changed ~/.cuckoocwd/conf/processing/misp.yaml
# Enable the usage of MISP queries in pre and post processing for
# the discovered IOCs.
- enabled: False
+ enabled: True
# The MISP API url. Is also used as the base URL for creating links to
# events.
- url: null
+ url: <your_misp_url>
# Verify if the configured MISP server is using a valid TLS certificate.
# Disable this your certificate is self-signed or no certificate is used.
verify_tls: True
# The API key to access the MISP api.
- key: null
+ key: <misp_api_key>
Enabling VirusTotal π
Optionally add your VT API key to file ~/.cuckoocwd/conf/processing/virustotal.yaml
# The VirusTotal API key to use. The default API key, kindly provided
# by the VirusTotal team, should enable you with a sufficient throughput
# and while being shared with all our users, it should not affect your use.
- key: a0283a2c3d55728300d064874239b5346fb991317e8449fe43c902879d758088
+ key: <vt_api_key>
Starting Cuckoo π
A quick way to start cuckoo is to launch the dev server with the --debug
option. This is not an efficient way, but will suffice for testing purposes. For a production-ready setup see the Post-installation part.
Start the cuckoo daemon
cuckoo --debug
Launch the cuckoo internal webserver
cuckoo web --host 10.7.42.100 --port 8080
Post installation π
In this part, we’ll see how to setup cuckoo for production use, create a simple launcher script and build the documentation.
Build the docs π
Switch to the folder containing docs
cd /opt/cuckoo3/docs
Install couple dependencies
pip install -r requirements.txt
Build the docs with mkdocs and copy to right destination
mkdocs build
cp -R site ../web/cuckoo/web/static/docs
Installing nginx π
Install uwsgi a nginx
pip install uwsgi
sudo apt-get install uwsgi uwsgi-plugin-python3 nginx -y
Generate the conf file for uswgi
cuckoo web generateconfig --uwsgi > cuckoo-web.ini
sudo mv cuckoo-web.ini /etc/uwsgi/apps-available/
sudo ln -s /etc/uwsgi/apps-available/cuckoo-web.ini /etc/uwsgi/apps-enabled/cuckoo-web.ini
Add the user cuckoo
to the group www-data
sudo adduser www-data cuckoo
In the file ~/.cuckoocwd/web/web_local_settings.py
change the STATIC_ROOT
so that it points to the folder with static assets
# Uncomment and set this path to a path all static files should be copied to
# when running 'cuckoo web djangocommand collectstatic'. These files should
# be served by a web server.
-#STATIC_ROOT = ""
+STATIC_ROOT = "/opt/cuckoo3/web/cuckoo/web/static"
Generate the nginx conf files
cuckoo web generateconfig --nginx > cuckoo-web.conf
Configure the server to listen on port 80
server {
- listen 127.0.0.1:8000;
+ listen 80;
Add the conf file to nginx folder and create a symbolic link
sudo mv cuckoo-web.conf /etc/nginx/sites-available/cuckoo-web.conf
sudo ln -s /etc/nginx/sites-available/cuckoo-web.conf /etc/nginx/sites-enabled/cuckoo-web.conf
Remove the default welcoming page from nginx and restart both services
sudo rm /etc/nginx/sites-enabled/default
sudo systemctl restart nginx uwsgi
Launcher script π
For the sake of convenience, I’ve put together this little script that is responsible for launching the cuckoo in quite mode using tmux. Probably a better approach would be to create a systemd service and enable it to launch on boot.
#!/bin/bash
sudo /opt/cuckoo3/venv/bin/vmcloak-qemubridge br0 192.168.30.1/24
source /opt/cuckoo3/venv/bin/activate
tmux new-session -d -s cuckoo 'cuckoo --quiet'
Cuckoo is now started in the background. Whenever you want to re-attach to the cuckoo session use tmux a