4 पॉइंट द्वारा GN⁺ 2025-04-07 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • eShard का लक्ष्य मौजूदा open source iOS emulation कार्य के आधार पर iOS 14 को QEMU में boot करना और UI व कुछ apps चलाने में सक्षम emulator बनाना था
  • QEMU के अंदर सीधे kernel patches डालने के बजाय PongoOS और checkra1n KPF का उपयोग करके XNU patches को अलग किया गया, और Mach-O diff आधारित tool से patches की समीक्षा संभव बनाई गई
  • Apple Silicon GPU emulation का दायरा बहुत बड़ा था, इसलिए पहले software rendering चुना गया, और jailbroken iPhone के QuartzCore patch से पुष्टि हुई कि UIKit UI धीमा सही, पर draw हो सकता है
  • screen के काली बनी रहने की समस्या हल करने के लिए address randomization disable करना, GDB debugging, lockdownd pairing bypass, PAC disable करना, QEMU 8.2.1 porting, और dyld cache patch automation जारी रखे गए
  • अंततः QEMU screen पर UIKit passcode input UI दिखाया गया और VNC keyboard input से textbox को manipulate किया गया; SpringBoard display तक के लिए जरूरी आधार तैयार हो गया

iOS emulation की शुरुआत

  • मौजूदा open source solutions की समीक्षा में alephsecurity/xnu-qemu-arm64 को चलाने का अनुभव था, लेकिन project read-only स्थिति में था
  • इसके बाद TrungNguyen1909/qemu-t8030 को शुरुआती आधार के रूप में इस्तेमाल किया गया
    • दूसरे “companion” QEMU के जरिए USB connection से iOS restore संभव
    • iOS 14 चलाने का support
    • अधिक नए QEMU version पर आधारित
    • emulator चलाने का तरीका बताने वाला wiki उपलब्ध
  • System/Library/xpc/launchd.plist को modify करके जल्दी से shell और SSH access हासिल किया गया
  • long-term goal UI के साथ और कम से कम कुछ apps चला सकने वाला functional iOS emulation है

PongoOS से kernel patches अलग करना

  • t8030 project ने XNU kernel patch code को QEMU में ही रखा था, लेकिन आगे patches बढ़ने की संभावना थी, इसलिए ज्यादा साफ structure की जरूरत थी
  • असली jailbroken iPhone के अनुभव के आधार पर PongoOS का इस्तेमाल करके checkra1n patches लागू करने का तरीका जांचा गया
  • सामान्य jailbreak flow में checkmate से pwn होने के बाद PongoOS को SRAM में inject किया जाता है और checkra1n-kpf module USB से भेजा जाता है
    • इस काम में शुरुआती USB handling से बचने के लिए emulated iPhone की SRAM बढ़ाई गई और PongoOS व checkra1n KPF module का उपयोग किया गया
  • PongoOS execution की शुरुआत में bootrom या iBoot द्वारा की जाने वाली initialization code न होने से समस्याएं आईं
    • double/float instructions से पहले FPU setup जरूरी था
    • ARM documentation और मौजूदा QEMU संबंधित code देखकर इसे हल किया गया
  • A13 के बाद वाले device features Pongo द्वारा supported नहीं थे, जिससे कुछ patches की pattern matching टूट गई
    • Pointer Authentication(PAC) instructions autda, xpacd जोड़े गए
    • Apple अलग slide का उपयोग करता है
    • task_for_pid(tfp0) patch में iPhone X और iPhone 11 के addresses और binary patterns का अंतर दिखा

Declarative kernel patch files

  • Pongo ने कई iOS versions के लिए मौजूदा checkra1n patches का उपयोग संभव बनाया, लेकिन dynamic application तरीका पढ़ने, modify करने और share करने में कठिन था
  • इन्हें असली code patches की तरह handle करने के लिए internal tool से declarative patches files बनाई गईं
    • दो Mach-O का diff करके assembly differences आधारित text patch file बनाई गई
    • generated patch file को binary पर apply करने के लिए अलग program लिखा गया
  • Pongo से boot करने के बाद QEMU monitor का उपयोग करके Pongo द्वारा patched memory sections dump किए गए
  • इसके बाद patched kernel को फिर से assemble किया गया और सभी modifications वाला बड़ा patch file बनाया गया
  • बड़े patch को भागों में बांटकर और comments जोड़कर kernel के किन हिस्सों को patch किया जा रहा है, इसकी review और control संभव हुआ

GPU के बिना screen draw करने की strategy

  • नए iPhone की graphics rendering आखिरकार Apple के Metal API से गुजरती है और real GPU की जरूरत होती है
  • Apple Silicon GPU को emulate करना बहुत complex माना गया, इसलिए दो विकल्पों पर विचार किया गया
    • पुराने iOS में जैसे संभव था, gpu=0 bootarg के जरिए software rendering
    • Metal calls को real iPhone या macOS वाले Mac तक forward करके rendering कराना
  • iOS 14 में XNU kernel का gpu=0 bootarg option हट चुका था
  • QuartzCore framework को Ghidra से analyze करने पर पता चला कि software rendering, Metal renderer न होने पर fallback के रूप में call होने वाली structure थी
  • real jailbroken iPhone पर QuartzCore patch करके software rendering के use की पुष्टि हुई
    • UI काफी धीमा था
    • कुछ areas में artifacts आए, और संभव है कि उन हिस्सों ने direct Metal rendering मांगी हो
  • इस experiment से माना गया कि Metal या OpenGL को direct use न करने वाली सीमा में, यानी अधिकांश UIKit apps में QEMU पर भी software rendering संभव है

Metal call proxy experiment

  • Metal calls को proxy करने का alternative भी दो physical iPhones पर test किया गया
    • LLVM से सभी iOS headers parse करना
    • server के Objective-C object pointers को client में stub pointers के रूप में represent करना
    • structures और pointer exchange code auto-generate करना
    • सभी functions और methods hook करना
    • सभी calls server को forward करना और execution result लौटाना
  • Metal initialization के basic call round trips कुछ हद तक सफल रहे
  • लेकिन Objective-C language और Metal API complex व बहुत feature-rich हैं, इसलिए real operation तक पहुंचने का workload बहुत बड़ा था
  • इस approach को बाद के लिए टालकर, limitations के बावजूद software rendering से दूसरे issues पहले हल करने का फैसला हुआ
  • iOS frameworks में public headers में न मौजूद private API भी exposed थे, और उन्हें parse करके headers बनाने का तरीका था, लेकिन अधिकतर direct use करना मुश्किल था और complexity बढ़ती थी

IOSurface और framebuffer debugging

  • software rendering try करने के बाद भी कम से कम framebuffer device की जरूरत थी, लेकिन original t8030 QEMU में यह implemented नहीं था
  • IOMFB support work वाले QEMUAppleSilicon fork को ढूंढकर display debugging में इस्तेमाल किया गया
  • इस version से iOS restore करते समय Apple logo और progress bar दिखे, लेकिन normal boot में screen पूरी तरह black रही
  • Ghidra से IOMFB kext देखने और QEMU framebuffer implementation की जांच करने पर दो modes दिखे
    • fixed hardware address वाला raw framebuffer
    • registers से कई planes set करके DMA से surface data लिखने वाला ज्यादा complex API
  • raw framebuffer से arbitrary ARGB surface display हो सकता था, लेकिन boot के दौरान system उस framebuffer में write नहीं कर रहा था
  • दूसरे display mode में kernel द्वारा registers से graphical plane set करने का trace दिखा, लेकिन उसके बाद screen output नहीं था

Address randomization हटाना और GDB debugging

  • सिर्फ SSH access से running system observe करने की सीमा थी, इसलिए kernel और user space को GDB से debug करना जरूरी हुआ
  • kernel address randomization t8030 board initialization में set था, इसलिए इसे पूरी तरह बंद किया जा सकता था
  • userland में executable randomization और dyld cache के अंदर dynamic library randomization था
    • executable को kernel के _load_machfile function को patch करके disable किया गया
    • dyld cache libraries boot के समय एक बार address-randomized होती हैं और फिर सभी executables में उसी address पर load होती हैं
  • /System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64e के dyld cache में सभी framework libraries बड़े binary blob के रूप में मौजूद हैं
  • C tool बनाकर सभी framework libraries को dlopen किया गया और _dyld* functions से loaded images व offsets list किए गए
  • इस तरीके और GDB addresses को reverse करने की process को साथ इस्तेमाल करके dyld cache libraries को debug किया जा सका
  • खास दिलचस्पी IOMFB kext, backboardd, SpringBoard, QuartzCore में थी
  • बाद में kernel patch से dyld cache disable करने का तरीका भी मिला, और host पर dyld cache के virtual addresses सीधे खोजने के लिए Gimli project की Rust object library इस्तेमाल की गई
  • user space debugging के लिए guest का GDB server जरूरी था, उदाहरण के लिए Procursus का debugserver package इस्तेमाल किया गया

System logs और lockdownd bypass

  • GDB से backboardd normal तरीके से start होता दिख रहा था, लेकिन असली स्थिति समझने के लिए system logs की जरूरत थी
  • real iPhone पर computer के साथ USB pairing के बाद idevicesyslog से system logs देखे जा सकते हैं
  • pairing process में key pair generation शामिल है, private key iPhone में save होती है और lockdownd computer की identity verify करता है
  • emulation environment में USB interaction संभव था, लेकिन lockdownd ठीक से काम नहीं कर रहा था
  • Ghidra analysis से पता चला कि lockdownd private key storage के लिए keybag इस्तेमाल करना चाहता था, जिसके लिए अनुपस्थित SEP चाहिए था
  • मौजूदा functions के कुछ हिस्सों को replace करने वाला shellcode inject करके pre-generated public/private key pair को file system से पढ़ने और lockdownd के keybag से fetch करने की कोशिश करने पर हर बार load कराने की व्यवस्था की गई
  • अतिरिक्त debugging और patching से simulate किया गया कि user ने computer पर trust किया है और iPhone unlocked है
  • आखिरकार companion QEMU से emulated iPhone के साथ pair किया जा सका
  • logs में पुष्टि हुई कि QuartzCore normal initialize हो रहा है, display size detect कर रहा है और software rendering fallback इस्तेमाल कर रहा है
  • सब कुछ normal जैसा दिखा, लेकिन screen अब भी display नहीं हो रही थी
  • pixel format से जुड़ी एक single error को RGBA force करके bypass किया गया, लेकिन बाद में उसे हटा दिया गया

PAC issue और QEMU 8 porting

  • backboardd की pixel format error ठीक करते समय iOS security feature की वजह से additional problem सामने आई
  • load-time और runtime signature checks kernel patch से हल हुए, लेकिन modified backboardd चलाते समय Pointer Authentication failure हुआ
  • Pointer Authentication ARMv8.3 में जोड़ा गया feature है, और पहले इस्तेमाल किए गए t8015 के बजाय emulated t8030 board पर यह नई समस्या थी
  • शुरुआत में सभी PAC instructions को NOP या PAC-less equivalent instructions में बदलने का तरीका सोचा गया
  • बाद में पता चला कि ARM64 PAC binaries दो तरीकों से build हो सकती हैं
    • सिर्फ ARMv8.3+ CPU पर चलने वाली dedicated PAC instruction set का उपयोग
    • ऐसी “unused” instruction set का उपयोग जो ARMv8.3+ में PAC के रूप में और पुराने ARM में PAC-less equivalent instructions के रूप में interpret होती है
  • buildroot और ARM64 Linux system पर test करके इस behavior को verify किया गया, और पुष्टि हुई कि t8030 binaries backward compatible instruction set arm64e इस्तेमाल करती हैं
  • लगा कि QEMU में सिर्फ PAC enforcing बंद करने से code PAC-less code की तरह चलेगा, लेकिन QEMU 7 में यह काम नहीं किया और QEMU 8 का behavior अलग था
  • current codebase को QEMU 8.2.1 पर port किया गया
    • Apple-specific instructions genter, gexit
    • GL exception levels handling code
    • QEMU generic code में बहुत modifications होने से porting कठिन थी
  • कई XNU panics, kernel GDB debugging, QEMU की खुद की debugging और git bisect के बाद iOS को QEMU 8 में फिर से boot कराया गया
  • इससे PAC disable करके किसी भी executable code को इच्छित location पर modify करना संभव हुआ

Black screen के कारण की tracking

  • system logs के अनुसार backboardd normal काम करता दिखा, इसलिए display न होने का कारण और गहराई से trace किया गया
  • raw ARGB frame को address पर directly write करने से actual display बदलता था, और कई graphical planes पर draw किया जा सकता था
  • इसलिए display implementation खुद normal दिखी और तीन संभावनाएं बचीं
    • backboardd कुछ भी नहीं लिख रहा
    • गलत address पर लिख रहा है
    • लिखा गया data valid नहीं है
  • QEMU monitor से non-contiguous physical addresses लिए गए, और script से physical DMA memory dump करके एक file में जोड़ी गई
  • ffplay से उसे ARGB frame की तरह interpret किया गया, लेकिन meaningful result नहीं मिला
  • अगला कदम iosurface_lock पर breakpoint लगाकर backboardd memory में mapped surface address लेना और जांचना था
  • कभी-कभी Apple logo जैसी अजीब shape मिली, लेकिन frame writing method में issue लगता था
  • यही काम real iPhone 10 पर करने पर current screen का पूरा raw ARGB frame आसानी से dump हो गया
  • iPhone 11, यानी t8030 के बाद, surface GPU द्वारा process किए जा सकने वाले compressed format में deliver होती दिखी
  • iPhone X के t8015 में ऐसा नहीं होता था, इसलिए QEMU के DTB में chip-id को 8030 के बजाय 8015 pass करने के लिए modify किया गया
  • नतीजतन boot के बाद screen पर Apple logo display हुआ

Progress bar और authentication patches

  • Apple logo display होने के बाद भी UI आगे नहीं बढ़ा, और system logs में कई daemons और libraries के बहुत सारे messages output हुए
  • कौन-सी error actual UI issue से जुड़ी है, इसका अनुमान लगाकर एक-एक करके ठीक किया गया
  • user authentication से जुड़ी problem मिली, और error के sources mobileactivationd daemon और SpringBoardFoundation framework थे
  • इन्हें patch करने के बाद restore stage में दिखने जैसी white progress bar display हुई
  • progress bar चलती हुई लग रही थी, लेकिन कई घंटों बाद भी 90% पर रुकी हुई दिखी

dyld cache और user space patch iteration सुधारना

  • address randomization disable होने से user space और dyld cache framework patches संभव हुए
  • kernel की तरह हर binary/library के लिए text patch files बनाकर internal tool से apply की गईं
  • dyld cache लगभग 2GB का था, इसलिए direct patch करना या SSH से बार-बार copy करना practical नहीं था
  • Linux environment में काम करने के कारण NVMe को सीधे modify भी नहीं किया जा सकता था
  • internal diff/patch tool को dyld cache के लिए extend किया गया ताकि framework offsets को dyld cache blob के अंदर खोज सके
  • iPhone पर सीधे apply किए जा सकने वाले simple dd commands और revert commands generate करने का option जोड़ा गया
  • file system को read/write mode में remount करने के बाद dd commands apply करके dyld cache modifications को तेजी से iterate किया जा सका
  • changes apply होने के लिए सिर्फ iOS reboot जरूरी था
  • इस तरीके के काम करने के लिए kernel signature check पर कुछ additional patches भी जरूरी थे

PreBoard execution और UIKit screen display

  • अटकी हुई progress bar हल करने से पहले system process PreBoard पर experiment किया गया
  • PreBoard केवल update interruption जैसी समस्याओं के समय user को display होता लगता था
  • SpringBoard की तरह यह backboardd के जरिए direct draw करने वाला system application था, इसलिए command line से सीधे start किया जा सकता था
  • run करने पर “swipe to upgrade” मांगने वाली white screen display हुई
  • पहले physical iPhone पर VNC server use करने के अनुभव के आधार पर VNC जोड़ा गया, और कई failures के बाद swipe नहीं बल्कि keyboard keys से screen unlock की गई
  • unlock के तुरंत बाद QEMU ने iOS के illegal instruction use करने पर execution रोक दिया
  • backboardd analysis से पता चला कि vImage framework _vHorizontal_Scale_ARGB_8888_Accelerate जैसे hardware-accelerated graphics operations के लिए AMX(Apple Matrix Coprocessor) instructions इस्तेमाल करता है
  • AMX, QEMU के emulated ARM CPU में implemented न होने वाली Apple की proprietary instruction set है
  • vImage framework में केवल generic ARM instructions इस्तेमाल करने वाला alternative software version था, इसलिए फिर patch करके उसे use कराया गया
  • final result के रूप में असली UIKit window display हुई और passcode input screen व working textbox दिखाई दिया
  • VNC से injected keyboard events के जरिए textbox में input किया जा सका
  • इस point पर SpringBoard को सही तरह display करने के लिए required components तैयार हो गए, और start होना बस समय की बात लगता है
  • अगला लेख Part 2 में जारी है

1 टिप्पणियां

 
GN⁺ 2025-04-07
Hacker News की राय
  • अच्छा होगा अगर https://github.com/devos50/qemu-ios इतना विकसित हो जाए कि iPhone OS 3.x तक सपोर्ट करे, ताकि शुरुआती iPhone ऐप्स को डिजिटल संरक्षण के तौर पर अनुभव किया जा सके
    https://github.com/touchHLE/touchHLE भी बेहतरीन है, लेकिन बहुत बेसिक ऐप्स को छोड़कर ऐप-विशेष पैच की जरूरत पड़ती है

    • QEMU से emulate किया गया iPhone 11 iOS 13.x से iOS 18.x तक सपोर्ट कर सकता है: https://github.com/ChefKissInc/QEMUAppleSilicon
      iOS 10 पर 32-bit ऐप्स चलाने के लिए QEMU को iPhone 7 भी सपोर्ट करना होगा
    • अगर शुरुआती गेम्स या शानदार पुराने ऐप्स फिर से इस्तेमाल किए जा सकें, जिनका अभी कोई विकल्प नहीं है, तो यह वाकई कमाल होगा
  • पहले QEMU से NumWorks N0100[1] और HP Prime G1[2] को emulate करके आधिकारिक firmware को सच में चलने लायक स्तर तक बनाया था
    [1] https://github.com/boricj/qemu/tree/numworks_calculators
    [2] https://github.com/boricj/qemu/tree/s3c2416-boricj

  • इस प्रोजेक्ट का मजेदार उपयोग यह हो सकता है कि postmarketOS hardware support वाले किसी अच्छे फोन पर न्यूनतम pmOS image और QEMU का यह version install करके Android phone पर iOS boot किया जाए
    QEMU को और customize करके modem, Bluetooth जैसे फोन hardware को iOS virtual machine तक pass through करना भी शायद संभव हो

    • आइडिया मजेदार है, लेकिन पहली समस्या ऐसा फोन ढूंढना है जिसमें postmarketOS पर camera भी चले और phone calls भी ठीक से हों
      iOS/Android emulation के बिना सिर्फ इतना हो जाए तो भी संतोष होगा
    • सिर्फ मजे के लिए हो तो ठीक है, लेकिन असल में यह बेहद inefficient होगा, इसलिए usable device बनना मुश्किल है और काम भी बहुत भारी होगा
    • क्या यह किसी तरह की paravirtualization जैसा है? मजेदार project हो सकता है
  • Archived version: https://archive.ph/l1CwO

  • क्या इसका मतलब है कि अब Apple hardware के बिना भी Linux system पर Safari testing या iOS के लिए compiling जैसी चीजें की जा सकती हैं?

  • https://github.com/ChefKissInc/QEMUAppleSilicon
    यह QEMU में emulate होने वाला Apple Silicon device है, और फिलहाल सिर्फ iPhone 11 को सपोर्ट करता है
    Demo video: https://nitter.poast.org/eshard/status/1908162866609311962

  • Run instructions follow करके देखा: https://github.com/TrungNguyen1909/qemu-t8030/wiki/Bringing-...
    जितनी बार crash हुआ, मानने में शर्म आएगी, लेकिन यह काफी cool है

  • Network connectivity का कोई जिक्र नहीं है। लगता है Wi-Fi या cellular modem chipset को emulate नहीं किया गया है
    उत्सुकता है कि इस emulated device को internet से कैसे जोड़ा जाएगा। शायद USB के जरिए Ethernet जैसा कोई तरीका हो सकता है

    • iOS USB Ethernet सपोर्ट करता है
  • Apple को multiplatform iOS development स्वीकार करने के लिए क्या चाहिए होगा?

    • Apple ऐसा कभी नहीं करेगा। अब तक उसका व्यवहार बिल्कुल उल्टा रहा है: devices और ecosystem पर पूरा control, standards पर दूसरी कंपनियों के साथ सहयोग न करना, और कड़ा App Store control
      Apple के नजरिए से ऐसे development model को अनुमति देकर उसे कुछ हासिल नहीं होगा
    • Apple software के जरिए hardware बेचता है। इसलिए Android के लिए iMessage नहीं आया
      ऐसा होने के लिए Apple का दुनिया को देखने का तरीका ही बदलना होगा, और यह बदलाव उतना ही बड़ा होगा जितना Microsoft ने WSL और Linux के लिए .NET के साथ Linux को कुछ हद तक अपनाया था
    • Corporate culture पूरी तरह बदलनी पड़ेगी
    • Apple एक hardware company है। जो hardware वह बेचता ही नहीं, उस पर कुछ support करने की वजह उसे क्यों चाहिए होगी?
    • शायद Internet Explorer वाले दौर की तरह breakup की धमकी मिलने जितना दबाव होना पड़ेगा
  • क्या इसे reproduce करने के लिए कोई repository है?