4 puan yazan GN⁺ 2025-04-07 | 1 yorum | WhatsApp'ta paylaş
  • eShard, mevcut açık kaynak iOS emülasyonu çalışmalarını temel alarak iOS 14’ü QEMU’da boot etmeyi ve UI ile bazı uygulamaları çalıştırabilen bir emülatör hedefliyor
  • QEMU’nun içine doğrudan kernel patch’leri eklemek yerine PongoOS ve checkra1n KPF kullanarak XNU patch’lerini ayırdı; Mach-O diff tabanlı araçlarla patch içeriklerinin incelenebilmesini sağladı
  • Apple Silicon GPU emülasyonu çok geniş kapsamlı olduğu için önce yazılımsal rendering seçildi; jailbreak’li iPhone’da QuartzCore patch’iyle UIKit UI’ın yavaş da olsa çizilebildiği doğrulandı
  • Ekranın siyah kalması sorununu çözmek için adres randomizasyonunu devre dışı bırakma, GDB debugging, lockdownd pairing bypass, PAC devre dışı bırakma, QEMU 8.2.1’e port etme ve dyld cache patch otomasyonuna devam edildi
  • Sonuçta QEMU ekranında UIKit passcode giriş UI’ı gösterildi ve VNC klavye girişiyle text box kontrol edildi; SpringBoard gösterimi için gerekli temel bileşenler hazırlandı

iOS emülasyonunun başlangıç noktası

  • Mevcut açık kaynak çözümleri incelerken alephsecurity/xnu-qemu-arm64 çalıştırılmıştı, ancak proje salt okunur durumdaydı
  • Daha sonra başlangıç noktası olarak TrungNguyen1909/qemu-t8030 kullanıldı
    • İkinci bir “companion” QEMU üzerinden USB bağlantısıyla iOS restore edilebiliyor
    • iOS 14 çalıştırma desteği var
    • Daha güncel bir QEMU sürümünü temel alıyor
    • Emülatörü çalıştırma yöntemini anlatan bir wiki sunuyor
  • System/Library/xpc/launchd.plist değiştirilerek hızlıca shell ve SSH erişimi sağlandı
  • Uzun vadeli hedef, UI’a sahip ve en azından bazı uygulamaları çalıştırabilen işlevsel iOS emülasyonu

Kernel patch’lerini PongoOS ile ayırma

  • t8030 projesi XNU kernel patch kodunu QEMU’nun kendisine eklemişti; ancak ileride patch sayısının artma olasılığı nedeniyle daha temiz bir yapıya ihtiyaç vardı
  • Gerçek jailbreak’li iPhone deneyimine dayanarak PongoOS ile checkra1n patch’lerini uygulama yöntemi incelendi
  • Normal jailbreak akışında, cihaz checkmate ile pwn edildikten sonra PongoOS SRAM’e enjekte edilir ve checkra1n-kpf modülü USB üzerinden aktarılır
    • Bu çalışmada ilk USB işlemlerinden kaçınmak için emüle edilen iPhone’un SRAM’i genişletildi ve PongoOS ile checkra1n KPF modülü kullanıldı
  • PongoOS’un ilk çalıştırılmasında bootrom veya iBoot’un yaptığı başlatma kodu olmadığı için sorunlar çıktı
    • double/float komutlarından önce FPU ayarı gerekiyordu
    • ARM dokümantasyonu ve mevcut QEMU ile ilgili kodlar referans alınarak çözüldü
  • A13 sonrası cihaz özelliklerini Pongo desteklemediği için bazı patch’lerin pattern matching’i bozuldu
    • Pointer Authentication(PAC) komutları olan autda, xpacd eklendi
    • Apple farklı bir slide kullanıyor
    • task_for_pid(tfp0) patch’inde iPhone X ile iPhone 11’in adres ve binary pattern farkları doğrulandı

Bildirimsel kernel patch dosyası

  • Pongo, çeşitli iOS sürümleri için mevcut checkra1n patch’lerini kullanmayı sağlıyordu; ancak dinamik uygulama yöntemi okumayı, değiştirmeyi ve paylaşmayı zorlaştırıyordu
  • Bunları gerçek kod patch’i gibi ele almak için dahili bir araçla bildirimsel patch dosyaları üretildi
    • İki Mach-O diff edilerek assembly farklarına dayalı metin patch dosyası oluşturuldu
    • Oluşturulan patch dosyasını binary’ye uygulayan ayrı bir program yazıldı
  • Pongo ile boot ettikten sonra QEMU monitor kullanılarak Pongo’nun patch’lediği bellek bölümleri dump edildi
  • Ardından patch’lenmiş kernel yeniden oluşturuldu ve tüm değişiklikleri içeren büyük bir patch dosyası üretildi
  • Büyük patch parçalara ayrılıp yorumlanarak kernel’in hangi bölümlerinin patch’lendiği incelenebilir ve kontrol edilebilir hale geldi

GPU olmadan ekran çizme stratejisi

  • Yeni iPhone’lardaki grafik rendering sonunda Apple’ın Metal API’sinden geçiyor ve gerçek GPU gerektiriyor
  • Apple Silicon GPU’yu emüle etmenin fazla karmaşık olacağı düşünülerek iki seçenek incelendi
    • Eski iOS’larda mümkün olduğu gibi gpu=0 bootarg ile yazılımsal rendering
    • Metal çağrılarını gerçek bir iPhone’a veya macOS çalıştıran bir Mac’e ileterek rendering yaptırmak
  • iOS 14’te XNU kernel’in gpu=0 bootarg seçeneği kaldırılmıştı
  • QuartzCore framework’ü Ghidra ile analiz edildiğinde, yazılımsal rendering’in Metal renderer olmadığında çağrılan bir fallback yapısı olduğu görüldü
  • Gerçek jailbreak’li iPhone’da QuartzCore patch’lenerek yazılımsal rendering kullanımı doğrulandı
    • UI çok daha yavaştı
    • Bazı alanlarda artefact’ler oluştu; bu bölümler doğrudan Metal rendering gerektiriyor olabilir
  • Bu deneyimle, Metal veya OpenGLi doğrudan kullanmayan kapsamda, yani çoğu UIKit uygulamasında, QEMU’da da yazılımsal rendering’in mümkün olabileceği düşünüldü

Metal çağrılarını proxy etme deneyi

  • Metal çağrılarını proxy etme alternatifi de iki fiziksel iPhone ile denendi
    • LLVM ile tüm iOS header’larının parse edilmesi
    • Sunucudaki Objective-C nesne pointer’larının istemcide stub pointer olarak temsil edilmesi
    • Struct ve pointer değişim kodunun otomatik üretilmesi
    • Tüm function ve method’ların hook edilmesi
    • Tüm çağrıların sunucuya iletilip yürütme sonucunun döndürülmesi
  • Metal initialization için temel çağrı gidiş dönüşleri kısmen başarılı oldu
  • Ancak Objective-C dili ve Metal API’si karmaşık ve çok kapsamlı olduğu için gerçek çalışmaya ulaşmak için gereken iş yükü çok büyüktü
  • Bu yöntem sonraya bırakıldı; sınırlamaları olsa da önce diğer sorunları yazılımsal rendering ile çözmeye karar verildi
  • iOS framework’lerinde public header’larda olmayan private API’ler de açığa çıkıyordu; bunları parse edip header oluşturmanın yolu vardı, ancak çoğunu doğrudan kullanmak zordu ve karmaşıklığı artırıyordu

IOSurface ve framebuffer debugging

  • Yazılımsal rendering denendikten sonra bile en azından temel bir framebuffer cihazı gerekiyordu; ancak orijinal t8030 QEMU’da bu uygulanmamıştı
  • IOMFB desteği üzerinde çalışılmış QEMUAppleSilicon fork’u bulunup display debugging için kullanıldı
  • Bu sürümle iOS restore edilirken Apple logosu ve progress bar görünüyordu, ancak normal boot sırasında ekran tamamen siyah kalıyordu
  • Ghidra ile IOMFB kext incelenip QEMU framebuffer implementasyonuna bakıldığında iki mod olduğu görüldü
    • Sabit donanım adresindeki raw framebuffer
    • Register’larla birden fazla plane ayarlayıp DMA ile surface verisi yazan daha karmaşık bir API
  • Raw framebuffer ile rastgele bir ARGB surface gösterilebiliyordu, ancak boot sırasında sistem bu framebuffer’a yazmıyordu
  • İkinci display modunda kernel’in register’larla graphical plane ayarladığı trace görülüyordu; ancak sonrasında ekrana çıktı gelmiyordu

Adres randomizasyonunu kapatma ve GDB debugging

  • Yalnızca SSH erişimiyle çalışan sistemi gözlemlemenin sınırları vardı; kernel ve user space’i GDB ile debug etme ihtiyacı doğdu
  • Kernel adres randomizasyonu t8030 board initialization’da ayarlanıyordu, bu yüzden tamamen kapatılabildi
  • Userland tarafında executable randomization ve dyld cache içindeki dynamic library randomization vardı
    • Executable için kernel’in _load_machfile fonksiyonu patch’lenerek devre dışı bırakıldı
    • dyld cache library’leri boot sırasında bir kez adres randomizasyonuna uğruyor ve sonra tüm executable’larda aynı adrese load ediliyordu
  • /System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e içindeki dyld cache, tüm framework library’lerini büyük bir binary blob olarak içeriyor
  • Tüm framework library’lerini dlopen eden ve _dyld* fonksiyonlarıyla load edilmiş image’ları ve offset’leri listeleyen bir C aracı yazıldı
  • Bu yöntem ile GDB adreslerini geri çevirme süreci birlikte kullanılarak dyld cache’teki library’ler debug edilebildi
  • Özellikle ilgi odağı IOMFB kext, backboardd, SpringBoard ve QuartzCore idi
  • Daha sonra kernel patch’iyle dyld cache’i devre dışı bırakmanın yolu da bulundu; host üzerinde dyld cache’in virtual address’ini doğrudan bulmak için Gimli projesinin Rust object library’si kullanıldı
  • User space debugging için guest tarafında GDB server gerekiyordu; örnek olarak Procursus debugserver paketi kullanıldı

Sistem log’ları ve lockdownd bypass

  • GDB ile backboardd normal şekilde başlıyor gibi görünüyordu, ancak gerçek durumu anlamak için sistem log’ları gerekiyordu
  • Gerçek iPhone’da bilgisayarla USB pairing sonrasında idevicesyslog ile sistem log’ları görülebilir
  • Pairing süreci anahtar çifti üretimini içerir; private key iPhone’da saklanır ve lockdownd bilgisayarın kimliğini doğrular
  • Emülasyon ortamında USB etkileşimi mümkündü, ancak lockdownd düzgün çalışmıyordu
  • Ghidra analizi sonucunda lockdowndun private key saklamak için keybag kullanmaya çalıştığı ve bunun mevcut olmayan SEP gerektirdiği anlaşıldı
  • Mevcut bazı fonksiyonların yerine geçen shellcode enjekte edilerek önceden oluşturulmuş public/private key çifti dosya sisteminden okunacak ve lockdownd her keybagden almaya çalıştığında yüklenecek şekilde düzenlendi
  • Ek debugging ve patch’lerle kullanıcının bilgisayara güvendiği ve iPhone’un kilidinin açık olduğu simüle edildi
  • Sonunda companion QEMU’dan emüle edilen iPhone ile pairing yapılabildi
  • Log’larda QuartzCoreun normal başlatıldığı, display size’ı algıladığı ve yazılımsal rendering fallback’ini kullandığı doğrulandı
  • Her şey normal görünmesine rağmen ekran hâlâ görüntülenmiyordu
  • Pixel format ile ilgili tek bir hata RGBA’yı zorlayarak bypass edildi, ancak daha sonra kaldırıldı

PAC sorunu ve QEMU 8’e port etme

  • backboardddaki pixel format hatası düzeltilmeye çalışılırken iOS güvenlik özellikleri nedeniyle ek bir sorun ortaya çıktı
  • Load zamanındaki ve runtime’daki signature kontrolleri kernel patch’iyle çözülmüştü, ancak değiştirilmiş backboardd çalışırken Pointer Authentication hatası oluştu
  • Pointer Authentication, ARMv8.3’e eklenen bir özellik; daha önce kullanılan t8015’te değil, emüle edilen t8030 board’da yeni karşılaşılan bir sorundu
  • İlk başta tüm PAC komutlarını NOP’a veya PAC’siz eşdeğer komutlara dönüştürme yöntemi düşünüldü
  • Sonra ARM64 PAC binary’lerinin iki şekilde build edilebildiği doğrulandı
    • Yalnızca ARMv8.3+ CPU’larda çalışan özel PAC instruction set kullanımı
    • ARMv8.3+’ta PAC olarak yorumlanan, eski ARM’de ise PAC’siz eşdeğer komut olarak yorumlanan “kullanılmayan” instruction set kullanımı
  • buildroot ve ARM64 Linux sisteminde test edilerek bu davranış doğrulandı; t8030 için binary’lerin backward compatible instruction set olan arm64e kullandığı belirlendi
  • QEMU’da yalnızca PAC enforcing kapatılırsa kodun PAC’siz kod gibi çalışacağı düşünüldü; ancak QEMU 7’de çalışmadı, QEMU 8’de davranış farklıydı
  • Mevcut codebase QEMU 8.2.1’e port edildi
    • Apple’a özel genter, gexit komutları
    • GL exception levels işleme kodu
    • QEMU generic code üzerinde çok sayıda değişiklik olduğu için port zordu
  • Birçok XNU panic, kernel GDB debugging, QEMU’nun kendi debugging’i ve git bisect sonunda iOS yeniden QEMU 8’de boot ettirildi
  • Böylece PAC devre dışı bırakılabildi ve istenen herhangi bir executable code istenen konumda değiştirilebilir hale geldi

Siyah ekranın nedenini izleme

  • Sistem log’larında backboardd normal çalışıyor gibi göründüğü için görüntü gelmemesinin nedeni daha derinlemesine izlendi
  • Raw ARGB frame doğrudan adrese yazılınca gerçek display değişiyor ve birden fazla graphical plane’e çizim yapılabiliyordu
  • Dolayısıyla display implementasyonu sağlam görünüyordu; geriye üç olasılık kalıyordu
    • backboardd hiçbir şey yazmıyor
    • Yanlış adrese yazıyor
    • Yazılan veri geçerli değil
  • QEMU monitor ile non-contiguous physical address’ler alındı; script ile physical DMA memory dump edilip tek bir dosyada birleştirildi
  • ffplay ile ARGB frame gibi yorumlandı, ancak anlamlı bir sonuç alınamadı
  • Sonra iosurface_lock üzerine breakpoint konarak backboardd belleğine map edilmiş surface adresleri alındı ve incelendi
  • Zaman zaman Apple logosuna benzeyen garip şekiller bulundu, ancak frame yazma biçiminde sorun var gibi görünüyordu
  • Aynı işlem gerçek iPhone 10’da yapılınca mevcut ekranın tam raw ARGB frame’i kolayca dump edilebildi
  • iPhone 11, yani t8030 sonrası cihazlarda surface’in GPU’nun işleyebileceği sıkıştırılmış biçimde iletildiği düşünüldü
  • iPhone X’in t8015inde bu gerçekleşmediği için QEMU’nun DTB’sinde chip-id 8030 yerine 8015 olarak iletilecek şekilde değiştirildi
  • Bunun sonucunda boot sonrası ekranda Apple logosu göründü

Progress bar ve aktivasyon patch’i

  • Apple logosu göründükten sonra bile UI daha ileri gitmedi; sistem log’larında birçok daemon ve library’den çok sayıda mesaj çıkıyordu
  • Hangi hatanın gerçek UI sorunuyla ilgili olduğunu tahmin edip tek tek düzeltme yöntemiyle ilerlenildi
  • Kullanıcı aktivasyonu ile ilgili bir sorun tespit edildi; hatanın kaynağı mobileactivationd daemon’u ve SpringBoardFoundation framework’üydü
  • Bunlar patch’lendikten sonra restore aşamasında görülenlere benzer beyaz progress bar gösterildi
  • Progress bar hareket ediyor gibi görünüyordu; ancak saatler sonra bile %90’da kalmış gibi duruyordu

dyld cache ve user space patch döngüsünü iyileştirme

  • Adres randomizasyonunun devre dışı bırakılması sayesinde user space ve dyld cache framework patch’leri mümkün oldu
  • Kernel ile aynı yöntemle her binary/library için metin patch dosyaları oluşturulup dahili araçla uygulandı
  • dyld cache yaklaşık 2GB olduğu için doğrudan patch’lemek veya SSH üzerinden tekrar tekrar kopyalamak pratik değildi
  • Linux ortamında çalışıldığı için NVMe doğrudan değiştirilemiyordu
  • Dahili diff/patch aracı dyld cache’e uyarlanarak framework offset’lerini dyld cache blob içinde bulacak şekilde genişletildi
  • iPhone’da doğrudan uygulanabilecek basit dd komutları ve revert komutları üretme seçeneği eklendi
  • Dosya sistemi read/write modunda yeniden mount edildikten sonra dd komutları uygulanınca dyld cache değişiklikleri hızlıca tekrarlanabildi
  • Değişikliklerin etkili olması için yalnızca iOS reboot gerekiyordu
  • Bu yöntemin çalışması için kernel’in signature check’lerine yönelik bazı ek patch’ler gerekiyordu

PreBoard çalıştırma ve UIKit ekranını gösterme

  • Takılan progress bar çözülmeden önce sistem process’i PreBoard ile deneme yapıldı
  • PreBoardun yalnızca update kesintisi gibi sorunlarda kullanıcıya gösterildiği düşünülüyordu
  • SpringBoard gibi backboardd üzerinden doğrudan çizen bir sistem uygulaması olduğundan command line’dan doğrudan başlatılabiliyordu
  • Çalıştırılınca “swipe to upgrade” isteyen beyaz bir ekran gösterildi
  • Geçmişte fiziksel iPhone’da VNC server kullanma deneyimine dayanarak VNC eklendi; birçok başarısız denemeden sonra ekran swipe ile değil klavye tuşlarıyla unlock edildi
  • Unlock işleminden hemen sonra QEMU, iOS’un illegal instruction kullanması nedeniyle yürütmeyi durdurdu
  • backboardd analizi sonucunda vImage framework’ünün _vHorizontal_Scale_ARGB_8888_Accelerate gibi donanım hızlandırmalı grafik işlemleri için AMX(Apple Matrix Coprocessor) komutları kullandığı anlaşıldı
  • AMX, QEMU’nun emülasyon ARM CPU’sunda uygulanmamış Apple’a özgü bir instruction set’tir
  • vImage framework’ünde yalnızca generic ARM komutları kullanan alternatif yazılımsal sürümler vardı; bunların kullanılması yine patch ile sağlandı
  • Nihai sonuç olarak gerçek UIKit penceresi gösterildi; passcode giriş ekranı ve çalışan bir text box ortaya çıktı
  • VNC ile enjekte edilen klavye event’leri üzerinden text box’a giriş yapılabildi
  • Bu noktada SpringBoardun düzgün gösterilmesi için gereken bileşenler hazırdı; başlaması yalnızca zaman meselesi gibi görünüyordu
  • Sonraki yazı Part 2 ile devam ediyor

1 yorum

 
GN⁺ 2025-04-07
Hacker News yorumları
  • https://github.com/devos50/qemu-ios projesinin iPhone OS 3.x'e kadar destek verecek şekilde gelişip, ilk dönem iPhone uygulamalarını dijital koruma açısından deneyimleyebilmemiz güzel olurdu.
    https://github.com/touchHLE/touchHLE de harika, ancak çok temel uygulamalar dışında uygulama bazında yama gerektiriyor.

    • QEMU ile emüle edilen iPhone 11, iOS 13.x'ten iOS 18.x'e kadar destekleyebilir: https://github.com/ChefKissInc/QEMUAppleSilicon
      iOS 10'da 32 bit uygulamaları çalıştırmak için QEMU'nun iPhone 7'yi de desteklemesi gerekiyor.
    • Şu anda alternatifi olmayan ilk dönem oyunları ya da harika eski uygulamaları yeniden kullanabilmek gerçekten müthiş olurdu.
  • Geçmişte QEMU ile NumWorks N0100[1] ve HP Prime G1[2]'i emüle edip, resmi firmware'in gerçekten çalıştığı seviyeye kadar getirmiştim.
    [1] https://github.com/boricj/qemu/tree/numworks_calculators
    [2] https://github.com/boricj/qemu/tree/s3c2416-boricj

  • Bu projeye eğlenceli bir uygulama olarak, postmarketOS donanım desteği oldukça iyi olan bir telefona minimum yapılandırmalı bir pmOS imajı ve QEMU'nun bu sürümü kurulup, bir Android telefonda iOS boot edilebilir gibi görünüyor.
    QEMU'yu daha da özelleştirerek modem, Bluetooth gibi telefon donanımlarını iOS sanal makinesine aktarmak da mümkün olabilir.

    • Eğlenceli bir fikir ama ilk sorun, postmarketOS üzerinde kamerası da çalışan ve telefon görüşmelerini de düzgün yapabilen bir telefon bulmak.
      iOS/Android emülasyonu olmadan sadece bu bile olsa memnun olurdum.
    • Sırf eğlence içinse sorun değil, ama pratikte aşırı verimsiz olacağı için kullanılabilir bir cihaz olması zor ve gereken iş miktarı da devasa olur.
    • Bir tür paravirtualization gibi mi? Eğlenceli bir proje olabilir.
  • Arşivlenmiş sürüm: https://archive.ph/l1CwO

  • Bu artık Apple donanımı olmadan Linux sisteminde Safari testi veya iOS için derleme gibi şeyler yapabileceğimiz anlamına mı geliyor?

  • https://github.com/ChefKissInc/QEMUAppleSilicon
    QEMU'da emüle edilen bir Apple Silicon cihazı; şu anda yalnızca iPhone 11 destekleniyor.
    Demo videosu: https://nitter.poast.org/eshard/status/1908162866609311962

  • Çalıştırma yönergelerini izledim: https://github.com/TrungNguyen1909/qemu-t8030/wiki/Bringing-...
    Kabul etmek istemeyeceğim kadar çok kez çöktü ama yine de epey havalı.

  • Ağ bağlantısından bahsedilmiyor. Wi‑Fi veya hücresel modem yonga setlerini emüle etmiyor gibi görünüyor.
    Bu emüle edilen cihazın internete nasıl bağlanacağını merak ediyorum. USB üzerinden Ethernet gibi bir yöntem olabilir.

    • iOS USB Ethernet destekliyor.
  • Apple'ın çok platformlu iOS geliştirmeyi kabul etmesi için ne gerekir?

    • Apple bunu asla yapmaz. Şimdiye kadarki davranışları tam tersini, yani cihazlar ve ekosistem üzerinde tam kontrolü, standartlar konusunda diğer şirketlerle iş birliği yapmamayı ve sıkı App Store denetimini gösteriyor.
      Apple açısından bakınca böyle bir geliştirme modeline izin vererek kazanacağı bir şey yok.
    • Apple yazılımla donanım satıyor. Android için iMessage'ın çıkmamış olmasının nedeni de bu.
      Böyle bir şeyin gerçekleşmesi için Apple'ın dünyaya bakış biçiminin değişmesi gerekir; bu da Microsoft'un WSL ve Linux için .NET ile Linux'u bir ölçüde benimsemesi kadar büyük bir değişim olurdu.
    • Kurum kültürünün tamamen değişmesi gerekir.
    • Apple bir donanım şirketi. Satmadığı donanımlarda bir şeyleri desteklemek istemesi için ne sebep olabilir?
    • Internet Explorer dönemindeki gibi parçalanma tehdidi alacak kadar ileri gitmesi gerekir gibi.
  • Bunu yeniden üretmeyi sağlayan bir depo var mı?