Next post: Trace travel debugging

Send files between virtual machine and host

A nice benefit of using a guest VM is that the host machine is protected from any malware that infects the guest (barring security vulnerabilities in the VM software itself).

So, sometimes I'll use a VM for this purpose. A few months ago I was downloading soundfonts, and some of the soundfonts were only available in a compressed .sfark format needing specific .sfark software to use. Downloading an obscure program from some shareware site from 15 years ago seemed a bit risky, and so I installed this software on a VM just to be safe.

Since the point is to be concerned with safety and security, what is a good way to transfer files to and from the guest VM and host machine?

  • VirtualBox's shared folders/network drives/USB connectivity is not a good choice because malware loves these vectors
  • VirtualBox's default way of transfering files, simulating a SMB network drive, also doesn't seem safe.
  • Probably same for the shared clipboard feature.
  • Logging into an email client on the guest could divulge password information.
  • Running a ftp server or web server on the host takes time and introduces an attack surface.


So, my idea is to send the raw file data over a socket, and write a Python script to re-assemble it into a file.

In VirtualBox, I configured bridged networking so that the guest can ping the host but all shared folders/networks are disabled. I install Python on the guest and use scripts to transfer files over a socket by ip address. (To see the guest's ip, in Windows ipconfig, in Linux ifconfig). Type this ip address into the second script below.

First run this script on the host, which I put together from some stack overflow answers,
import socket

f  = open('output_file', 'wb')
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
portnumber = 8206
conn.bind(('', portnumber))
conn.listen(5)
channel, details = conn.accept()
  
print('connected')
while True:
  received_data = channel.recv(4096)
  if not received_data:
    break
  f.write(received_data)
  
f.close()
print("transfer complete!")
channel.close()


Then, run this script on the guest, after changing the file name and ip address.
import socket

file_to_send = '/path/to/filename'
ip_of_recipient = '192.168.xxxxxxx.yyyyyy'
portnumber = 8206
f = open(file_to_send, 'rb')
all_file_contents = f.read()

conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.connect((ip_of_recipient, portnumber))
conn.sendall(all_file_contents)
conn.shutdown(socket.SHUT_RDWR)
conn.close()


To ensure that the data is intact, I can use a quick checksum with SHA512,
import hashlib

f1 = open(r'./filename','rb')
hash = hashlib.sha512()
while True:
  # update the hash 256k at a time
  buf = f1.read(1024 * 256)
  if not buf:
    break
  hash.update(buf)

print(hash.hexdigest())


The chances of any malware reaching the host machine are low. Only one file is written to a port that is quickly closed, and the file contents are checked with SHA512. I still don't use this to transfer any executable files, but in general I think this is a safer way to copy files from a VM.