Virtualbox, cara memaksa CPU tertentu untuk tamu

13

Saya punya tamu XP di VirtualBox, host windows 8. Tamu menunjukkan prosesor secara transparan sama dengan tuan rumah (i5 2500k). Namun sebagian besar penginstal tidak mengenali prosesor ini dan gagal melanjutkan menyatakan prosesor yang tidak didukung.

Apakah ada cara untuk membodohi tamu sehingga berpikir ini adalah prosesor lama? Jika saya ingat dengan benar VMWare memiliki fitur masking CPU, apakah ada sesuatu yang serupa di virtualbox?

IUnknown
sumber
Perangkat lunak apa yang Anda instal yang memeriksa model CPU?
Darth Android
Kontrol Agen Ganda, Orca dan Wix. Ini untuk proyek VB6 yang kami coba untuk menghidupkan kembali.
IUnknown

Jawaban:

18

Dasar-dasar VirtualBox dan CPUID

Anda perlu mengatur VBoxInternal/CPUM/HostCPUID extradata dari mesin virtual. Ini akan membuat VirtualBox melaporkan hasil khusus untuk CPUID instruksi untuk tamu. Bergantung pada nilai register EAX, instruksi ini mengembalikan informasi tentang prosesor - hal-hal seperti vendor, tipe, keluarga, loncatan, merek, ukuran cache, fitur (MMX, SSE, SSE2, PAE, HTT), dll. Semakin banyak hasil Anda mangle, semakin tinggi peluang untuk menipu tamu.

Anda dapat menggunakan vboxmanage setextradata perintah untuk mengkonfigurasi mesin virtual. Sebagai contoh,

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

akan membuat CPUID mengembalikan 50202952₍₁₆₎ dalam register EBX, ketika dipanggil dengan EAX diatur ke 80000003₍₁₆₎. (Mulai sekarang, angka heksadesimal akan ditulis sebagai 0xNN atau NNh.)

Mengatur string vendor CPU

Jika EAX adalah 0 (atau 80000000h pada AMD), CPUID mengembalikan vendor sebagai string ASCII dalam register EBX, EDX, ECX (perhatikan urutannya). Untuk CPU AMD, mereka terlihat seperti ini:

| 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" |

(Diambil dari Spesifikasi AMD CPUID , ayat "CPUID Fn0000_0000_E")

Jika Anda menggabungkan EBX, EDX dan ECX, Anda akan mendapatkannya AuthenticAMD.

Jika Anda memiliki Bash dan utilitas Unix tradisional, Anda dapat dengan mudah mengatur vendor dengan perintah berikut:

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

Mengatur string merek CPU

Jika EAX adalah 80000002h, 80000003h, 80000004h, CPUID mengembalikan 16 karakter ASCII dari string merek dalam register EAX, EBX, ECX, EDX, dengan total 3 * 16 = 48 karakter; string itu diakhiri dengan karakter nol . Perhatikan bahwa fitur ini diperkenalkan dengan prosesor Pentium 4. Inilah bagaimana string merek dapat terlihat pada prosesor Pentium 4:

| 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"           |
|-----------------|-----------------|------------------|

(Diambil dari Intel Architecture Instruction Set Referensi Pemrograman Ekstensi , ayat 2.9, "Instruksi CPUID", tabel 2-30. ☠ adalah karakter nol (nilai numerik 0).)

Jika Anda menyatukan hasilnya, Anda akan mendapatkannya Intel(R) Pentium(R) 4 CPU 1500MHz☠.

Jika Anda memiliki Bash dan utilitas Unix tradisional, Anda dapat dengan mudah mengatur merek dengan perintah berikut:

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

Jika Anda memiliki prompt perintah Windows, Anda dapat mengatur merek Intel(R) Core(TM)2 CPU 6600 @ 2.40 GHz 1 dengan menjalankan:

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 @ 2.40 GHz

1 Itu HostCPUID nilai diambil dari laporan bug VirtualBox # 7865 .

Cristian Ciupitu
sumber
Terima kasih. VM saya rusak dengan VERR_CFGM_INVALID_CHILD_PATH.
highmaintenance
1
sed harus digunakan dengan bendera G: 's/ //g'
highmaintenance
1
Jawaban yang bagus! Dan dengan munculnya CPU Kaby Lake, ini tiba-tiba menjadi paling menarik karena kebijakan tertentu dari Redmond untuk tidak mendukung Windows 7 pada mereka ... Tampaknya semua yang hilang adalah petunjuk tentang cara mengatur "EAX = 1: Info Prosesor dan Bit Fitur "karena mereka bukan string sederhana (hanya dengan merek CPU, CPU-Z masih mengakui CPU sebagai KL); ada yang tahu?
sxc731
1
Per forums.virtualbox.org/viewtopic.php?f=2&t=77211#p359428 , mungkin ada cara yang lebih baik (lebih ringkas, lebih didukung) untuk menetapkan nilai-nilai ini.
Mark Amery
@MarkAmery, terima kasih atas tautannya. Ini berfungsi baik untuk merek, tetapi tidak begitu baik untuk vendor karena vendor tidak diatur dalam register EAX dan --cpuid subcommand membutuhkan nilai untuk register EAX.
Cristian Ciupitu
5

Berikut adalah pendekatan yang memungkinkan menyamar CPU host tepat sebagai CPU spesifik daripada mencoba menebak pengaturan yang diperlukan. Anda akan memerlukan akses ke mesin yang menjalankan VirtualBox pada CPU host tersebut sehingga Anda dapat membuangnya cpuid register (mungkin yang terbaik untuk memilih arsitektur yang cukup mirip dengan CPU Anda yang sebenarnya sebagai model). Jika Anda tidak memilikinya, Anda dapat bertanya-tanya (Saya sudah sukses di Reddit misalnya)

  1. Buat file "model" dari CPU yang ingin Anda tiru:

    vboxmanage list hostcpuids > i7_6600U
    
  2. Pada host target, pastikan VM yang ingin Anda modifikasi tidak berjalan; Anda mungkin ingin mengambil cadangan untuk berjaga-jaga.
  3. Jalankan skrip berikut untuk memuat file model ( i7_6600U di sini) ke dalam definisi VM VBox Anda ( my_vm_name sini):

    #!/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. Itu saja, Anda sekarang dapat menjalankan VM Anda dan menikmati CPU yang disamarkan (catatan: Anda hanya perlu menjalankan skrip di atas sekali).

Jika Anda perlu mengembalikan topeng CPU, Anda dapat menggunakan vboxmanage modifyvm $vm --cpuidremove $leaf untuk masing-masing daun di loop di atas ( man vboxmanage adalah temanmu).

Ini telah bekerja dengan sempurna selama beberapa bulan bagi saya, menyamar CPU Danau Kaby (i7_7500U) sebagai yang Skylake (i7_6600U) pada host Ubuntu 17,04 yang menjalankan VBox 5.1.22. Pendekatan harus bekerja pada OS host apa pun, asalkan Anda dapat membuat yang setara dengan skrip bash kecil di atas untuk OS tersebut.

sxc731
sumber
Mengenai bagian "Mengatur string vendor CPU", saya punya komentar: Anda harus memastikan untuk mengubah nama vendor menjadi "AuthenticAMD" pada AMD CPU dan "GenuineIntel" pada Intel CPU. Jika Anda menggunakan "GenuineIntel" pada CPU AMD, mesin virtual akan sangat mungkin rusak.
abulhol
Terima kasih banyak atas ini! Ini bekerja seperti pesona pada Ryzen 7700K saya. Saya menggunakan motherboard AMD Socket SF2 lama untuk mendapatkan CPUID dengan menjalankan LiveCD Ubuntu, menginstal VirtualBox di lingkungan langsung, dan menjalankan perintah vboxmanage. Di sisi host, saya menginstal Windows Subsystem untuk Linux sehingga saya bisa menjalankan Bash prompt di Windows 10 dan menjalankan skrip yang Anda bagikan. Sekarang saya dapat menipu Windows 7 VM saya dengan berpikir saya menjalankan A8-5600K.
njbair
Senang ini bekerja untuk Anda juga! Saya seharusnya mengklarifikasi bahwa semua ini tidak memerlukan host Linux; bahkan tidak mengumpulkan file "model", yang dibutuhkan hanyalah VirtualBox yang berjalan di mesin itu. Script bash mungkin terlihat rumit, tetapi yang dilakukannya hanyalah membaca baris dari file model, melewatkan daun di antara 0000000b dan 00000017 (inklusif) dan menjalankannya satu per satu hingga vboxmanage modifyvm my_vm_name --cpuidset <line> jadi ini bisa dengan mudah dilakukan dengan tangan karena ini sekali saja.
sxc731
Tidak masalah, saya menginstal WSL pada komputer host, dan Ubuntu LiveCD hanya karena itu adalah cara tercepat untuk memutar motherboard AMD lama.
njbair