Extract OEM Windows Licence to run Windows in Qemu

Context

When I buy a new computer, my first first action is to install Linux based distribution instead of Windows. However, sometimes I need to have Windows virtual machine to run some program not available on Linux.

The problem is I don’t want to pay a licence just for this while there is an OEM licence shipped with each computers.

In this blogpost we will see how can we extract licence and use it into qemu virtual machine.

ACPI tables

ACPI is an open standard interface between hardware and OS. It is provided by UEFI with AcpiTableProtocol which allow manipulate ACPI tables. (ACPI spec overview)

On modern laptop, OEM licence key is written in ACPI tables on MSDM table.
This table contain the following informations (Microsoft official document about it) :

Field Byte Length Byte Offset Description
Signature 4 0 MSDM
Length 4 4 Length, in bytes, of the entire table.
Revision 1 8 0x01
Checksum 1 9 Checksum of the entire table.
OEMID 6 10 An OEM-supplied string that identifies the OEM.
OEM Table ID 8 16 Optional motherboard/BIOS logical identifier.
OEM Revision 4 24 OEM revision number of the table for the supplied OEM Table ID.
Creator ID 4 28 Vendor ID of the utility that created the table.
Creator Revision 4 32 Revision of the utility that created the table.
Software Licensing Structure Variable length 36 Proprietary data structure that contains all the licensing data necessary to enable Windows activation. Details can be found in the appropriate Microsoft OEM licensing kit by first visiting the Microsoft OEM website here.

On linux you can read this table by doing this :

1
sudo cat /sys/firmware/acpi/tables/MSDM

If you want to read table byte by byte to match upper table you can do this :

1
sudo cat /sys/firmware/acpi/tables/MSDM | xxd

We will use this table into file to insert it in QEMU command line.

How to

First we will collect system informations to have qemu SMBIOS configuration. To achieve this :

1
sudo dmidecode -t system

We’ll need the following informations :

  • Manufacturer
  • Product Name
  • UUID
  • SKU
  • Family

You can pass this informations as parameters in Qemu cmdline but we will generate binary file to have short command and to easily use theses parameters in other VMs.

If you want to do it with arguments you can find details on Qemu documentation.

To generate smbios file I’ve done a small bash script to do that :

gen_smbios.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/bin/bash

set -eo pipefail

# Get all necessary fields from dmidecode
output=$(sudo dmidecode -t system)
manufacturer=$(echo "$output" | awk -F: '/Manufacturer:/ {print $2; exit}' | xargs)
product_name=$(echo "$output" | awk -F: '/Product Name:/ {print $2; exit}' | xargs)
uuid=$(echo "$output" | awk -F: '/UUID:/ {print $2; exit}' | xargs | tr '[:upper:]' '[:lower:]' | sed 's/\-//g')
sku=$(echo "$output" | awk -F: '/SKU Number:/ {print $2; exit}' | xargs)
family=$(echo "$output" | awk -F: '/Family:/ {print $2; exit}' | xargs)

# Function to pad strings with null bytes
pad_string() {
local string="$1"
local length="$2"
local padded_string
padded_string=$(printf "%-${length}s" "$string")
echo -n "$padded_string"
}

# Create the smbios.bin file
{
pad_string "$manufacturer" 32 | dd conv=notrunc bs=1 count=32
pad_string "$product_name" 32 | dd conv=notrunc bs=1 count=32
pad_string "$uuid" 16 | dd conv=notrunc bs=1 count=16
pad_string "$sku" 32 | dd conv=notrunc bs=1 count=32
pad_string "$family" 32 | dd conv=notrunc bs=1 count=32
} > smbios.bin

echo "smbios.bin created successfully."

To run the script :

1
2
chmod +x gen_smbios.sh
sudo ./gen_smbios.sh

Then we will extract MSDM table into file to pass is as qemu arg :

1
sudo cat /sys/firmware/acpi/tables/MSDM > MSDM.bin

Let’s start a virtual machine

Prepare VM

1
2
3
4
5
6
mkdir windows-vm
cd windows-vm
qemu-img create -f qcow2 disk0.img 60G
sudo cat /sys/firmware/acpi/tables/MSDM > MSDM.bin
sudo ./gen_smbios.sh
# Download windows ISO and put it in folder

And start VM :

1
sudo qemu-system-x86_64 -m 4096 -hda disk0.img -boot d -enable-kvm -smp cores=2 -vga std -acpitable file=MSDM.bin -smbios file=smbios.bin -cdrom Win10_22H2_French_x64v1.iso

Once Windows installed, you can go to Windows activation parameters. You will see that Windows is enabled by software licence.

N.B.: By this way, you don’t need to provide licence key during installation process.