This article explains how to create a stealthy virtual machine that can be used for multiple things.
I made this for my personnal use so there is still room for improvement.

Virtual machine detection can be done in a lot of ways however, except for the most basic ones it always revolves around identifying markers that are hard coded into the hypervisor. For example PCI ID’s, plug and play devices names, etc
To defeat this in addition to configuring the VM so it doesn’t appear like one we will have to patch and compile the hypervisor.

1. Compiling QEMU Link to heading

⚠️ Always maintain an installation of QEMU managed by your package manager, because it may delete necessary runtime dependencies otherwise! The binaries you compile are saved in /usr/local/bin, so they will take precedence.

Build dependencies Link to heading

Arch: sudo pacman -S git wget base-devel glib2 ninja python

Ubuntu: sudo apt install git build-essential ninja-build python-venv libglib2.0-0 flex bison

Patching and building QEMU Link to heading

Go to the directory where you want to keep the sources and run

wget https://raw.githubusercontent.com/furtest/furtest/refs/heads/main/qemu_patch/qemu-10.1.0.patch
wget https://download.qemu.org/qemu-10.1.0.tar.xz
tar xvJf qemu-10.1.0.tar.xz
cd qemu-10.1.0
../qemu-10.1.0.patch
./configure --disable-werror
make -j$(nproc)
sudo make install

For some reasons the build fails with Werror enabled so we disable it.
If you only need the x86_64 system hypervisor you can add --target-list=x86_64-softmmu to the configure command which will significantly shorten the compile time.

2. Creating the VM Link to heading

You need to make the following changes to the configuration :

  • Use BIOS not UEFI
  • Change the MAC address (eg: 8c:1f:66:b8:67:84)
  • Set the video to VGA
  • Each of those snippets are things you need to have in your config, some of the text (like the </hyperv> ) is here for you to locate where to put the thing.
  <cpu mode='host-model' >
    <feature policy='disable' name='hypervisor'/>
  </cpu>

<kvm>
  <hidden state='on'/>
</kvm>
</features>
<vendor_id state='on' value='blackmega'/>
</hyperv>

In the uuid field below replace with your uuid (top of the file)

<vcpu placement='static'>6</vcpu>
<sysinfo type='smbios'>
<bios>
  <entry name='vendor'>Dell Inc.</entry>
  <entry name='version'>2.5.2</entry>
  <entry name='date'>01/28/2015</entry>
  <entry name='release'>2.5</entry>
</bios>
<system>
  <entry name='manufacturer'>Dell Inc.</entry>
  <entry name='product'>PowerEdge R720</entry>
  <entry name='version'>Not Specified</entry>
  <entry name='serial'>H5DR542</entry>
  <entry name='uuid'>SHOULD MATCH THE UUID OF THE DOMAIN .. CHECK THE ELEMENT uuid ABOVE</entry>
  <entry name='sku'>SKU=NotProvided;ModelName=PowerEdge R720</entry>
  <entry name='family'>Not Specified</entry>
</system>
<baseBoard>
  <entry name='manufacturer'>Dell Inc.</entry>
  <entry name='product'>12NR12</entry>
  <entry name='version'>A02</entry>
  <entry name='serial'>.5KT0B123.ABCDE000000001.</entry>
  <entry name='asset'>Not Specified</entry>
  <entry name='location'>Null Location</entry>
</baseBoard>
<chassis>
  <entry name='manufacturer'>Lenovo</entry>
  <entry name='version'>none</entry>
  <entry name='serial'>J30038ZR</entry>
  <entry name='asset'>none</entry>
  <entry name='sku'>Default string</entry>
</chassis>
<oemStrings>
  <entry>myappname:some arbitrary data</entry>
  <entry>otherappname:more arbitrary data</entry>
</oemStrings>
</sysinfo>

3. Installing windows Link to heading

During the windows installation there are 2 annoying things

  • Windows 11 hardware requirements.
  • Microsoft forcing you to connect to a microsoft account.

Once the installer has started open a cmd with shift F10 and run regedit.
Then go to KEY_LOCAL_MACHINE\SYSTEM\Setup, create a new key called LabConfig and inside three DWORD values

  • BypassTPMCheck = 1
  • BypassSecureBootCheck = 1
  • BypassRAMCheck = 1

To use a local account :

  1. Configure until the windows installation is done which is when you have to choose the language again.
  2. Then open a cmd again and run OOBE\BYPASSNRO
  3. Wait for reboot
  4. Once rebooted run ipconfig /release (if you forget you will have to go from step 1 again)

Sources Link to heading