Last active
February 5, 2020 19:59
-
-
Save mgeeky/80b1f7addb792796d8bfb67188d72f4a to your computer and use it in GitHub Desktop.
Specified VirtualBox's VM bash management functions and aliases. Used for instance to work with Kali vm: startkali, sshkali, iskali, getkali, stopkali.
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 | |
# | |
# Simple vm-specific management bash functions and aliases. | |
# Coming with basic functionality of starting, stopping and status checking | |
# routines. Easy to change to manage other type of VMs. | |
# | |
# Providing commands for: | |
# - starting/stopping selected VM | |
# - checking whether selected VM is running | |
# - easily ssh'ing to the selected VM | |
# - scanning for other VMs | |
# - setting selected VM's IP address within /etc/hosts (and alike) file | |
# | |
# Mariusz B. / mgeeky, '16-'19 | |
# v0.7 | |
# | |
# VM_NAME as defined in VirtualBox. Name must not contain any special characters, not | |
# even space. | |
VM_NAME= | |
# User's name to be used during ssh. | |
VM_USER=root | |
# Host-only's interface network address and interface | |
HOST_ONLY_NET=192.168.56.1 | |
HOST_ONLY_IFACE=vboxnet0 | |
# Hosts file where to put the VM's host IP address | |
HOSTS_FILE=/etc/hosts | |
# Command to be run to detect proper VM and pattern to be matched then. | |
VM_DETECT_COMMAND="uname -a" | |
VM_DETECT_PATTERN="Linux kmwr" | |
# Initial commands one would like to get executed upon VM start. | |
VM_INIT_COMMANDS="dhclient -r eth1 ; dhclient -v eth1" | |
# | |
# Will set the following aliases: | |
# - ssh<vm> alias for quick ssh-connection | |
# - get<vm> alias for quick vm's ip resolution | |
# - start<vm> alias for starting up particular vm | |
# - stop<vm> alias for stopping particular vm | |
# - is<vm> alias for checking whether the vm is running. | |
# | |
# For instance, when VM_NAME=Kali - the following aliases will be defined: | |
# sshkali, getkali, and so on | |
# | |
function setup_aliases() { | |
name=$VM_NAME | |
if [ -z $name ]; then | |
echo "[!] You must set the VM_NAME variable within that script first!" | |
exit 1 | |
fi | |
alias ssh$name="ssh -o StrictHostKeyChecking=no -Y $VM_USER@$name" | |
alias get$name="cat $HOSTS_FILE | grep -i $name | cut -d' ' -f1" | |
alias start$name="startvm" | |
alias stop$name="stopvm" | |
alias is$name="VBoxManage list runningvms | grep -qi $name && echo '[+] Running' || echo '[-] Not running';" | |
} | |
# | |
# Function for starting particular VM and then detecting it within | |
# user-specified host-only network, in order to setup correct entry in hosts file. | |
# Afterwards some additional actions like sshfs mounting could be deployed. | |
# | |
function startvm() { | |
if [ -n "$1" ] && [[ "$1" == "-h" ]]; then | |
echo "[?] Usage: startvm [mode] - where [mode] is: headless (default) or gui" | |
return | |
fi | |
name=$VM_NAME | |
#hostname=${name,,} | |
hostname=$name | |
mode=$1 | |
if [[ "$mode" == "" ]]; then | |
mode='headless' | |
elif [[ "$mode" == "gui" ]]; then | |
mode='gui' | |
else | |
echo "[?] Usage: startvm [mode] - where [mode] is: headless (default) or gui" | |
return | |
fi | |
echo "[>] Launching $name in $mode" | |
if [[ $(VBoxManage list runningvms | grep -i $name) ]]; then | |
echo "[+] Already running..." | |
else | |
echo "[>] Awaiting for machine to get up..." | |
VBoxManage startvm $name --type $mode | |
if [ $? -ne 0 ]; then | |
echo "[!] Could not get $name started. Bailing out." | |
exit 1 | |
fi | |
found=0 | |
sleep 16 | |
for i in `seq 1 25`; | |
do | |
if [ $found -ne 0 ]; then | |
break | |
fi | |
echo -e "\t$i. Attempting to connect with $name..." | |
sleep 3 | |
if scan_for_vm; then | |
found=1 | |
break | |
fi | |
done | |
if [ $found -ne 1 ]; then | |
echo "[!] Critical - could not locate $name VM machine on network." | |
echo -e "\tYou can always try 'scan_for_vm' command to do a sweep again and retry process." | |
return | |
fi | |
echo "[+] Succeeded. $name found in network." | |
fi | |
} | |
# | |
# Function for stopping particular VM. | |
# | |
function stopvm() { | |
name=$VM_NAME | |
hostname=$name | |
if VBoxManage list runningvms | grep -qi $name | |
then | |
sleep 2 | |
sudo sed -i "/$hostname/d" $HOSTS_FILE | |
echo "[+] Stopping $VM_NAME..." | |
VBoxManage controlvm $name savestate | |
else | |
echo "[-] Not running." | |
return | |
fi | |
sleep 3 | |
if VBoxManage list runningvms | grep -qi $name | |
then | |
echo "[?] Seems that $name do not want to be pasued..." | |
sleep 2 | |
VBoxManage controlvm $name acpipowerbutton | |
if VBoxManage list runningvms | grep -qi $name | |
then | |
echo "[-] Could not pause $name politely. Cut his head!" | |
sleep 3 | |
VBoxManage controlvm $name poweroff | |
else | |
echo "[+] Ok, it had shut itself down." | |
fi | |
fi | |
} | |
# | |
# One can use that very function to enumerate available machines | |
# visible from VMs network interface (under ARP scanning). | |
# | |
function find_vms_netdiscover { | |
sudo netdiscover -i $HOST_ONLY_IFACE -r $HOST_ONLY_NET/24 -N -P | grep ${HOST_ONLY_NET:0:5} | cut -d' ' -f2 | tail -n +2 | |
} | |
function find_vms_nmap { | |
nmap -sn $HOST_ONLY_NET/24 -oG - | grep Up | awk '{print $2}' | |
} | |
function find_vms { | |
sudo ifconfig $HOST_ONLY_IFACE up | |
out="" | |
if [ -x "$(command -v nmap)" ]; then | |
out=$(find_vms_nmap) | |
if test "$out" != ""; then | |
echo "$out" | |
return | |
fi | |
fi | |
if [ -x "$(command -v netdiscover)" ]; then | |
out=$(find_vms_netdiscover) | |
if test "$out" != ""; then | |
echo "$out" | |
return | |
fi | |
fi | |
echo "" | |
} | |
function detect_vm { | |
out=$(timeout 30s ssh -o BatchMode=yes -o StrictHostKeyChecking=no -o ConnectTimeout=5 $VM_USER@$1 "$VM_DETECT_COMMAND" 2>/dev/null ) | |
if [ $? -eq 124 ] || [ $? -eq 255 ]; then | |
echo "[!] Machine $1 timed out while trying to detect it by ssh probing." | |
return 1 | |
fi | |
if echo "$out" | grep -qi "$VM_DETECT_PATTERN" ; then | |
return 0 | |
else | |
return 1 | |
fi | |
} | |
# | |
# If for some reason `start` command didn't manage to find the VM | |
# that was starting at that moment, one can repeat the scan & set process | |
# manually using the below command. | |
# | |
function scan_for_vm { | |
# Scanning hosts in host-only network made by VirtualBox and then every | |
# found host will be ssh'd to get it's uname and determine whether it is our vm. | |
# Thanks to this loop we will not be failing to connect to our VM in case it's | |
# IP would get assigned differently from VBox dhcp. | |
hosts=$(find_vms) | |
declare -a hostsarray | |
while read -r host | |
do | |
hostsarray+=($host) | |
done <<< "$hosts" | |
sorted_hostsarray=($(echo "${hostsarray[@]}" | tr ' ' '\n' | sort -u)) | |
for host in $sorted_hostsarray[@]; do | |
echo "[.] Testing: $host" | |
detect_vm $host | |
if [ $? -eq 0 ] | |
then | |
# VM found by match in uname's output. | |
echo "[+] Found VM by ssh probing: $host" | |
if [ -n "$VM_INIT_COMMANDS" ]; then | |
echo "[+] Running VM init commands..." | |
timeout 1m ssh -o BatchMode=yes -o StrictHostKeyChecking=no -o ConnectTimeout=5 $VM_USER@$host "$VM_INIT_COMMANDS" 2>/dev/null | |
if [ $? -eq 124 ]; then | |
echo "[?] Timed out while trying to run VM_INIT_COMMANDS." | |
#return 1 | |
echo "Continuing anyway..." | |
fi | |
detect_vm $host | |
if [ $? -ne 0 ]; then | |
if [ $# -eq 1 ] && [ "$1" == "again" ] ; then | |
echo "[!] After initial commands the connection with VM is lost. Repeat the 'scan_for_vm' process" | |
return 1 | |
else | |
scan_for_vm "again" | |
fi | |
fi | |
fi | |
# Since the shell does output redirection not sudo, we have to write | |
# to the hosts file like so: | |
# | |
cat $HOSTS_FILE | grep -qi $VM_NAME | |
if [ $? -eq 0 ] && [ "$1" != "again" ]; then | |
sudo sed -i -E "s/^[0-9]{1,3}.[0-9]{1,3}+.[0-9]{1,3}+.[0-9]{1,3}+\s+$VM_NAME/$host $VM_NAME/" $HOSTS_FILE | |
echo "[+] Updated /etc/hosts file with '$host $VM_NAME' entry." | |
else | |
echo "$host $hostname" | sudo tee --append $HOSTS_FILE > /dev/null | |
fi | |
return 0 | |
else | |
#echo "[.] Not our target VM: '$host'" | |
continue | |
fi | |
done | |
echo "[!] Could not locate $VM_NAME machine within the network." | |
return 1 | |
} | |
setup_aliases |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment