Last active
December 9, 2025 23:02
-
-
Save LM-CT/0ea72757766d2b6693d2c9f30956d178 to your computer and use it in GitHub Desktop.
Minor improvements in Cuckoo3's "quickstart" installation script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| ##################### | |
| ##### Variables ##### | |
| ##################### | |
| LATEST_SUPPORTED_PYTHON_VERSION=python3.10 | |
| CURRENT_PYTHON_MINOR_VERSION=$(python3 --version | awk '{print $2}' | awk -F '.' '{print $2}') | |
| DEFAULT_ROOT=/opt/cuckoo3/static | |
| RED='\e[31m' | |
| ORANGE='\e[33m' | |
| GREEN='\e[32m' | |
| NC='\e[0m' | |
| ######################### | |
| ##### Flight checks ##### | |
| ######################### | |
| # Ensure Ubuntu version is supported | |
| if [[ ! $(lsb_release -r | awk '{print $2}') == 22.04 ]]; then | |
| echo -e "\n#################\n### ${RED}Attention${NC} ###\n#################" | |
| echo -e "Your current Ubuntu release is $(lsb_release -r | awk '{print $2}')" | |
| echo "Cuckoo supported Ubuntu release is 22.04. Please run Cuckoo3 on supported Ubuntu release." | |
| echo "Exiting script" | |
| exit 1 | |
| fi | |
| # Ensure the script is run as root for system-related tasks | |
| if [[ $(id -u) -ne 0 ]]; then | |
| echo -e "\n#################\n### ${RED}Attention${NC} ###\n#################" | |
| echo "This script must be run with sudo privileges to manage system-related tasks." | |
| echo "Please enter your password to run as sudo: " | |
| exec sudo bash "$0" "$@" | |
| if [[ $? -ne 0 ]]; then | |
| echo "Failed to obtain sudo privileges. Exiting" | |
| exit 1 | |
| fi | |
| fi | |
| ##################### | |
| ##### Templates ##### | |
| ##################### | |
| ### Install VMCloak ### | |
| install_vmcloak_with() { | |
| local python_version="$1" | |
| cat << EOF | |
| if [[ ! -d vmcloak ]]; then | |
| git clone https://github.com/cert-ee/vmcloak.git | |
| fi | |
| cd vmcloak | |
| git fetch --all | |
| git switch bugfix/write_input_format && git pull | |
| if [[ ! -d venv ]]; then | |
| echo -e "\n### Initiating new virtualenv ###" | |
| $python_version -m venv venv | |
| echo -e "\n### Activating new virtualenv ###" | |
| source venv/bin/activate | |
| echo -e "\n### Installing VMCloak packages ###" | |
| $python_version -m pip install . | |
| fi | |
| EOF | |
| } | |
| ### Install Cuckoo ### | |
| install_cuckoo_with() { | |
| local python_version="$1" | |
| cat << EOF | |
| if [[ ! -d cuckoo3 ]]; then | |
| git clone https://github.com/cert-ee/cuckoo3.git | |
| fi | |
| cd cuckoo3 | |
| git switch main && git pull | |
| if [[ ! -d venv ]]; then | |
| echo -e "\n### Initiating new virtualenv ###" | |
| $python_version -m venv venv | |
| echo -e "\n### Activating virtualenv ###" | |
| source venv/bin/activate | |
| echo -e "\n### Installing wheel and requests ###" | |
| $python_version -m pip install -U wheel requests | |
| echo -e "\n### Installing dependencies ###" | |
| for repo in peepdf sflock roach httpreplay; do | |
| $python_version -m pip install -U git+https://github.com/cert-ee/\$repo | |
| done | |
| $python_version -m pip install daphne | |
| declare -a pkglist=("./common" "./processing" "./machineries" "./web" "./node" "./core") | |
| echo -e "\n### Installing Cuckoo packages ###" | |
| for pkg in \${pkglist[@]}; do | |
| if [[ ! -d "\$pkg" ]]; then | |
| echo "Missing package: \$pkg" | |
| exit 1 | |
| fi | |
| $python_version -m pip install -e "\$pkg" | |
| if [[ \$? -ne 0 ]]; then | |
| echo "Install of \$pkg failed" | |
| exit 1 | |
| fi | |
| done | |
| fi | |
| # Create Cuckoo3 cwd folder | |
| if [[ ! -d ~/.cuckoocwd ]]; then | |
| echo -e "\n### Creating Cuckoo3 cwd folder ###" | |
| cuckoo createcwd | |
| fi | |
| EOF | |
| } | |
| ### Configure Cuckoo ### | |
| configure_cuckoo_for() { | |
| local username="$1" | |
| cat << EOF | |
| cd ~/cuckoo3 | |
| source venv/bin/activate | |
| # Import monitor binaries and extract signatures | |
| echo -e "\n### Importing monitor binaries ###" | |
| cuckoo getmonitor monitor.zip &>/dev/null | |
| echo -e "\n### Extracting signatures ###" | |
| unzip -o -d ~/.cuckoocwd/signatures/cuckoo signatures.zip &>/dev/null | |
| echo -e "\n### Building documentation ###" | |
| cd docs | |
| pip install -r requirements.txt | |
| mkdocs build | |
| cp -R site ../web/cuckoo/web/static/docs | |
| cuckoo web djangocommand collectstatic --noinput | |
| echo -e "\n### Generating Nginx configuration ###" | |
| cuckoo web generateconfig --nginx > /home/$username/cuckoo3/cuckoo-web.conf | |
| echo -e "\n### Migrating databases ###" | |
| cuckoomigrate database all | |
| EOF | |
| } | |
| ### Download images ### | |
| download_images_for() { | |
| local username="$1" | |
| cat << EOF | |
| echo -e "\n### Downloading images ###" | |
| cd /home/$username/vmcloak | |
| source venv/bin/activate | |
| vmcloak isodownload --win10x64 --download-to /home/$username/win10x64.iso | |
| EOF | |
| } | |
| ### Create VMs ### | |
| create_vms_for() { | |
| local username="$1" | |
| cat << EOF | |
| echo -e "\n### Activating Python venv for VMCloak ###" | |
| cd /home/$username/vmcloak | |
| source venv/bin/activate | |
| echo -e "\n### Creating qcow2 image ###" | |
| vmcloak --debug init --win10x64 --hddsize 128 --cpus 2 --ramsize 4096 --network 192.168.30.0/24 --vm qemu --vrde --vrde-port 1 --ip 192.168.30.2 --iso-mount /mnt/win10x64 win10base br0 | |
| echo -e "\n### Installing software on VM ###" | |
| vmcloak --debug install win10base --recommended | |
| echo -e "\n### Generating snapshots ###" | |
| vmcloak --debug snapshot --count 3 win10base win10_ 192.168.30.10 | |
| EOF | |
| } | |
| ### Configure VMs for Cuckoo ### | |
| configure_vms_for() { | |
| local username="$1" | |
| cat << EOF | |
| echo -e "\n### Importing VMs to Cuckoo ###" | |
| cd ~/cuckoo3 | |
| source venv/bin/activate | |
| cuckoo machine import qemu /home/$username/.vmcloak/vms/qemu | |
| echo -e "\n### Deleting example configurations ###" | |
| cuckoo machine delete qemu example1 | |
| EOF | |
| } | |
| ### Run as Cuckoo user ### | |
| run_cuckoo_for() { | |
| cat << EOF | |
| cd /home/$username/cuckoo3 | |
| source venv/bin/activate | |
| cuckoo | |
| EOF | |
| } | |
| ############################ | |
| ##### Helper functions ##### | |
| ############################ | |
| generate_section_header() { | |
| local name="$1" | |
| local header="### $name ###" | |
| local top_bottom=$(printf '%*s' "${#header}" '' | tr ' ' '#') | |
| echo -e "\n$top_bottom\n$header\n$top_bottom\n" | |
| } | |
| generate_warning() { | |
| local name="$1" | |
| local header="### ${RED}$name${NC} ###" | |
| local adjusted_length=$((${#header} - 11)) | |
| local top_bottom=$(printf '%*s' "${adjusted_length}" '' | tr ' ' '#') | |
| echo -e "\n$top_bottom\n$header\n$top_bottom\n" | |
| } | |
| create_user() { | |
| local username="$1" | |
| local password="$2" | |
| if id "$username" &>/dev/null; then | |
| echo "User $username already exists." | |
| else | |
| sudo useradd -m -s /bin/bash "$username" | |
| if [[ $? -ne 0 ]]; then | |
| echo "Error creating user." | |
| exit 1 | |
| fi | |
| echo "$username:$password" | chpasswd | |
| if [[ $? -ne 0 ]]; then | |
| echo "Error setting user password" | |
| exit 1 | |
| fi | |
| echo "User $username has been created with the specified password." | |
| fi | |
| } | |
| run_as_cuckoo() { | |
| local username="$1" | |
| local commands="$2" | |
| su - "$username" -c "$commands" | |
| } | |
| ######################################## | |
| ##### Confirmations and user setup ##### | |
| ######################################## | |
| generate_section_header "User options" | |
| echo -e "${RED}NOTE!${NC} To safely run Cuckoo3 sandboxes, it is recommended to create a separate user without sudo privileges." | |
| read < /dev/tty -p "Would you like to create a new Cuckoo3 user? [y/n]: " create_cuckoo_user | |
| while [[ ! "$create_cuckoo_user" =~ ^[yn]$ ]]; do | |
| echo "Invalid option, please type y or n." | |
| read < /dev/tty -p "[y/n]: " create_cuckoo_user | |
| done | |
| if [[ $create_cuckoo_user == "n" ]]; then | |
| generate_section_header "Setting Cuckoo3 user" | |
| read < /dev/tty -p "Please enter the name of the existing user you would like to use for Cuckoo: " username | |
| while [[ ! $(id -u $username) ]]; do | |
| echo -e "### ${RED}Attention!${NC} Provided user '$username' does not exist ###" | |
| echo "If you want to start over and create a new user press Ctrl+C and run the command again." | |
| read < /dev/tty -p "Please enter the name of the existing user you would like to use for Cuckoo: " username | |
| done | |
| read < /dev/tty -s -p "Please enter the password for '$username': " password | |
| echo | |
| elif [[ $create_cuckoo_user == "y" ]]; then | |
| generate_section_header "Creating Cuckoo3 user" | |
| read < /dev/tty -p "Please enter a username for Cuckoo user: " username | |
| while [[ $(id -u $username &>/dev/null) ]];do | |
| echo "### User exists ###" | |
| read < /dev/tty -p "Please enter another username for Cuckoo user: " username | |
| done | |
| read < /dev/tty -s -p "Please enter a password for '$username': " password | |
| echo | |
| create_user "$username" "$password" | |
| fi | |
| generate_section_header "VM options" | |
| read < /dev/tty -p "Would you like VMCloak to create default VMs? (y/n): " create_cuckoo_vms | |
| while [[ ! "$create_cuckoo_vms" =~ ^[yn]$ ]]; do | |
| echo "Invalid option, please type y or n." | |
| read < /dev/tty -p "[y/n]: " create_cuckoo_vms | |
| done | |
| generate_section_header "Web options" | |
| echo "Cuckoo uses Django to serve the web. It requires a location to store all static assets (default - /opt/cuckoo3/static)" | |
| read < /dev/tty -p "Please enter the full path of Cuckoo static root (press enter to use default): " cuckoo_web_static_root | |
| if [[ $cuckoo_web_static_root == "" ]]; then | |
| cuckoo_web_static_root=$DEFAULT_ROOT | |
| fi | |
| echo "Cuckoo static root is set to: $cuckoo_web_static_root" | |
| ####################################### | |
| ##### Install system dependencies ##### | |
| ####################################### | |
| generate_section_header "Installing system dependencies" | |
| apt-get update | |
| apt-get install -yq build-essential \ | |
| software-properties-common \ | |
| git \ | |
| unzip \ | |
| libhyperscan5 libhyperscan-dev \ | |
| libjpeg8-dev zlib1g-dev p7zip-full rar unace-nonfree cabextract \ | |
| yara \ | |
| tcpdump \ | |
| libssl-dev libcapstone-dev \ | |
| genisoimage qemu-system-common qemu-utils qemu-system-x86 \ | |
| uwsgi uwsgi-plugin-python3 \ | |
| nginx | |
| ########################################### | |
| ##### Install latest supported Python ##### | |
| ########################################### | |
| generate_section_header "Installing latest supported Python version" | |
| add-apt-repository -y ppa:deadsnakes/ppa | |
| apt-get update | |
| apt-get install -y $LATEST_SUPPORTED_PYTHON_VERSION \ | |
| $LATEST_SUPPORTED_PYTHON_VERSION-dev \ | |
| $LATEST_SUPPORTED_PYTHON_VERSION-venv | |
| ############################## | |
| ##### Installing VMCloak ##### | |
| ############################## | |
| generate_section_header "Installing VMCloak" | |
| run_as_cuckoo "$username" "$(install_vmcloak_with "$LATEST_SUPPORTED_PYTHON_VERSION")" | |
| ############################## | |
| ##### Installing Cuckoo3 ##### | |
| ############################## | |
| generate_section_header "Installing Cuckoo3" | |
| run_as_cuckoo "$username" "$(install_cuckoo_with "$LATEST_SUPPORTED_PYTHON_VERSION")" | |
| ##################################### | |
| ##### Cuckoo user configuration ##### | |
| ##################################### | |
| generate_section_header "Configuring user $username" | |
| echo -e "\n### Adding cuckoo user to kvm group ###" | |
| sudo adduser $username kvm && sudo chmod 666 /dev/kvm | |
| echo -e "\n### Configuring tcpdump for $username ###" | |
| sudo groupadd pcap | |
| sudo adduser $username pcap | |
| sudo chgrp pcap /usr/bin/tcpdump | |
| sudo setcap cap_net_raw,cap_net_admin=eip /usr/bin/tcpdump | |
| echo -e "\n### Adding Cuckoo permission to tcpdump profile in apparmor ###" | |
| sudo sed -i 's|audit deny @{HOME}/.\*/\*\* mrwkl,|audit deny @{HOME}/.[^c]\*/\*\* mrwkl,\n audit deny @{HOME}/.c[^u]\*/\*\* mrwkl,\n audit deny @{HOME}/.cu[^c]\*/\*\* mrwkl,\n audit deny @{HOME}/.cuc[^k]\*/\*\* mrwkl,\n audit deny @{HOME}/.cuck[^o]\*/\*\* mrwkl,\n audit deny @{HOME}/.cucko[^o]\*/\*\* mrwkl,\n audit deny @{HOME}/.cuckoo[^c]\*/\*\* mrwkl,\n audit deny @{HOME}/.cuckooc[^w]\*/\*\* mrwkl,\n audit deny @{HOME}/.cuckoocw[^d]\*/\*\* mrwkl,\n audit deny @{HOME}/.cuckoocwd?\*/\*\* mrwkl,|g' /etc/apparmor.d/usr.bin.tcpdump | |
| sudo apparmor_parser -r /etc/apparmor.d/usr.bin.tcpdump | |
| ###################### | |
| ##### Create VMs ##### | |
| ###################### | |
| if [[ $create_cuckoo_vms == "y" ]]; then | |
| generate_section_header "Creating VMs with VMCloak" | |
| # ------------------------------ | |
| # ----- Downloading images ----- | |
| # ------------------------------ | |
| echo -e "\n### Downloading images for VMCloak ###" | |
| run_as_cuckoo "$username" "$(download_images_for "$username")" | |
| # --------------------------------- | |
| # ----- VMCloak configuration ----- | |
| # --------------------------------- | |
| echo -e "\n### Enabling interface and mounting image ###" | |
| sudo /home/$username/vmcloak/bin/vmcloak-qemubridge br0 192.168.30.1/24 && \ | |
| sudo mkdir -p /etc/qemu/ && echo "allow br0" | sudo tee /etc/qemu/bridge.conf && \ | |
| sudo chmod u+s /usr/lib/qemu/qemu-bridge-helper && \ | |
| sudo mkdir -p /mnt/win10x64 && sudo mount -o loop,ro /home/$username/win10x64.iso /mnt/win10x64 | |
| # ------------------------ | |
| # ----- Creating VMs ----- | |
| # ------------------------ | |
| echo -e "\n### Creating VM-s and snapshots ###" | |
| run_as_cuckoo "$username" "$(create_vms_for "$username")" | |
| fi | |
| ######################### | |
| ##### Cuckoo3 setup ##### | |
| ######################### | |
| generate_section_header "Configuring Cuckoo3" | |
| run_as_cuckoo "$username" "$(configure_vms_for "$username")" | |
| ####################### | |
| ###### Cuckoo Web ##### | |
| ####################### | |
| generate_section_header "Setting up Cuckoo3 Web" | |
| echo -e "\n### Configuring Web ###" | |
| sudo sed -i 's/allowed_subnets: 127.0.0.0\/8,10.0.0.0\/8/allowed_subnets: 127.0.0.0\/8,10.0.0.0\/8,192.168.68.0\/24/g' /home/$username/.cuckoocwd/conf/web/web.yaml | |
| sudo sed -i "s|# STATIC_ROOT = \"\"|STATIC_ROOT = \"$cuckoo_web_static_root\"|g" /home/$username/.cuckoocwd/web/web_local_settings.py | |
| echo -e "\n### Creating static root ###" | |
| sudo mkdir -p $cuckoo_web_static_root | |
| sudo chown -R $username:$username $cuckoo_web_static_root | |
| sudo adduser www-data "$username" | |
| run_as_cuckoo "$username" "$(configure_cuckoo_for "$username")" | |
| sudo rm /etc/nginx/sites-enabled/cuckoo-web.conf 2&>/dev/null | |
| sudo rm /etc/nginx/sites-enabled/default 2&>/dev/null | |
| echo -e "\n### Creating ASGI service###" | |
| sudo cat <<EOF > /etc/systemd/system/cuckoo-web.service | |
| [Unit] | |
| Description=Daphne ASGI Server | |
| After=network.target | |
| [Service] | |
| User=$username | |
| Group=$username | |
| WorkingDirectory=/home/$username/cuckoo3/web/cuckoo/web | |
| ExecStart=/home/$username/cuckoo3/venv/bin/daphne -p 9090 cuckoo.web.web.asgi:application | |
| Environment=CUCKOO_APP=web | |
| Environment=CUCKOO_CWD=/home/$username/.cuckoocwd | |
| Environment=CUCKOO_LOGLEVEL=DEBUG | |
| Restart=always | |
| [Install] | |
| WantedBy=multi-user.target | |
| EOF | |
| echo -e "\n### Enabling and starting ASGI service ###" | |
| sudo systemctl enable cuckoo-web.service && \ | |
| sudo systemctl start cuckoo-web.service | |
| echo -e "\n### Creating Nginx configuration ###" | |
| sudo cat <<EOF > /etc/nginx/sites-available/cuckoo-web.conf | |
| # This is a basic NGINX configuration generated by Cuckoo. It is | |
| # recommended to review it and change it where needed. This configuration | |
| # is meant to be used together with the generated uWSGI configuration. | |
| upstream cuckoo_web { | |
| server 127.0.0.1:9090; | |
| } | |
| server { | |
| listen 80; | |
| # Directly serve the static files for Cuckoo web. Copy | |
| # (and update these after Cuckoo updates) these by running: | |
| # 'cuckoo web djangocommand collectstatic'. The path after alias should | |
| # be the same path as STATIC_ROOT. These files can be cached. Be sure | |
| # to clear the cache after any updates. | |
| location /static { | |
| alias /opt/cuckoo3/static; | |
| } | |
| # Pass any non-static requests to the Cuckoo web wsgi application run | |
| # by uwsgi. It is not recommended to cache paths here, this can cause | |
| # the UI to no longer reflect the correct state of analyses and tasks. | |
| location / { | |
| client_max_body_size 1G; | |
| proxy_http_version 1.1; | |
| proxy_set_header Host \$host; | |
| proxy_set_header X-Forwarded-Proto \$scheme; | |
| proxy_set_header X-Real-IP \$remote_addr; | |
| proxy_pass http://cuckoo_web; | |
| } | |
| } | |
| EOF | |
| sudo ln -s /etc/nginx/sites-available/cuckoo-web.conf /etc/nginx/sites-enabled/cuckoo-web.conf | |
| echo -e "\n### Restarting Nginx ###" | |
| sudo systemctl restart nginx cuckoo-web.service | |
| ################################# | |
| ##### Create helper scripts ##### | |
| ################################# | |
| generate_section_header "Creating helper scripts under $(pwd)" | |
| touch ~/helper_script.sh && chmod u+x ~/helper_script.sh | |
| cat <<EOT > helper_script.sh | |
| echo -e "\n### Bringing up network bridge ###" | |
| sudo /home/$username/vmcloak/bin/vmcloak-qemubridge br0 192.168.30.1/24 | |
| echo -e "\n### Mounting ISO ###" | |
| sudo mount -o loop,ro /home/$username/win10x64.iso /mnt/win10x64 | |
| EOT | |
| ###################### | |
| ##### Run Cuckoo ##### | |
| ###################### | |
| generate_section_header "Running cuckoo in debug mode" | |
| run_as_cuckoo "$username" "$(run_cuckoo_for "$username")" | |
| # End of script |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment