← All writing

Kali on Hyper-V Gen1: black console and an RDP session that dies in zero seconds

Four stacked causes behind a Kali VM with no desktop and an xrdp session that closes instantly — and why the obvious fix for the first one breaks the second.

I run my offensive-security lab as a Kali Linux VM on a Windows Server Hyper-V host. After a rebuild it came up broken in two ways at once:

  • the Hyper-V console showed a black screen, or at best a text TTY — no Xfce desktop;
  • RDP connected, showed the session for a fraction of a second, and closed. Zero seconds.

Searching either symptom gives you a dozen one-line answers, and each of them fixes part of the problem while quietly breaking something else. It took four separate fixes, in the right order, to get both the console and RDP working and surviving reboots. Here is the chain.

The setup that makes this hard

A Generation 1 Hyper-V VM exposes two video devices to the guest:

  • a legacy emulated PCI adapter (1414:5353, the Microsoft synthetic VGA), and
  • the hyperv_drm kernel driver on VMBus, which shows up as /dev/dri/card0.

Most guides assume there is one GPU. With two, Xorg has to be told exactly which one to use, or it picks badly.

Cause 1 — nomodeset disables the driver you need

Somewhere along the way the kernel command line had picked up nomodeset, a common “fix” for black screens on VMs. On this VM it is the cause: it prevents hyperv_drm from doing kernel mode-setting, so Xorg has no usable display at all.

# /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="quiet"   # no nomodeset
sudo update-grub

Cause 2 — legacy X drivers fight KMS

xserver-xorg-video-vesa and xserver-xorg-video-fbdev were installed. With KMS working again, they still got probed and competed with the modesetting driver. Remove them:

sudo apt-get remove --purge xserver-xorg-video-vesa xserver-xorg-video-fbdev

Cause 3 — Xorg picks the wrong GPU and deletes its own screen

With both devices visible, Xorg tried the legacy PCI framebuffer, failed, and logged the memorable:

Cannot run in framebuffer mode. Please specify busIDs for all framebuffer devices

…then deleted Screen 0. The fix is to pin the modesetting driver to the DRM device explicitly and stop Xorg from auto-adding the other GPU:

# /etc/X11/xorg.conf.d/20-modesetting.conf
Section "ServerFlags"
    Option "AutoAddGPU" "off"
EndSection

Section "Device"
    Identifier "Card0"
    Driver "modesetting"
    Option "kmsdev" "/dev/dri/card0"
EndSection

After this the console desktop came back. RDP was now worse.

Cause 4 — xrdp reads the same config directory

This is the step no one-liner mentions. The Xorg instance that xorgxrdp starts for each RDP session is launched with its own -config file but no -configdir, so it also loads everything in /etc/X11/xorg.conf.d/. My new file told it to open /dev/dri/card0 — which the console session already owned. The RDP Xorg failed to start and the session died instantly.

The fix is to scope the config to the physical seat, so only the console’s Xorg matches it and xrdp falls back to its own dummy driver:

Section "ServerFlags"
    Option "AutoAddGPU" "off"
EndSection

Section "Device"
    Identifier "Card0"
    MatchSeat  "seat0"
    Driver     "modesetting"
    Option     "kmsdev" "/dev/dri/card0"
EndSection

Section "Screen"
    Identifier "Screen0"
    MatchSeat  "seat0"
    Device     "Card0"
EndSection

Section "ServerLayout"
    Identifier "Layout0"
    MatchSeat  "seat0"
    Screen 0   "Screen0"
EndSection
sudo systemctl restart lightdm xrdp xrdp-sesman

Console and RDP both work, and the setup survives reboots.

Takeaways

  • Count your GPUs first. lspci | grep -i vga and ls /dev/dri/ tell you in five seconds whether you are in the two-device situation.
  • nomodeset is a diagnostic, not a fix. It turns off the driver most modern VMs need.
  • Global X config is global. Anything in xorg.conf.d also affects xrdp’s Xorg. Scope it with MatchSeat when it is meant for the physical console only.
  • One gotcha that remains: Xfce won’t happily run two sessions for the same user, so don’t stay logged in on the console as the user you connect with over RDP.

I keep the final config plus a one-command restore script with my lab notes, so rebuilding the VM is now a two-minute job instead of an afternoon.