4 poin oleh GN⁺ 2025-04-07 | 1 komentar | Bagikan ke WhatsApp
  • eShard, berdasarkan pekerjaan emulasi iOS open-source yang sudah ada, menargetkan emulator yang dapat mem-boot iOS 14 di QEMU serta menjalankan UI dan sebagian aplikasi
  • Alih-alih memasukkan patch kernel langsung ke dalam QEMU, mereka memanfaatkan PongoOS dan checkra1n KPF untuk memisahkan patch XNU, lalu membuat isi patch dapat ditinjau dengan tool berbasis diff Mach-O
  • Karena emulasi GPU Apple Silicon terlalu luas cakupannya, mereka lebih dulu memilih software rendering, dan memastikan lewat patch QuartzCore pada iPhone yang di-jailbreak bahwa UI UIKit dapat digambar meski lambat
  • Untuk mengatasi masalah layar yang tetap hitam, mereka melanjutkan dengan menonaktifkan randomisasi alamat, debugging GDB, bypass pairing lockdownd, menonaktifkan PAC, porting ke QEMU 8.2.1, dan otomatisasi patch dyld cache
  • Pada akhirnya, mereka menampilkan UI input passcode UIKit di layar QEMU dan memanipulasi textbox lewat input keyboard VNC, serta menyiapkan fondasi yang diperlukan hingga SpringBoard dapat ditampilkan

Titik awal emulasi iOS

  • Dalam peninjauan solusi open-source yang sudah ada, alephsecurity/xnu-qemu-arm64 pernah dicoba dijalankan, tetapi proyeknya berstatus read-only
  • Setelah itu, TrungNguyen1909/qemu-t8030 digunakan sebagai titik awal
    • Memungkinkan restore iOS melalui koneksi USB menggunakan QEMU “companion” kedua
    • Mendukung menjalankan iOS 14
    • Berbasis versi QEMU yang lebih baru
    • Menyediakan wiki yang membahas cara menjalankan emulator
  • Dengan memodifikasi System/Library/xpc/launchd.plist, akses shell dan SSH dapat diperoleh dengan cepat
  • Target jangka panjangnya adalah emulasi iOS yang fungsional dengan UI dan setidaknya mampu menjalankan sebagian aplikasi

Memisahkan patch kernel dengan PongoOS

  • Proyek t8030 memasukkan kode patch kernel XNU ke QEMU itu sendiri, tetapi karena kemungkinan jumlah patch akan bertambah, diperlukan struktur yang lebih rapi
  • Berdasarkan pengalaman dengan iPhone yang benar-benar di-jailbreak, mereka meninjau cara menerapkan patch checkra1n menggunakan PongoOS
  • Dalam alur jailbreak umum, setelah perangkat di-pwn dengan checkmate, PongoOS disuntikkan ke SRAM dan modul checkra1n-kpf dikirim melalui USB
    • Dalam pekerjaan ini, untuk menghindari penanganan USB awal, mereka memperbesar SRAM iPhone yang diemulasikan dan menggunakan PongoOS serta modul checkra1n KPF
  • Pada tahap awal menjalankan PongoOS, masalah muncul karena tidak ada kode inisialisasi yang biasanya dijalankan bootrom atau iBoot
    • Pengaturan FPU diperlukan sebelum instruksi double/float
    • Masalah ini diselesaikan dengan merujuk dokumentasi ARM dan kode terkait QEMU yang sudah ada
  • Fitur perangkat setelah A13 tidak didukung Pongo, sehingga merusak pattern matching pada sebagian patch
    • Instruksi Pointer Authentication (PAC) seperti autda dan xpacd ditambahkan
    • Apple menggunakan slide yang berbeda
    • Pada patch task_for_pid(tfp0), ditemukan perbedaan alamat dan pola biner antara iPhone X dan iPhone 11

File patch kernel deklaratif

  • Pongo memungkinkan penggunaan patch checkra1n yang sudah ada untuk berbagai versi iOS, tetapi metode penerapan dinamis sulit dibaca, dimodifikasi, dan dibagikan
  • Untuk memperlakukannya seperti patch kode sungguhan, mereka membuat file patch deklaratif dengan tool internal
    • Membuat file patch teks berbasis perbedaan assembly dengan melakukan diff pada dua Mach-O
    • Menulis program terpisah untuk menerapkan file patch yang dihasilkan ke biner
  • Setelah boot dengan Pongo, mereka memakai QEMU monitor untuk men-dump bagian memori yang dipatch Pongo
  • Setelah itu, kernel yang sudah dipatch disusun ulang dan sebuah file patch besar yang memuat semua modifikasi dibuat
  • Dengan memecah patch besar tersebut dan memberi komentar, menjadi mungkin untuk meninjau dan mengendalikan bagian kernel mana yang dipatch

Strategi menggambar layar tanpa GPU

  • Rendering grafis pada iPhone modern pada akhirnya melewati API Metal milik Apple dan membutuhkan GPU sungguhan
  • Karena emulasi GPU Apple Silicon dianggap terlalu kompleks, mereka meninjau dua opsi
    • Software rendering menggunakan bootarg gpu=0 seperti yang dulu dimungkinkan pada iOS lama
    • Meneruskan panggilan Metal ke iPhone sungguhan atau Mac dengan macOS untuk melakukan rendering
  • Di iOS 14, opsi bootarg gpu=0 pada kernel XNU sudah hilang
  • Dari analisis framework QuartzCore dengan Ghidra, software rendering ternyata dipanggil sebagai fallback ketika renderer Metal tidak ada
  • Pada iPhone sungguhan yang di-jailbreak, mereka mempatch QuartzCore dan memastikan software rendering digunakan
    • UI menjadi jauh lebih lambat
    • Artefak muncul di beberapa area, dan bagian tersebut kemungkinan secara langsung meminta rendering Metal
  • Dari eksperimen ini, mereka menilai software rendering juga memungkinkan di QEMU untuk cakupan yang tidak memakai Metal atau OpenGL secara langsung, yaitu sebagian besar aplikasi UIKit

Eksperimen proxy panggilan Metal

  • Alternatif mem-proxy panggilan Metal juga diuji dengan dua iPhone fisik
    • Mem-parsing semua header iOS dengan LLVM
    • Pointer objek Objective-C di server direpresentasikan sebagai pointer stub di klien
    • Menghasilkan kode pertukaran struct dan pointer secara otomatis
    • Melakukan hook pada semua fungsi dan metode
    • Meneruskan semua panggilan ke server dan mengembalikan hasil eksekusinya
  • Round trip panggilan dasar untuk inisialisasi Metal sebagian berhasil
  • Namun, bahasa Objective-C dan API Metal sangat kompleks dan kaya fitur, sehingga beban kerja untuk membuatnya benar-benar berjalan sangat besar
  • Pendekatan ini ditunda, dan mereka memutuskan menyelesaikan masalah lain terlebih dahulu dengan software rendering meski ada batasan
  • Framework iOS juga mengekspos private API yang tidak ada di header publik, dan meski ada cara untuk mem-parsingnya menjadi header, sebagian besar sulit digunakan langsung dan menambah kompleksitas

Debugging IOSurface dan framebuffer

  • Setelah mencoba software rendering, perangkat framebuffer minimal tetap diperlukan, tetapi QEMU t8030 asli belum mengimplementasikannya
  • Mereka menemukan fork QEMUAppleSilicon yang memiliki pekerjaan dukungan IOMFB dan menggunakannya untuk debugging display
  • Saat melakukan restore iOS dengan versi ini, logo Apple dan progress bar terlihat, tetapi pada boot normal layar tetap sepenuhnya hitam
  • Setelah melihat kext IOMFB dengan Ghidra dan meninjau implementasi framebuffer QEMU, tampaknya ada dua mode
    • Raw framebuffer pada alamat hardware tetap
    • API yang lebih kompleks yang mengatur beberapa plane melalui register dan menulis data surface lewat DMA
  • Mereka dapat menampilkan surface ARGB sembarang melalui raw framebuffer, tetapi saat boot sistem tidak menulis ke framebuffer tersebut
  • Pada mode display kedua, terlihat trace bahwa kernel mengatur graphical plane melalui register, tetapi setelah itu tidak ada output layar

Menonaktifkan randomisasi alamat dan debugging GDB

  • Akses SSH saja membatasi observasi sistem saat berjalan, sehingga perlu men-debug kernel dan user space dengan GDB
  • Randomisasi alamat kernel diatur saat inisialisasi board t8030, sehingga bisa dimatikan sepenuhnya
  • Di userland terdapat randomisasi executable dan randomisasi dynamic library di dalam dyld cache
    • Executable dinonaktifkan dengan mempatch fungsi _load_machfile di kernel
    • Library dyld cache sekali dirandomisasi alamatnya saat boot, lalu dimuat pada alamat yang sama oleh semua executable
  • Dyld cache di /System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e berisi semua library framework dalam bentuk blob biner besar
  • Mereka membuat tool C yang melakukan dlopen pada semua library framework dan mencantumkan image yang dimuat serta offset-nya dengan fungsi _dyld*
  • Dengan menggabungkan cara ini dan proses mengembalikan alamat GDB, library di dyld cache dapat di-debug
  • Yang terutama menjadi perhatian adalah kext IOMFB, backboardd, SpringBoard, dan QuartzCore
  • Kemudian mereka juga menemukan cara menonaktifkan dyld cache dengan patch kernel, dan menggunakan library Rust object dari proyek Gimli untuk menemukan langsung alamat virtual dyld cache di host
  • Untuk debugging user space diperlukan GDB server di guest, misalnya mereka menggunakan paket debugserver dari Procursus

Log sistem dan bypass lockdownd

  • Dengan GDB, backboardd tampak mulai berjalan normal, tetapi untuk memahami situasi sebenarnya diperlukan log sistem
  • Pada iPhone sungguhan, log sistem dapat dilihat dengan idevicesyslog setelah pairing USB dengan komputer
  • Proses pairing mencakup pembuatan key pair, private key disimpan di iPhone, dan lockdownd memverifikasi identitas komputer
  • Di lingkungan emulasi, interaksi USB dimungkinkan, tetapi lockdownd tidak berjalan dengan benar
  • Hasil analisis Ghidra menunjukkan lockdownd mencoba memakai keybag untuk menyimpan private key, dan ini membutuhkan SEP yang tidak ada
  • Mereka menyuntikkan shellcode yang menggantikan sebagian fungsi yang ada agar key pair publik/privat yang sudah dibuat sebelumnya dibaca dari filesystem, lalu dimuat setiap kali lockdownd mencoba mengambilnya dari keybag
  • Dengan debugging dan patch tambahan, mereka menyimulasikan bahwa pengguna telah memercayai komputer dan iPhone sudah dibuka kuncinya
  • Pada akhirnya, QEMU companion dapat melakukan pairing dengan iPhone yang diemulasikan
  • Dari log terlihat bahwa QuartzCore berhasil diinisialisasi, mendeteksi ukuran display, dan menggunakan fallback software rendering
  • Semuanya tampak normal, tetapi layar tetap tidak tampil
  • Satu kesalahan terkait pixel format diakali dengan memaksa RGBA, tetapi kemudian dihapus

Masalah PAC dan porting QEMU 8

  • Saat memperbaiki kesalahan pixel format pada backboardd, muncul masalah tambahan akibat fitur keamanan iOS
  • Pemeriksaan tanda tangan saat load dan runtime sudah diselesaikan dengan patch kernel, tetapi saat menjalankan backboardd yang dimodifikasi, terjadi kegagalan Pointer Authentication
  • Pointer Authentication adalah fitur yang ditambahkan di ARMv8.3, dan ini adalah masalah baru yang dihadapi pada board t8030 yang sedang diemulasikan, bukan t8015 yang sebelumnya digunakan
  • Awalnya mereka mempertimbangkan mengubah semua instruksi PAC menjadi NOP atau instruksi ekuivalen tanpa PAC
  • Kemudian diketahui bahwa biner ARM64 PAC dapat dibangun dengan dua cara
    • Menggunakan set instruksi PAC khusus yang hanya berjalan pada CPU ARMv8.3+
    • Menggunakan set instruksi “unused” yang ditafsirkan sebagai PAC pada ARMv8.3+ dan sebagai instruksi ekuivalen tanpa PAC pada ARM lama
  • Mereka memverifikasi perilaku ini dengan pengujian pada buildroot dan sistem ARM64 Linux, lalu memastikan biner untuk t8030 menggunakan set instruksi backward compatible arm64e
  • Mereka menduga jika PAC enforcing saja dimatikan di QEMU, kode akan berjalan seperti kode tanpa PAC, tetapi di QEMU 7 ini tidak berfungsi, sementara QEMU 8 memiliki perilaku berbeda
  • Codebase saat ini di-porting ke QEMU 8.2.1
    • Instruksi khusus Apple genter, gexit
    • Kode penanganan GL exception levels
    • Banyak modifikasi pada generic code QEMU membuat porting sulit
  • Setelah berbagai panic XNU, debugging kernel GDB, debugging QEMU sendiri, dan git bisect, iOS kembali bisa boot di QEMU 8
  • Dengan demikian, PAC dapat dinonaktifkan dan kode executable apa pun bisa dimodifikasi di lokasi yang diinginkan

Melacak penyebab layar hitam

  • Karena menurut log sistem backboardd tampak berjalan normal, mereka menelusuri lebih dalam alasan tampilan tidak muncul
  • Jika raw ARGB frame ditulis langsung ke alamat, display sungguhan berubah, dan mereka dapat menggambar pada beberapa graphical plane
  • Jadi implementasi display sendiri tampak normal, dan tersisa tiga kemungkinan
    • backboardd tidak menulis apa pun
    • Menulis ke alamat yang salah
    • Data yang ditulis tidak valid
  • Dengan QEMU monitor, mereka memperoleh alamat fisik yang tidak kontigu, lalu men-dump memori DMA fisik menggunakan skrip dan menggabungkannya menjadi satu file
  • Mereka menafsirkannya sebagai frame ARGB dengan ffplay, tetapi tidak memperoleh hasil yang bermakna
  • Berikutnya, mereka memasang breakpoint pada iosurface_lock untuk mendapatkan alamat surface yang dipetakan ke memori backboardd, lalu menyelidikinya
  • Sesekali ditemukan bentuk aneh yang tampak seperti logo Apple, tetapi tampaknya ada masalah pada cara frame ditulis
  • Ketika pekerjaan yang sama dilakukan pada iPhone 10 sungguhan, raw ARGB frame lengkap dari layar saat ini dapat di-dump dengan mudah
  • Pada iPhone 11, yaitu setelah t8030, surface tampaknya dikirim dalam bentuk terkompresi yang dapat diproses GPU
  • Karena hal ini tidak terjadi pada t8015 milik iPhone X, mereka memodifikasi DTB QEMU agar mengirim chip-id sebagai 8015, bukan 8030
  • Hasilnya, setelah boot, logo Apple muncul di layar

Progress bar dan patch aktivasi

  • Meski logo Apple sudah muncul, UI tidak bergerak lebih jauh, dan log sistem menampilkan banyak pesan dari berbagai daemon dan library
  • Mereka melanjutkan dengan menebak kesalahan mana yang benar-benar terkait masalah UI, lalu memperbaikinya satu per satu
  • Masalah terkait aktivasi pengguna ditemukan, dan sumber kesalahannya adalah daemon mobileactivationd serta framework SpringBoardFoundation
  • Setelah keduanya dipatch, progress bar putih yang mirip dengan yang terlihat pada tahap restore muncul
  • Progress bar tampak bergerak, tetapi setelah beberapa jam terlihat berhenti di 90%

Peningkatan iterasi patch dyld cache dan user space

  • Berkat penonaktifan randomisasi alamat, patch user space dan framework dyld cache menjadi mungkin
  • Seperti pada kernel, mereka membuat file patch teks untuk tiap biner/library dan menerapkannya dengan tool internal
  • Karena dyld cache berukuran sekitar 2 GB, mempatch langsung atau menyalinnya berulang lewat SSH tidak praktis
  • Karena bekerja di lingkungan Linux, NVMe juga tidak bisa dimodifikasi langsung
  • Tool diff/patch internal diperluas agar sesuai untuk dyld cache dengan menemukan offset framework di dalam blob dyld cache
  • Mereka menambahkan opsi untuk menghasilkan perintah dd sederhana yang bisa langsung diterapkan di iPhone, beserta perintah revert
  • Setelah filesystem di-remount dalam mode baca/tulis, modifikasi dyld cache dapat diiterasi dengan cepat dengan menerapkan perintah dd
  • Agar perubahan diterapkan, hanya perlu reboot iOS
  • Agar cara ini bekerja, sebagian patch tambahan pada pemeriksaan tanda tangan kernel diperlukan

Menjalankan PreBoard dan menampilkan layar UIKit

  • Sebelum menyelesaikan progress bar yang macet, mereka bereksperimen dengan proses sistem PreBoard
  • PreBoard tampaknya hanya ditampilkan kepada pengguna saat terjadi masalah seperti pembaruan yang terhenti
  • Seperti SpringBoard, ini adalah aplikasi sistem yang menggambar langsung melalui backboardd, sehingga dapat dijalankan langsung dari command line
  • Hasil eksekusinya menampilkan layar putih yang meminta “swipe to upgrade”
  • Berdasarkan pengalaman sebelumnya menggunakan server VNC pada iPhone fisik, mereka menambahkan VNC, dan setelah berbagai kegagalan, layar dibuka bukan dengan swipe melainkan tombol keyboard
  • Segera setelah dibuka, QEMU berhenti berjalan karena iOS menggunakan illegal instruction
  • Analisis backboardd menunjukkan framework vImage menggunakan instruksi AMX (Apple Matrix Coprocessor) untuk operasi grafis terakselerasi hardware seperti _vHorizontal_Scale_ARGB_8888_Accelerate
  • AMX adalah set instruksi proprietary Apple yang tidak diimplementasikan di CPU ARM emulasi QEMU
  • Framework vImage memiliki versi software alternatif yang hanya memakai instruksi ARM generik, sehingga mereka kembali mempatch agar versi itu digunakan
  • Hasil akhirnya, jendela UIKit sungguhan ditampilkan, dengan layar input passcode dan textbox yang berfungsi
  • Event keyboard yang disuntikkan melalui VNC dapat digunakan untuk mengetik ke textbox
  • Pada titik ini, komponen yang dibutuhkan agar SpringBoard tampil dengan benar sudah siap, dan memulainya tampak hanya soal waktu
  • Tulisan berikutnya berlanjut ke Part 2

1 komentar

 
GN⁺ 2025-04-07
Komentar Hacker News
  • Akan menyenangkan kalau https://github.com/devos50/qemu-ios berkembang hingga mendukung iPhone OS 3.x, sehingga aplikasi iPhone awal bisa dicoba kembali sebagai bentuk pelestarian digital
    https://github.com/touchHLE/touchHLE juga bagus, tetapi selain aplikasi yang sangat dasar, biasanya perlu patch per aplikasi

    • iPhone 11 yang diemulasikan dengan QEMU dapat mendukung iOS 13.x hingga iOS 18.x: https://github.com/ChefKissInc/QEMUAppleSilicon
      Untuk menjalankan aplikasi 32-bit di iOS 10, QEMU juga perlu mendukung iPhone 7
    • Akan luar biasa kalau kita bisa mencoba lagi game-game awal yang kini tak punya pengganti, atau aplikasi lama yang keren
  • Dulu saya pernah mengemulasikan NumWorks N0100[1] dan HP Prime G1[2] dengan QEMU, sampai firmware resminya benar-benar bisa berjalan
    [1] https://github.com/boricj/qemu/tree/numworks_calculators
    [2] https://github.com/boricj/qemu/tree/s3c2416-boricj

  • Kalau proyek ini diterapkan dengan cara yang menarik, sepertinya kita bisa memasang image pmOS minimal dan versi QEMU ini di ponsel yang dukungan hardware postmarketOS-nya cukup baik, lalu mem-boot iOS di ponsel Android
    Mungkin juga QEMU bisa dikustomisasi lebih jauh untuk meneruskan hardware ponsel seperti modem dan Bluetooth ke mesin virtual iOS

    • Idenya menarik, tetapi masalah pertamanya adalah menemukan ponsel yang kameranya bisa dipakai dan panggilan teleponnya juga berfungsi dengan baik di postmarketOS
      Rasanya itu saja sudah cukup memuaskan, bahkan tanpa emulasi iOS/Android
    • Kalau sekadar untuk bersenang-senang, tidak masalah, tetapi dalam praktiknya ini akan sangat tidak efisien sehingga sulit menjadi perangkat yang layak dipakai, dan beban kerjanya juga sangat besar
    • Apakah ini terasa seperti semacam paravirtualisasi? Sepertinya akan jadi proyek yang menarik
  • Versi arsip: https://archive.ph/l1CwO

  • Apakah ini berarti sekarang kita bisa melakukan hal-hal seperti pengujian Safari atau kompilasi untuk iOS di sistem Linux tanpa hardware Apple?

  • https://github.com/ChefKissInc/QEMUAppleSilicon
    Ini adalah perangkat Apple Silicon yang diemulasikan di QEMU, dan saat ini hanya mendukung iPhone 11
    Video demo: https://nitter.poast.org/eshard/status/1908162866609311962

  • Saya mencoba mengikuti panduan menjalankannya: https://github.com/TrungNguyen1909/qemu-t8030/wiki/Bringing-...
    Terjadi crash berkali-kali, lebih banyak daripada yang ingin saya akui, tetapi hasilnya memang cukup keren

  • Tidak ada penyebutan tentang koneksi jaringan. Sepertinya chipset Wi-Fi atau modem seluler tidak diemulasikan
    Saya penasaran bagaimana perangkat yang diemulasikan ini akan dihubungkan ke internet. Mungkin lewat semacam Ethernet melalui USB

    • iOS mendukung USB Ethernet
  • Apa yang dibutuhkan agar Apple mau menerima pengembangan iOS multiplatform?

    • Apple tidak akan pernah melakukannya. Tindakan mereka sejauh ini justru menunjukkan kebalikannya: kontrol penuh atas perangkat dan ekosistem, tidak bekerja sama dengan perusahaan lain soal standar, serta kontrol App Store yang ketat
      Dari sudut pandang Apple, mereka tidak mendapat apa-apa dengan mengizinkan model pengembangan seperti itu
    • Apple menjual hardware melalui software. Itulah sebabnya iMessage untuk Android tidak pernah muncul
      Agar hal seperti ini terjadi, cara Apple memandang dunia harus berubah, dan itu tampaknya akan menjadi perubahan besar seperti ketika Microsoft sampai batas tertentu menerima Linux lewat WSL dan .NET untuk Linux
    • Budaya perusahaannya harus berubah total
    • Apple adalah perusahaan hardware. Mengapa mereka ingin mendukung sesuatu di hardware yang tidak mereka jual?
    • Sepertinya harus sampai ada ancaman pemecahan perusahaan, seperti pada masa Internet Explorer
  • Apakah ada repositori yang bisa dipakai untuk mereproduksi ini?