2 poin oleh GN⁺ 2023-09-29 | 1 komentar | Bagikan ke WhatsApp
  • Saat melakukan Ctrl-C break-in dengan i386kd di Windows NT 3.1, sistem target 486DX4 reboot alih-alih menampilkan prompt kd>; penyebabnya adalah masalah kompatibilitas enhanced 486
  • KiSaveProcessorControlState dan KiRestoreProcessorControlState di NTOSKRNL.EXE memakai perbandingan word saat memeriksa tipe CPU, sehingga salah mengira 486 yang mendukung CPUID sebagai Pentium atau yang lebih baru
  • Karena CpuType dan CpuID di KPRCB terbaca bersama, nomor model 486 yang mendukung CPUID ditafsirkan lebih besar 256, sehingga terjadi akses ke register CR4 yang tidak ada pada 486
  • Debugging kernel berjalan normal pada 486DX-33 bawaan dan Am486DX4-NV8T write-through tanpa SMM, sehingga masalahnya dipersempit ke enhanced 486 yang menyediakan instruksi CPUID
  • Dengan menambal dua lokasi cmp ds:word_FFDFF138, 5 di NTOSKRNL.EXE menjadi byte compare, masalah dapat diperbaiki baik pada NT 3.1 Advanced Server asli maupun NT 3.1 SP3

Lingkungan reproduksi dan gejala

  • Windows NT 3.1 dipasang pada Compaq ProSignia 3080, lalu dicoba debugging kernel
    • Sistem ini pernah menjalankan Windows NT 3.1 dalam penggunaan nyata, dan tampaknya merupakan salah satu mesin yang secara eksplisit ditargetkan oleh Windows NT
    • RAM diperluas menjadi 128MB, dan Intel 486DX-33 bersoket diganti dengan AMD enhanced 486DX4-SV8B
    • CPU tersebut mendukung write-back cache dan SMM, serta dipasang pada soket adaptor tegangan
  • Penanganan dukungan 486DX4 di BIOS ditunda, dan CPU diatur dengan jumper ke pengali 2x
    • Tanpa dukungan L1 write-back dari chipset, pengaturan pengali 2x diharapkan kompatibel secara perangkat lunak dengan Intel 80486DX2-66
    • Intel 80486DX2-66 adalah opsi yang didukung sistem ini
  • Instalasi Windows NT 3.1 sendiri selesai dengan normal
  • CD Windows NT 3.1 menyertakan simbol debugging lengkap, sehingga debugging kernel dicoba
    • Tujuannya adalah menyelidiki mengapa NetDDE meninggalkan error di event log
    • Ada juga masalah sistem crash pada kartu Ethernet EISA tertentu, dan kemungkinan cacat hardware masih tersisa
  • Alih-alih kd atau ntkd dari Windows 10 development kit terbaru, perlu menggunakan i386kd yang disertakan dalam Windows NT 3.1 agar konfigurasi debugging kernel sesuai
  • Saat mencoba Ctrl-C break-in dari i386kd, mesin target tidak memberikan prompt kd>, melainkan reboot

Hal-hal yang disingkirkan sebagai penyebab

  • Memori dipastikan normal
  • Bukan kerusakan file sistem
  • Watchdog hardware yang me-reboot sistem saat kernel dihentikan untuk debugging tidak aktif
  • Adaptor USB-serial di sisi host berkomunikasi normal
    • Perangkat itu tampak seperti PL2301 palsu, tetapi bukan karena mengirim perintah debugger yang salah berupa perintah “reboot system”
    • Protokol KD memang memiliki perintah reboot system
  • Tidak terkait dengan opsi manajemen jarak jauh atau peringatan pada motherboard

Penyebab sebenarnya: ketidakcocokan enhanced 486 dengan kernel NT 3.1

  • Kernel Windows NT 3.1 tidak kompatibel dengan prosesor enhanced 486
  • Lebih spesifiknya, masalah muncul pada prosesor 486 yang menyediakan instruksi CPUID
  • Debugging kernel berjalan normal pada CPU berikut
    • 486DX-33 yang semula terpasang
    • Am486DX4-NV8T write-through dengan older non-enhanced core tanpa SMM
  • Jika tujuannya hanya menguji debugging kernel NT 3.1, lebih cocok menggunakan CPU yang memang kompatibel secara bawaan dengan Windows NT 3.1
  • Untuk memperbaiki NT itu sendiri, bug penentuan tipe CPU di NTOSKRNL.EXE harus ditambal

Jalur kode kernel tempat masalah muncul

  • Penyebab langsung ketidakcocokan adalah bug di KiSaveProcessorControlState
    • Fungsi pasangannya, KiRestoreProcessorControlState, juga memiliki bug serupa
  • KiSaveProcessorControlState dipanggil dari tiga lokasi di dalam NTOSKRNL.EXE
    • Saat exception dipantulkan ke kernel debugger melalui KdpTrap
      • Pada Ctrl-C break-in, breakpoint exception terjadi dari fungsi break-in polling di dalam timer tick interrupt
    • Saat KeBugCheckEx dipanggil, yaitu dalam situasi “blue screen”
    • Saat KiSaveProcessorState dipanggil
      • Jika analisis control flow NTOSKRNL.EXE oleh IDA lengkap, fungsi ini tidak diekspor dan juga tidak dipanggil di dalam NTOSKRNL, sehingga tampaknya tidak benar-benar terjadi
  • KiSaveProcessorControlState menyimpan status kontrol prosesor ke struktur CONTEXT yang diperluas
    • Menyimpan CR0, CR2, CR3
    • Pada Pentium atau yang lebih baru, juga menyimpan CR4
    • Menyimpan register debug DR0~DR3, DR6, DR7
    • Juga menyimpan pengaturan protected mode global seperti alamat GDT, alamat IDT, selector TSS aktif, dan selector LDT

Kesalahan interpretasi field KPRCB

  • Nilai di KPRCB digunakan untuk menentukan tipe prosesor
    • KPRCB adalah bagian dari KPCR
    • KPRCB untuk boot processor atau sistem uniprocessor berada di alamat virtual FFDFF120, dan alamat itu di-hardcode dalam metode terkait
  • Field terkait KPRCB NT 3.1 yang dirangkum oleh Geoff Chappell adalah sebagai berikut
    • +018 CHAR CpuType
    • +019 CHAR CpuID
    • +01A UShort CpuStep
  • Field-field ini diinisialisasi di KiSetProcessorType
    • Offset byte 18 pada prosesor 486 diatur ke 4
    • Prosesor Pentium diatur ke 5
    • Prosesor Pentium Pro serta Pentium II/III diatur ke 6
    • Offset byte 19 adalah boolean flag yang menunjukkan apakah prosesor mendukung CPUID dan berperilaku secara “reasonable”
  • Instruksi pembanding yang bermasalah membaca word, bukan byte, pada alamat FFDFF138
    • FFDFF138 adalah lokasi yang berjarak 18h byte dari awal KPRCB
    • Karena itu, bukan hanya CpuType, tetapi juga byte berikutnya, yaitu CpuID, ikut ditafsirkan sebagai bagian dari nomor model
  • Prosesor yang mendukung CPUID diperlakukan seolah nomor modelnya 256 lebih besar dari nilai sebenarnya
    • 80-4-86 yang mendukung CPUID diperlakukan oleh Windows NT 3.1 seperti 80-260-86
    • Karena 260 jauh lebih besar daripada batas Pentium yaitu 5, kernel menilai bahwa prosesor tersebut seharusnya memiliki CR4
    • Karena enhanced 486 tidak memiliki CR4, masalah terjadi pada jalur break-in

Cara menambal

  • Setelah bug dipastikan, perbaikannya sederhana
  • Di NTOSKRNL.EXE, instruksi cmp ds:word_FFDFF138, 5 hanya muncul dua kali
    • KiSaveProcessorControlState
    • KiRestoreProcessorControlState
  • Kedua lokasi harus diubah dari word compare menjadi byte compare
  • Dengan hex editor, tambal rangkaian byte berikut sebanyak dua kali
    • Lama: 66 83 3D 38 F1 DF FF 05
    • Baru: 90 80 3D 38 F1 DF FF 05
  • Perbaikan ini berlaku untuk NTOSKRNL.EXE dari distribusi NT 3.1 Advanced Server asli maupun NT 3.1 SP3

1 komentar

 
GN⁺ 2023-09-29
Komentar Hacker News
  • Dulu saya pernah membuat pemeriksaan port untuk memastikan apakah sebuah layanan masih hidup, dan hanya dengan membuka beberapa port TCP di mesin-mesin itu, saya pernah menjatuhkan separuh perusahaan
    Masa-masa yang absurd

    • Ada masa ketika Win95 bisa mati, atau bahkan diambil alih, hanya dengan dikirimi ping dengan cara tertentu
      Kita sudah melangkah sangat jauh
      https://en.wikipedia.org/wiki/Ping_of_death
      Di sebagian mesin juga ada kerentanan SMB yang tidak dipatch selama bertahun-tahun. Saat itu Metasploit sudah ada, jadi hanya dengan beberapa perintah, VNC bisa diinjeksi ke sebagian besar host Windows di jaringan lokal. Sekarang setidaknya kecepatan patching sangat cepat
    • Sepertinya jumlahnya jauh lebih banyak daripada “beberapa”
  • Ah, lubang kelinci retro computing. Terpisah secara aman dari konsekuensi dunia nyata, tetapi tetap sangat memuaskan
    Benar-benar jebakan madu untuk para geek. Pada akhirnya saya menekan tombol perluasan “lihat 6 komentar lagi”

    • Saya melihat kursor bergerak ke tombol perluasan itu dan nyaris berhasil menarik diri
      Mungkin hari ini saya masih bisa menyelesaikan sedikit pekerjaan
    • Kalau melihat komputer dari sebelum masa saya, seperti PET, saya berpikir pasti seru untuk dimainkan. Box IRIX lama juga boleh
      Tapi 486? Terlalu banyak kenangan tentang blue screen dan penantian tanpa akhir saat disk swapping karena memorinya tidak sanggup. Sepertinya masih terlalu dini bagi saya
    • Isi tulisannya tampaknya masih cukup relevan hingga hari ini
  • Solusinya sudah jelas” memang benar-benar tepat

    • Profesor matematika saya pernah bilang ada dua jenis soal: soal yang mudah, dan soal yang belum Anda pahami
    • Memang begitu setelah bug-nya teridentifikasi. Namun saya penasaran bagaimana bug seperti ini ditemukan
      Mungkin mereka terus membaca disassembly kode trap sampai menemukan masalahnya. Sepertinya tidak mungkin mereka bisa memakai QEMU atau sarana debugging lain
  • Wajib juga membaca metode yang terkubur di dalam komentar tersembunyi di bagian akhir

    • Auto-collapse komentar di Stack Overflow selalu tidak saya mengerti setiap kali melihatnya
      Bukan komentar dengan vote terendah yang disembunyikan, juga bukan yang terbaru atau terlama. Rasanya acak dan tidak perlu
      Kalau masalahnya ruang, menurut saya lebih baik diberi pagination daripada disembunyikan
  • Hal-hal seperti adapter slotket yang dulu dipakai untuk kompatibilitas di board Abit, Asus, mungkin juga MSI lama benar-benar punya kemampuan overclocking
    Kuncinya adalah berapa kecepatan RAM-nya, dan sampai clock berapa motherboard bisa bertahan pada pengaturan multiplier. Itu masa overclocking yang relatif awal, saat ada Celeron dan Pentium II
    Suatu waktu, demi kompatibilitas, saya memasang Celeron 600 ke adapter, lalu memasangnya lagi ke adapter Slot II to Socket 370 dalam konfigurasi seperti [1], dan berjalan baik di 1,2GHz. Bahkan seingat saya pernah menaikkannya sampai 1,4GHz di Windows ME, dan akhirnya CPU itu hangus
    [1]http://krick.3feetunder.com/370mod/

    • Overclocking memang menyenangkan, tetapi bagus juga bahwa CPU modern kini bisa mengontrol clock dan voltase dengan presisi untuk memanfaatkan margin keamanan lama
  • Jawaban pada pertanyaan itu benar-benar luar biasa
    Topiknya bagus dan jawabannya juga sangat bagus

    • Sebenarnya dia menjawab pertanyaannya sendiri. Tetap saja luar biasa
  • Keren bahwa orang yang bertanya juga memberi jawabannya sendiri
    Saya suka hal seperti ini. Senang sekali orang-orang tertarik pada retro computing
    Mendokumentasikan masalah dan solusinya seperti ini untuk semua orang adalah hal yang baik

  • Saya sudah tahu bahwa CPUID ini ide yang buruk

    • Lucu bahwa para developer Windows merasa perlu memasukkan bagian “trustworthiness” ke dalam struct
  • Kenapa timestamp pertanyaan dan jawabannya sama?

    • Itu dilakukan untuk berbagi informasi. Bisa terlihat bahwa penulis pertanyaan dan penulis jawaban adalah orang yang sama
      Mungkin dia menilai bahwa mengunggah informasi ini dalam bentuk tanya-jawab SO akan lebih bertahan lama daripada posting blog yang tidak akan ditemukan siapa pun
  • Apakah buruk kalau saya sudah tahu ini tentang apa tanpa membukanya?
    Sudahlah, saya harus pergi meneriaki anak-anak zaman sekarang agar keluar dari halaman rumah saya

    • Pemecahan masalah pada masa kami tumbuh dulu berbeda
      Yang bisa diandalkan hanya kecerdikan, dan kalau perlu para jagoan yang bisa dipanggil lewat telepon rumah. Tidak ada internet hebat yang penuh jawaban dengan tingkat kegunaan yang berbeda-beda