# Starting a VM as an unprivileged Linux User

After reading this article you will be able to start *any* OS of *any* architecture from your (unprivileged) [Linux shell](https://thc.org/segfault) (and log in as *root* to start (for example) Docker inside the emulated OS).

**This is a great way to test or compile exploits and tools.**

The instructions have been tested on [**Segfault's Disposable Root Servers**](https://thc.org/segfault).

---

First, we will boot an *Ubuntu Linux x86\_64*, then an *Ubuntu Linux aarch64* (arm64), then an *Ubuntu Linux PowerPC* (ppc64el) and lastly an *OpenBSD x86\_64*.

**Boot an AMD64 (x86\_64) "Ubuntu 22.04 LTS Jammy"-Linux:**

```bash
[[ -z $URL ]] && URL="https://cloud-images.ubuntu.com/releases/jammy/release/ubuntu-22.04-server-cloudimg-amd64.img"
IMAGE="${URL##*/}"
OS="${IMAGE%%-*}"
ARCH="${IMAGE##*-}"
ARCH="${ARCH%%.*}"
[[ $ARCH =~ ^[0-9]*$ ]] && ARCH="x86_64" # No ARCH in name
apt-get install -y cloud-image-utils qemu-system
mkdir -p ~/.vm/"${OS}-${ARCH}" &>/dev/null && \
cd ~/.vm/"${OS}-${ARCH}" && \
cat >metadata.yaml <<-__EOF__
instance-id: iid-${SF_HOSTNAME:-THC}01
local-hostname: ${SF_HOSTNAME:-THC}-${OS}-${ARCH}-guest
__EOF__
```

Create an SSH key and configure the VM. The host's `/sec` directory will be shared with the VM:

```bash
[[ ! -f ~/.ssh/id_ed25519 ]] && ssh-keygen -t ed25519 -N "" -f ~/.ssh/id_ed25519
cat >user-data.yaml <<-__EOF__
#cloud-config
users:
  - name: root
    lock_passwd: false
    # OpenBSD: hashed_passwd: '$2b$06$mbQdo90rertzSkoBBeZCzePTMtdkx7cuOax8xv.1W5ta0tJiNAlMG'
    hashed_passwd: '$(echo segfault | openssl passwd -6 -stdin)'
    ssh_authorized_keys:
      - $(ssh-keygen -y -f ~/.ssh/id_ed25519)
bootcmd:
  #FreeBSD: - sed -i "" 's/#PermitRootLogin.*/PermitRootLogin yes/g' /etc/ssh/sshd_config
  - mkdir -p /sec
mounts:
  - [ host0, /sec, 9p ]
__EOF__
# Edit this file for OpenBSD or FreeBSD
```

Create the `seed.img` file (aka cloud-init) and download and enlarge the cloud image:

```bash
cloud-localds seed.img user-data.yaml metadata.yaml
[[ ! -f "${IMAGE:?}" ]] && wget "${URL}"
qemu-img resize "${IMAGE}" 32G
```

Boot the VM:

```bash
unset ARGS
[[ -e /dev/kvm ]] && ARGS+=("-enable-kvm")
[[ $ARCH == amd64 ]] && ARCH="x86_64"
[[ $ARCH == arm64 ]] && ARCH="aarch64"
[[ $ARCH == aarch64 ]] && ARGS=("-machine" "virt" "-bios" "/usr/share/qemu-efi-aarch64/QEMU_EFI.fd" "-cpu" "cortex-a57")
[[ $ARCH == ppc64el ]] && ARCH=ppc64le
[[ $ARCH == ppc64le ]] && unset ARGS
qemu-system-${ARCH} \
    -m 1G \
    -nographic \
    "${ARGS[@]}" \
    -device virtio-net-pci,netdev=net0 \
    -netdev user,id=net0,hostfwd=tcp:127.0.0.1:2222-:22 \
    -drive "if=virtio,format=qcow2,file=${IMAGE}" \
    -drive "if=virtio,format=raw,file=seed.img" \
    -virtfs local,path=/sec,mount_tag=host0,security_model=passthrough
```

The Linux Kernel will boot and you can log in with `root` / `segfault` or with `ssh -p 2222 root@0`:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1695820430358/caae5956-e524-4f32-80c5-704a19799722.jpeg align="center")

Optional: Install and run an Alpine Linux inside Docker (inside the guest VM):

```bash
sudo bash
bash -c "$(curl -fsSL https://get.docker.com)"
docker run --rm -it alpine
```

---

Set the `URL=` to a different location to start any other OS of any architecture. Examples:

```bash
# Ubuntu ARM64 (aarch64)
URL="https://cloud-images.ubuntu.com/releases/jammy/release/ubuntu-22.04-server-cloudimg-arm64.img"
# Ubuntu PowerPC-64
URL="https://cloud-images.ubuntu.com/releases/jammy/release/ubuntu-22.04-server-cloudimg-ppc64el.img"
# Centos x86_64
URL="https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2"
# OpenBSD x86_64
URL="https://object-storage.public.mtl1.vexxhost.net/swift/v1/1dbafeefbd4f4c80864414a441e72dd2/bsd-cloud-image.org/images/openbsd/7.3/2023-04-22/ufs/openbsd-7.3-2023-04-22.qcow2"
# FreeBSD x86_64
URL="https://object-storage.public.mtl1.vexxhost.net/swift/v1/1dbafeefbd4f4c80864414a441e72dd2/bsd-cloud-image.org/images/freebsd/13.2/2023-04-21/zfs/freebsd-13.2-zfs-2023-04-21.qcow2"
```

Note:

1. For OpenBSD, edit `user-data.yaml` and change:  
    `hashed_passwd: '$2b$06$mbQdo90rertzSkoBBeZCzePTMtdkx7cuOax8xv.1W5ta0tJiNAlMG'`
    
2. For FreeBSD, edit `user-data.yaml` and change:
    
    `sed -i "" 's/#PermitRootLogin.*/PermitRootLogin yes/g' /etc/ssh/sshd_config`
    

Other Cloud Servers:

1. [https://bsd-cloud-image.org/](https://bsd-cloud-image.org/)
    
2. [https://cloud-images.ubuntu.com/releases/](https://cloud-images.ubuntu.com/releases/)
    
3. [https://cloud.centos.org/centos/7/images/](https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2)
    

Go all the way down the rabbit hole and read about [cross-compiling exploits](https://iq.thc.org/cross-compiling-exploits). Or read how to [Start a User-Mode-Linux](https://iq.thc.org/starting-a-user-mode-linuxdebian-os-as-an-unprivileged-linux-user).

---

*Shoutz to crt, MRX7014, Matthew and Ray San.*
