Get IP of headless Virtualbox VM

This short article will describe how you will get quickly the IP for an headless running Virtualbox VM. For demonstration purpose, I have assigned an “Bridged Interface” on NIC 1. So the IP is dynamically allocated (IP address is being assigned by DHCP).

# start VM headless (if not running)
$ VBoxManage startvm --type headless "vm name"

# check VM state (optional)
$ VBoxManage showvminfo "vm name" | grep "State"

# show IP
$ VBoxManage guestproperty get "vm name" "/VirtualBox/GuestInfo/Net/0/V4/IP"

That was super easy … now you can connect via SSH (if SSH service is running).

# start SSH connection
$ ssh -C4 remote_user@

Man in the Middle Attack (MITM)

In this tutorial you will learn how to work a man in the middle attack. For this you will create and configure a simple test environment. The test environment simulates a small home network with a NAT router, a client (victim) and another client (evil) that has already penetrated the network. For the attack itself, you will get in touch with popular mitmf framework.

Attention: The tutorial is presented just for educational purposes. If you do what you have learned outside the test environment, you may be liable to prosecution.


  • VirtualBox (5.2.18)
  • Vagrant (2.1.5)

Prepare environment

In the first step, you need to configure, setup and provision the environment. Vagrant will help you here. Via Vagrant you will create all needed virtual machines (incl. SSH keys) and install the needed packages on the evil engine. Via file machines.yml you could add Vagrant boxes for Windows, macOS as well.

# create project
$ mkdir -p ~/Projects/ExampleEnv && cd ~/Projects/ExampleEnv

# create needed files
$ touch Vagrantfile machines.yml

# edit machines.yml (copy content into file)
$ vim machines.yml

# edit Vagrantfile (copy content into file)
$ vim Vagrantfile

# run Vagrant
$ vagrant up
  - name: evil
    box: debian/stretch64
    cpus: 1
    memory: 1024
  - name: victim
    box: chad-thompson/ubuntu-trusty64-gui
    cpus: 1
    memory: 1024

Note: Please remove the spaces behind etc (in the Vagrantfile)! These are only because of the security settings of my provider.

# -*- mode: ruby -*-
# vi: set ft=ruby :

require 'yaml'
machines = YAML.load_file('machines.yml')

Vagrant.configure("2") do |config|
  machines.each do |machines|
    config.vm.define machines["name"] do |machine|

      # define vagrant box = machines["box"]
      # disbale default synced_folder
      machine.vm.synced_folder ".", "/vagrant", disabled: true
      # configure virtualbox
      machine.vm.provider :virtualbox do |vb| = machines["name"]
        vb.cpus = machines["cpus"]
        vb.memory = machines["memory"]
        vb.gui = false
      # provisioning: only evil
      if machines["name"] == 'evil'
        machine.vm.provision "shell", inline: <<-SHELL
          echo 'deb kali-rolling main non-free contrib' >> /etc /apt/sources.list
          echo 'deb-src kali-rolling main non-free contrib' >> /etc /apt/sources.list
          apt-get update
          apt-get install -y --allow-unauthenticated mitmf


Small network changes

You must now switch from typical NAT to NAT network. For that you stop (halt) all VM’s. In the next steps you will create a new NAT network and configure the VM network adapters for this network. In the end, you simulated a simple home network.

# stop all VM's
$ vagrant halt

# create new VirtualBox NAT-Network
$ VBoxManage natnetwork add --netname homenet --network "" --enable --dhcp on --ipv6 off

# list all NAT-Networks (optional)
$ VBoxManage list natnetworks

# change interfaces from NAT to NAT-Network for evil VM
$ VBoxManage modifyvm evil --nic1 natnetwork --nat-network1 homenet

# change mac address for evil VM
$ VBoxManage modifyvm evil --macaddress1 08002707B96E

# show network configuration for evil (optional)
$ VBoxManage showvminfo evil | grep "NIC"

# change interfaces from NAT to NAT-Network for victim VM
$ VBoxManage modifyvm victim --nic1 natnetwork --nat-network1 homenet

# change mac address for victim VM
$ VBoxManage modifyvm victim --macaddress1 080027C0B653

# some Ubuntu VirtualBox changes
$ VBoxManage modifyvm victim --accelerate3d on --vram 128

# show network configuration for victim (optional)
$ VBoxManage showvminfo victim | grep "NIC"

Start all VM’s again

In this step we start all VM’s but without Vagrant.

# start evil VM
$ VBoxManage startvm evil

# start victim VM
$ VBoxManage startvm victim

Now check the network interfaces for both VM’s. Please note down the IP’s, you will need them in next steps. You can login in both with credentials vagrant:vagrant.

# evil VM
$ ip -4 addr

# victim VM
$ ip -4 addr

Note: In the example the evil VM has the IP: and the victim the IP: – this could be different for you.

In order not to use the VirtualBox Terminal, create a port forward from the localhost to the evil VM.

# add port forwarding from localhost to evil VM
$ VBoxManage natnetwork modify --netname homenet --port-forward-4 "evilssh:tcp:[]:2222:[]:22"

# ssh connection to evil
$ ssh -i .vagrant/machines/evil/virtualbox/private_key -p 2222 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null vagrant@localhost

Man-in-the-middle attack

You made it, the test environment is finally ready. If you have been able to learn something new up to this point, I am glad. Now imagine the following situation. You are the victim and you surf the Internet, logging in on your popular websites. Can you imagine what can happen? In a few minutes you will see it.

Once the Ubuntu has booted, run the following command (as evil) and surf the web using the Firefox browser (as victim). If the mitmf returns an error message, repeat the command in the terminal. Be a bit patient on successful call.

# change to root
$ sudo su -

# enable ip4_forward (only this session)
$ sysctl -w net.ipv4.ip_forward=1

# check ip4_forwarding is enabled (optional)
$ sysctl net.ipv4.ip_forward

# start mitmf (incl. ARP spoofing)
$ mitmf --spoof --arp -i eth0 --gateway --target

# start mitmf (incl. ARP spoofing, enabled SSLstrip, Session kill)
$ mitmf --spoof --arp --hsts -k -i eth0 --gateway --target

Mitmf still offers a lot of plug-ins, just give it a try.

Create a simple video test environment (Part 2)

In the first part we created the video test environment and you learned how to extend it. At the end of this tutorial you will know how to embed video content in the video test environment. Therefore, a few basics are shown around ffmpeg (how to create, edit and use videos).

Record and prepare some videos

The recording should contain video and sound and should be 5 minutes long. The content of the video does not matter!

# open Quicktime Player
$ open -a "QuickTime Player"

# press Control-Command-N, start record (approximately 5 min)
# save record into project folder as (~/Projects/VideoTest/

As soon as a video is ready we have to create more.

# copy binary (optional)
$ sudo cp ~/Projects/VideoTest/ffmpeg /usr/local/bin/ffmpeg && sudo chmod a+rx /usr/local/bin/ffmpeg

# convert mov into mp4 (copy)
$ ffmpeg -i -vcodec copy -acodec copy demo.mp4

# resize mp4 to 320x240 (filter_graph)
$ ffmpeg -i demo.mp4 -vf scale=320:240 ./src/demo_scaled.mp4

# create poster from mp4 (position and frame)
$ ffmpeg -i ./src/demo_scaled.mp4 -ss 00:00:30 -vframes 1 ./src/demo_poster.png

# create m3u8/ts files from mp4 (HLS - Apple HTTP Live Stream)
$ ffmpeg -i demo.mp4 -b:v 1M -g 60 -hls_time 2 -hls_list_size 0 -hls_segment_size 500000 ./src/output.m3u8

# run specific SHELL provisioner
$ vagrant provision --provision-with video

Note: After this step you will have many video files which you will use

  • ./ (original)
  • ./demo.mp4 (converted)
  • ./src/demo_scaled.mp4 (converted and resized)
  • ./src/output.m3u8
  • ./src/\*.ts

Get in contact with ffmpeg

I assume that ffmpeg is properly installed and the test environment is running.

# create target folder
$ mkdir ~/Projects/VideoTest/test

# extract some images from video
$ ffmpeg -i -ss 00:00:30 -t 0.1 -f image2 -qscale 2 -vcodec mjpeg ./test/img-%03d.jpg

# create local m3u8/ts files from mp4
$ ffmpeg -i demo.mp4 -b:v 1M -g 60 -hls_time 2 -hls_list_size 0 -hls_segment_size 500000 ./test/output.m3u8

# extract mp4 from local m3u8/ts files
$ ffmpeg -i test/output.m3u8 -bsf:a aac_adtstoasc -vcodec copy -c copy -crf 50 ./test/output_local.mp4

# extract mp4 from url to m3u8 file (will not work with LiveStream)
$ ffmpeg -i http://localhost:8080/output.m3u8 -c copy -bsf:a aac_adtstoasc stream.mp4

Stream videos

# open browser
$ open -a Safari http://localhost:8080/livestream.html

# stream video (Real-Time Messaging Protocol)
$ ffmpeg -re -i demo.mp4 -vcodec libx264 -vprofile baseline -g 30 -acodec aac -strict -2 -f flv rtmp://localhost/show/stream

Stream from FaceTime HD Camera (macOS)

# open browser
$ open -a Safari http://localhost:8080/livestream.html

# list devices
$ ffmpeg -f avfoundation -list_devices true -i ""

# stream sound and video (Real-Time Messaging Protocol)
$ ffmpeg -f avfoundation -framerate 30 -i "0:0" -pix_fmt yuv420p -vcodec libx264 -vprofile baseline -g 30 -acodec libmp3lame -f flv rtmp://localhost/show/stream

Create a simple video test environment

In this series I would like to clarify the following questions. How can you test local videos and videos provided by a server? What tools are there? How could the test environment look like? … So these tutorials should provide an entry into the subject of video testing. In this part, we will provide the test environment.


additional Software


# create project
$ mkdir -p ~/Projects/ && cd ~/Projects/

# clone all files from repository
$ git clone

# change directory
$ cd ~/Projects/VideoTest

Project Structure

$ tree .
├── src
│   ├── directstream.html
│   ├── index.html
│   ├── livestream.html
│   ├── nginx.conf
│   └── simplevideo.html
└── Vagrantfile

Prepare and run your test environment

The test environment will created by Vagrant. The Vagrant Base box needs to be provided with Debian 9. Therefore you have now 2 options. You can use a Debian 9 Base box from Vagrant cloud or you create your own. To create your own Debian 9 Base box you can use my Packer Git repository.

Please ensure, that the  Vagrantfile is properly configured (config.vm.box_url, before start-up environment.

# modify Vagrantfile (box name)
$ vim Vagrantfile

# start new environment
$ vagrant up --provision-with install,prepare,start

# open in browser
$ open -a Safari http://localhost:8080/

After successful start you will find some informations on start page about How-to create, modify, upload and stream videos. In second tutorial we will have a detailed look on it.

StartPage Video Test Environment

To understand the background somewhat better, take a look!

# tail nginx log files (optional)
$ vagrant ssh -c 'sudo tail -f /usr/local/nginx/logs/*.log'

# show content of directory (optional)
$ vagrant ssh -c 'sudo ls -la /tmp/hls/'

Develop some more

There are even more ways to publish video files (Media Streaming Server). You can easily expand the environment. Just customize/create the configurations and files in the “src” folder as well as the Vagrantfile. For Dynamic Adaptive Streaming over HTTP (DASH) support take a look here. This link opens the commercial software solution.

Note: You simply link the IDE with the “src” folder. To change the images and videos, just run vagant provisioner.

# run specific SHELL provisioner (video)
$ vagrant provision --provision-with video

# restart after configuration
$ vagrant up --provision-with stop,prepare,start

Download and install ffmpeg binaries on macOS

Currently official ffmpeg packages are available for Windows, Linux (Debian, Ubuntu, Fedora, RedHat) and macOS. You can download latest versions here.

Here now a solution for macOS users, if you don’t like to install many additional software on your system (static FFmpeg binaries).

# download ffmpeg
$ curl -C - -k -o ~/Downloads/ffmpeg-

# install debian package
$ vagrant ssh -c 'sudo apt install -y p7zip-full'

# copy archive (into shared folder)
$ cp ~/Downloads/ffmpeg- ~/Projects/VideoTest/src/

# unzip archive
$ vagrant ssh -c '7z x /home/vagrant/src/ffmpeg-'

# mv binary into src
$ vagrant ssh -c 'mv /home/vagrant/ffmpeg /home/vagrant/src/ffmpeg'

# delete archive (on shared folder)
$ rm ~/Projects/VideoTest/src/ffmpeg-

# mv binary into project folder (from shared folder)
$ mv ~/Projects/VideoTest/src/ffmpeg ~/Projects/VideoTest/

# ensure binary is executable
$ chmod +x ffmpeg

Now some basic ffmpeg commands, which should work now. If you like,you can move the binary into directory “/usr/local/”.

# show version
$ ~/Projects/VideoTest/ffmpeg -version

# show help
$ ~/Projects/VideoTest/ffmpeg -help

# list codecs
$ ~/Projects/VideoTest/ffmpeg -codecs

# list formats
$ ~/Projects/VideoTest/ffmpeg -formats

Okay, that’s it for first tutorial.

Quick and dirty sync folders for Vagrant


In our company we have different development teams working with same Vagrant boxes. As a challenge they need different sync folder locations – even inside teams. I’m just too lazy to provide and maintain all Vagrantfile templates for their needs. So i provide a quick and dirty solution for them.


# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|

  # box name = "lupin/centos7"

  # Disable replacing insecure key
  config.ssh.insert_key = false

  # Disable default synced folder
  config.vm.synced_folder ".", "/vagrant", disabled: true

  # Synced folder(s) by argument
  if !ENV['mount'].nil?

    loop do
      puts "local folder: "
      local_dir = STDIN.gets.chomp
      puts "target folder: "
      target_dir = STDIN.gets.chomp

      if local_dir.empty? || target_dir.empty?

      config.vm.synced_folder local_dir, target_dir


 # VirtualBox specific configuration
  config.vm.provider "virtualbox" do |vb|
    vb.gui = false
    vb.memory = "1024"
    vb.cpus = 1 = "example_vm"



# simple command
$ vagrant up

# check for synced folder(s)
$ vagrant ssh -c 'ls -la /'

# destroy environment
$ vagrant halt

# run with argument (mount)
$ mount=yes vagrant up
local folder:
src_a <ENTER>
target folder:
/vagrant_a <ENTER>
local folder:
src_b <ENTER>
target folder:
/vagrant_b <ENTER>
local folder:
target folder:

# show content
$ vagrant ssh -c 'cat /vagrant_a/SomeTestFile_a && cat /vagrant_b/SomeTestFile_b'
Hello world ... a
Hello world ... b

# destroy environment
$ vagrant destroy -f


Create Alpine Linux VM with VirtualBox

Today a tutorial for creating a Alpine Linux VM with VirtualBox. The only limitation is that VirtualBox is already installed. Furthermore,  all of the steps are performed in the terminal (without VirtualBox-GUI).

Creation of VM

# change directory
$ cd VirtualBox\ VMs/

# download alpine iso
$ curl -o alpine-3.4.3-x86_64.iso

# checksum sha1 (optional)
$ openssl sha1 alpine-3.4.3-x86_64.iso

# create new directory
$ mkdir AlpineVM

# create storage medium for VM
$ VBoxManage createhd --filename ./AlpineVM/AlpineVM.vdi --size 8192

# list available OS types (just for fun and good to know)
$ VBoxManage list ostypes

# register new alpine VM
$ VBoxManage createvm --name "AlpineVM" --ostype Linux26_64 --register

# configure system settings of alpine VM
$ VBoxManage modifyvm "AlpineVM" --memory 1024 --cpus 1 --acpi on --pae off --hwvirtex on --nestedpaging on --rtcuseutc on --vram 16 --audio none --accelerate3d off --accelerate2dvideo off --usb on

# configure boot settings of VM
$ VBoxManage modifyvm "AlpineVM" --boot1 dvd --boot2 disk --boot3 none --boot4 none

# modify a storage controller (IDE)
$ VBoxManage storagectl "AlpineVM" --name "IDE" --add ide

# modify a storage controller (SATA)
$ VBoxManage storagectl "AlpineVM" --name "SATA" --add sata

# add storage medium to VM
$ VBoxManage storageattach "AlpineVM" --storagectl "SATA" --port 0 --device 0 --type hdd --medium ./AlpineVM/AlpineVM.vdi

# add alpine iso
$ VBoxManage storageattach "AlpineVM" --storagectl "IDE" --port 1 --device 0 --type dvddrive --medium alpine-3.4.3-x86_64.iso

# start alpine VM
$ VBoxManage startvm "AlpineVM"

Basic Alpine installation

# after login as user "root" (passwordless)

# run setup
$ setup-alpine

keyboard layout: "us"
keyboard variant: "us"
system hostname: "localhost"
initialise interface: "eth0, dhcp, no manual setup"
enter root password
timezone: "UTC"
HTTP/FTP proxy URL: "none"
Detect and add fastest mirror: "f"
SSH server: "openssh"
NTP client: "chrony"
install to disk: "sda"
install type: "sys"
erase & continue: "y"

# shutdown system
$ poweroff

Note: if you have an answers file you can do…

# download answers file
$ wget http://<uri>/<answers file>

# configuration via answers file
$ alpine-setup -f <path/to/answers file>

Remove medium (ISO)

# remove alpine iso
$ VBoxManage storageattach "AlpineVM" --storagectl "IDE" --port 1 --device 0 --type dvddrive --medium emptydrive

# start VM
$ VBoxManage startvm "AlpineVM"

Update Packages and install VirtualBox additions

# change directory
$ cd /etc

# enable repositories
$ vi apk/repositories


# update and upgrade system
$ apk update && apk upgrade

# install virtualbox additions
$ apk add virtualbox-guest-modules-grsec virtualbox-additions-grsec

# reboot system
$ reboot

Optional steps

# install vim
$ apk add vim

# change directory
$ cd /etc

# modify sshd (manual) 
$ vim ssh/sshd_config

# restart sshd
$ init.d/sshd restart

# modify network interfaces (manual)
$ vim network/interfaces

# restart network
$ init.d/networking restart

Create own Docker port scanner

Today’s tutorial shows how quickly and easily a Docker port scanner can be created. With the knowledge you can then create additional Docker applications.


# prepare knocker project (local)
$ mkdir ~/Projects/Knocker && cd ~/Projects/Knocker

# create Dockerfile (local)
$ vim Dockerfile

# create KnockerVM (local)
$ docker-machine create -d virtualbox KnockerVM

# pointing shell to KnockerVM (local)
$ eval $(docker-machine env KnockerVM)

# copy Dockerfile into KnockerVM (local)
$ docker-machine scp ~/Projects/Knocker/Dockerfile KnockerVM:Dockerfile

# SSH into KnockerVM (local)
$ docker-machine ssh KnockerVM


FROM alpine

# install needed packages
RUN apk --update add wget build-base gcc abuild binutils binutils-doc gcc-doc

# download and unzip
RUN wget
RUN tar -zxvf knocker-0.7.1.tar.gz && rm -f knocker-0.7.1.tar.gz

# configure, install and clean up
WORKDIR /knocker-0.7.1
RUN ./configure \
    && make install \
    && make clean

# create mountable directory
RUN mkdir /results
VOLUME /results
WORKDIR /results

# remove packages
RUN apk del wget build-base gcc abuild binutils binutils-doc gcc-doc \
    && rm -fr /knocker-0.7.1

ENTRYPOINT ["knocker"]


# build Docker image (KnockerVM)
$ docker build -t alpine/knocker .

# run Knocker help (KnockerVM)
$ docker run -ti --rm alpine/knocker --help

# run simple port scan (KnockerVM)
$ docker run -ti --rm alpine/knocker -H -SP 1 -EP 10

# run port scan with (KnockerVM)
$ docker run -ti --rm -v /home/docker:/results alpine/knocker -H -SP 80 -EP 90 -lf /results/report

# read report (KnockerVM)
$ cat report

Feel free to edit and/or expand! Knocker self can be found here.

SSH jump host example with vagrant

This time shows the tutorial two topics in one. The first topic is: “How an easy to configure SSH host jump”. The 2nd topic is: “Provisioning examples for Vagrant”.


  • Vagrant installed
  • VirtualBox installed

File content

- name: jump_host
  box: centos/7
  cpus: 1
  memory: 1024
- name: host_a
  box: centos/7
  cpus: 1
  memory: 1024
- name: host_b
  box: centos/7
  cpus: 1
  memory: 1024
Host *
  Compression yes
  AddressFamily inet
  Protocol 2
  ServerAliveInterval 60
  ServerAliveCountMax 30

Host jump_host
  HostName 192.168.x.x
  User testuser

Host host_*
  ProxyCommand ssh jump_host -W %h:%p
  User testuser
# -*- mode: ruby -*-

require 'yaml'

machines = YAML.load_file('machines.yml')
KEY_LOCATION = "~/.ssh/"

Vagrant.require_version ">= 1.8.1"
Vagrant.configure(API_VERSION) do |config|

  # loop
  machines.each do |machines|
    # vm setup + provisioning
    config.vm.define machines["name"] do |machine| = machines["box"]
      machine.vm.synced_folder ".", "/vagrant", disabled: true "private_network", ip: machines["ip"]

      machine.vm.provider :virtualbox do |vb| = machines["name"]
        vb.cpus = machines["cpus"]
        vb.memory = machines["memory"]
        vb.gui = false

      # provisioning: only jump_host
      if machines["name"] == 'jump_host'
        # prompt for interface "public_network"

        machine.vm.provision "shell", inline: <<-SHELL
          cd /etc && sudo sed -i '/#AllowTcpForwarding yes/c\AllowTcpForwarding yes' ssh/sshd_config
          sudo systemctl restart sshd.service
          cd /etc && sudo grep -q 'host_a' hosts || echo '  host_a' >> hosts
          cd /etc && sudo grep -q 'host_b' hosts || echo '  host_b' >> hosts

      # provisioning: all
      machine.vm.provision "file", source: KEY_LOCATION, destination: "/tmp/pub.key"

      machine.vm.provision "shell", inline: <<-SHELL
        sudo useradd testuser
        sudo mkdir /home/testuser/.ssh
        sudo touch /home/testuser/.ssh/authorized_keys
        sudo cat /tmp/pub.key > /home/testuser/.ssh/authorized_keys
        sudo rm -f /tmp/pub.key
        sudo chmod 0700 /home/testuser/.ssh
        sudo chmod 0644 /home/testuser/.ssh/authorized_keys
        sudo chown -R testuser:testuser /home/testuser/.ssh

Note: Replace values for HostName “192.168.x.x” by real IP from jump_host and KEY_LOCATION “~/.ssh/”!


# create and goto project
$ mkdir ~/Projects/JumpHostExample && cd ~/Projects/JumpHostExample

# create yaml file
$ vim machines.yml

# create Vagrantfile
$ vim Vagrantfile

# start Vagrant
$ vagrant up

# get IP from jump_host (for config)
$ ssh jump_host -c "ip addr show enp0s9"

# create or edit ssh config
$ vim ~/.ssh/config

# ssh into hosts via jump_host
$ ssh host_a
$ ssh host_b