Virtualbox, wie dem Gast eine bestimmte CPU aufgezwungen wird

13

Ich habe einen XP-Gast in VirtualBox, Windows 8-Host. Der Gast zeigt den Prozessor transparent wie den Host (i5 2500k). Die meisten Installationsprogramme erkennen diese Prozessoren jedoch nicht und geben keinen nicht unterstützten Prozessor an.

Gibt es eine Möglichkeit, den Gast zu täuschen, dass dies ein alter Prozessor ist? Wenn ich mich richtig erinnere, hatte VMWare eine CPU-Maskierungsfunktion. Gibt es etwas Ähnliches in virtualbox?

IUnbekannt
quelle
Welche Software installieren Sie, die das CPU-Modell überprüft?
Darth Android
Doppelte Agentenkontrollen, Orca und Wix. Dies ist für ein VB6-Projekt, das wir wiederbeleben möchten.
IUnknown

Antworten:

18

Grundlagen zu VirtualBox und CPUID

Sie müssen die VBoxInternal/CPUM/HostCPUIDExtradaten der virtuellen Maschine festlegen. Dadurch meldet VirtualBox dem Gast benutzerdefinierte Ergebnisse für die CPUID- Anweisung. Abhängig vom Wert des EAX-Registers gibt dieser Befehl Informationen über den Prozessor zurück - beispielsweise Hersteller, Typ, Familie, Stepping, Marke, Cache-Größe, Funktionen (MMX, SSE, SSE2, PAE, HTT) usw. Je mehr Ergebnisse Wenn Sie verstümmeln, ist die Wahrscheinlichkeit höher, den Gast zu täuschen.

Mit dem vboxmanage setextradataBefehl können Sie die virtuelle Maschine konfigurieren. Beispielsweise,

vboxmanage setextradata WinXP VBoxInternal/CPUM/HostCPUID/80000003/ebx 0x50202952

bewirkt, dass die CPUID 50202952₍₁₍ im EBX-Register zurückgibt, wenn der Aufruf mit EAX auf 80000003₍₁₍ eingestellt ist. (Hexadezimalzahlen werden ab sofort als 0xNN oder NNh geschrieben.)

Festlegen der Zeichenfolge des CPU-Herstellers

Wenn EAX 0 ist (oder 80000000h bei AMD), gibt die CPUID den Anbieter als ASCII-Zeichenfolge in den Registern EBX, EDX, ECX zurück (beachten Sie die Reihenfolge). Für eine AMD-CPU sehen sie folgendermaßen aus:

| Register | Value      | Description                    |
|----------|------------|--------------------------------|
| EBX      | 6874_7541h | The ASCII characters "h t u A" |
| ECX      | 444D_4163h | The ASCII characters "D M A c" |
| EDX      | 6974_6E65h | The ASCII characters "i t n e" |

(Aus der AMD CPUID-Spezifikation , Unterabschnitt "CPUID Fn0000_0000_E")

Wenn Sie EBX, EDX und ECX verketten, erhalten Sie AuthenticAMD.

Wenn Sie über Bash und die traditionellen Unix-Dienstprogramme verfügen, können Sie den Anbieter mit den folgenden Befehlen einfach festlegen:

vm='WinXP'  # UUID works as well
# The vendor string needs to have 12 characters!
vendor='AuthenticAMD'
if [ ${#vendor} -ne 12 ]; then
    exit 1
fi
ascii2hex() { echo -n 0x; od -A n --endian little -t x4 | sed 's/ //g'; }

registers=(ebx edx ecx)
for (( i=0; i<${#vendor}; i+=4 )); do
    register=${registers[$(($i/4))]}
    value=`echo -n "${vendor:$i:4}" | ascii2hex`
    # set value to an empty string to reset the CPUID, i.e.
    # value=""
    for eax in 00000000 80000000; do
        key=VBoxInternal/CPUM/HostCPUID/${eax}/${register}
        vboxmanage setextradata "$vm" $key $value
    done
done

Festlegen der Zeichenfolge der CPU-Marke

Wenn EAX 80000002h, 80000003h, 80000004h ist, gibt die CPUID 16 ASCII-Zeichen der Markenzeichenfolge in den Registern EAX, EBX, ECX, EDX zurück, insgesamt 3 * 16 = 48 Zeichen; Die Zeichenfolge wird mit einem Nullzeichen abgeschlossen . Beachten Sie, dass diese Funktion mit Pentium 4-Prozessoren eingeführt wurde. So kann die Markenzeichenfolge auf einem Pentium 4-Prozessor aussehen:

| EAX Input Value | Return Values   | ASCII Equivalent |
|-----------------|-----------------|------------------|
| 80000002h       | EAX = 20202020h | "    "           |
|                 | EBX = 20202020h | "    "           |
|                 | ECX = 20202020h | "    "           |
|                 | EDX = 6E492020h | "nI  "           |
|-----------------|-----------------|------------------|
| 80000003h       | EAX = 286C6574h | "(let"           |
|                 | EBX = 50202952h | "P )R"           |
|                 | ECX = 69746E65h | "itne"           |
|                 | EDX = 52286D75h | "R(mu"           |
|-----------------|-----------------|------------------|
| 80000004h       | EAX = 20342029h | " 4 )"           |
|                 | EBX = 20555043h | " UPC"           |
|                 | ECX = 30303531h | "0051"           |
|                 | EDX = 007A484Dh | "☠zHM"           |
|-----------------|-----------------|------------------|

(Entnommen aus der Programmierreferenz für Intel Architecture Instruction Set Extensions , Unterabschnitt 2.9, "CPUID Instruction", Tabelle 2-30. ☠ ist das Nullzeichen (numerischer Wert 0).)

Wenn Sie die Ergebnisse zusammenfassen, erhalten Sie Intel(R) Pentium(R) 4 CPU 1500MHz☠.

Wenn Sie über Bash und die traditionellen Unix-Dienstprogramme verfügen, können Sie die Marke mit den folgenden Befehlen einfach festlegen:

vm='WinXP'  # UUID works as well
# The brand string needs to have 47 characters!
# The null terminator is added automatically
brand='              Intel(R) Pentium(R) 4 CPU 1500MHz'
if [ ${#brand} -ne 47 ]; then
    exit 1
fi
ascii2hex() { echo -n 0x; od -A n --endian little -t x4 | sed 's/ //g'; }

eax_values=(80000002 80000003 80000004)
registers=(edx ecx ebx eax)
for (( i=0; i<${#brand}; i+=4 )); do
    eax=${eax_values[$((${i} / 4 / 4))]}
    register=${registers[$((${i} / 4 % 4 ))]}
    key=VBoxInternal/CPUM/HostCPUID/${eax}/${register}
    value=`echo -n "${brand:$i:4}" | ascii2hex`
    # set value to an empty string to reset the CPUID, i.e.
    # value=""
    vboxmanage setextradata "$vm" $key $value
done

Wenn Sie eine Windows-Eingabeaufforderung haben, können Sie die Marke auf Intel(R) Core(TM)2 CPU 6600 @ 2.40 GHz1 setzen, indem Sie Folgendes ausführen:

set vm=your-vm-name-or-uuid
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000002/eax 0x65746e49
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000002/ebx 0x2952286c
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000002/ecx 0x726f4320
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000002/edx 0x4d542865
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000003/eax 0x43203229
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000003/ebx 0x20205550
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000003/ecx 0x20202020
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000003/edx 0x20202020
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000004/eax 0x30303636
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000004/ebx 0x20402020
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000004/ecx 0x30342e32
vboxmanage setextradata %vm% VBoxInternal/CPUM/HostCPUID/80000004/edx 0x007a4847

Computer: Intel (R) Core (TM) 2-CPU 6600 bei 2,40 GHz

1 Die HostCPUIDWerte wurden aus dem VirtualBox-Fehlerbericht Nr. 7865 übernommen .

Cristian Ciupitu
quelle
Vielen Dank. Ich habe meine VM mit VERR_CFGM_INVALID_CHILD_PATH beschädigt.
Ben Sinclair
1
sed muss mit G-Flagge verwendet werden:'s/ //g'
Ben Sinclair
1
Was für eine großartige Antwort! Und mit dem Aufkommen der Kaby Lake-CPUs wurde dies plötzlich aufgrund einer bestimmten Richtlinie von Redmond, Windows 7 auf diesen nicht zu unterstützen, am interessantesten. Es scheint, dass nur die Anweisungen zum Festlegen von "EAX = 1" fehlen: Processor Info and Feature Bits ", da es sich nicht um einfache Zeichenfolgen handelt (mit nur der CPU-Marke erkennt CPU-Z die CPU weiterhin als KL); Wer weiß?
sxc731
1
Per forums.virtualbox.org/viewtopic.php?f=2&t=77211#p359428 , kann es ein besserer (prägnanter, mehr unterstützt) seinen Weg , um diese Werte zu setzen.
Mark Amery
@MarkAmery, danke für den Link. Es funktioniert gut für die Marke, aber nicht so gut für den Anbieter, da der Anbieter nicht im EAX-Register festgelegt ist und der --cpuidUnterbefehl einen Wert für das EAX-Register erfordert.
Cristian Ciupitu
5

Hier ist ein Ansatz, der es ermöglicht, die Host-CPU genau als bestimmte CPU zu tarnen, anstatt zu versuchen, die erforderlichen Einstellungen zu erraten. Sie benötigen Zugriff auf eine Maschine, auf der VirtualBox auf dieser Host-CPU ausgeführt wird, damit Sie ihre cpuidRegister sichern können (wahrscheinlich ist es am besten, eine Architektur zu wählen, die der Ihrer tatsächlichen CPU als Modell ziemlich ähnlich ist). Wenn Sie keine zur Hand haben, können Sie sich umsehen (ich hatte zum Beispiel Erfolg bei Reddit).

  1. Erstellen Sie eine "Modell" -Datei aus der CPU, die Sie emulieren möchten:

    vboxmanage list hostcpuids > i7_6600U
    
  2. Stellen Sie auf dem Zielhost sicher, dass die zu ändernde VM nicht ausgeführt wird. Vielleicht möchten Sie für alle Fälle eine Sicherungskopie erstellen.
  3. Führen Sie das folgende Skript aus, um die Modelldatei ( i7_6600Uhier) in die Definition Ihrer VBox-VM ( my_vm_namehier) zu laden :

    #!/bin/bash
    vm=my_vm_name
    model_file=i7_6600U
    
    egrep -e '^[[:digit:]abcdef]{8} ' $model_file |
    while read -r line; do
        leaf="0x`echo $line | cut -f1 -d' '`"
        # VBox doesn't like applying leaves between the below boundaries so skip those:
        if [[ $leaf -lt 0x0b || $leaf -gt 0x17 ]]; then
            echo "Applying: $line"
            vboxmanage modifyvm $vm --cpuidset $line
        fi
    done
  4. Jetzt können Sie Ihre VM ausführen und die maskierte CPU genießen (Hinweis: Sie müssen das obige Skript nur einmal ausführen).

Wenn Sie jemals die CPU-Maskerade zurücksetzen müssen, können Sie vboxmanage modifyvm $vm --cpuidremove $leaffür jedes der Blätter in der obigen Schleife ( man vboxmanageist Ihr Freund) verwenden.

Dies funktioniert für mich seit ein paar Monaten einwandfrei und maskiert eine Kaby Lake-CPU (i7_7500U) als eine Skylake-CPU (i7_6600U) auf einem Ubuntu 17.04-Host mit VBox 5.1.22. Der Ansatz sollte auf jedem Host-Betriebssystem funktionieren, vorausgesetzt, Sie können ein Äquivalent des obigen kleinen Bash-Skripts für dieses Betriebssystem erstellen.

sxc731
quelle
In Bezug auf den Teil "Einstellen der Zeichenfolge des CPU-Herstellers" habe ich einen Kommentar: Sie müssen sicherstellen, dass der Name des Herstellers auf AMD-CPU auf "AuthenticAMD" und auf Intel-CPU auf "GenuineIntel" geändert wird. Wenn Sie "GenuineIntel" auf einer AMD-CPU verwenden, bricht die virtuelle Maschine sehr wahrscheinlich zusammen.
Abulhol
Vielen Dank dafür! Es hat wie ein Zauber auf meinem Ryzen 7700K gewirkt. Ich habe ein altes AMD Socket SF2-Motherboard verwendet, um die CPUID zu ermitteln, indem ich eine Ubuntu LiveCD ausgeführt, VirtualBox in der Live-Umgebung installiert und den Befehl vboxmanage ausgeführt habe. Auf der Hostseite habe ich das Windows-Subsystem für Linux installiert, damit ich in Windows 10 eine Bash-Eingabeaufforderung ausführen und das von Ihnen freigegebene Skript ausführen kann. Jetzt kann ich meine Windows 7-VM so täuschen, als würde ich einen A8-5600K einsetzen.
Njbair
Ich bin froh, dass das auch für dich funktioniert! Ich hätte klarstellen sollen, dass dies alles keinen Linux-Host erfordert. Es wird nicht einmal die "Modell" -Datei gesammelt, sondern es wird lediglich VirtualBox auf diesem Computer ausgeführt. Das Bash-Skript mag kompliziert aussehen, aber alles, was es tut, ist, die Zeilen aus der Modelldatei zu lesen, Blätter zwischen 0000000bund 00000017(einschließlich) zu überspringen und sie vboxmanage modifyvm my_vm_name --cpuidset <line>einzeln durchlaufen zu lassen.
sxc731
Kein Problem, ich hatte WSL sowieso auf dem Host-Computer installiert, und die Ubuntu LiveCD war nur, weil es der schnellste Weg war, das alte AMD-Motherboard hochzufahren.
Njbair