2 điểm bởi GN⁺ 2024-10-08 | 1 bình luận | Chia sẻ qua WhatsApp
  • Đây là một thử nghiệm dùng Virtualization.framework trên Mac Apple silicon và môi trường vma2 để khởi động bản dựng iOS 15.0.2 cho iPhone XR tới PreBoard.app
  • Điểm cốt lõi của cách tiếp cận là tái sử dụng chuỗi khởi động của macOS 12.0.1 và chỉ thay thế image hệ thống iOS, mtree, root_hash, trustcache, nhằm giảm gánh nặng sửa đổi chuỗi khởi động giai đoạn đầu
  • Khi hạ VM xuống trạng thái CPFM 01 bằng lệnh gọi không công khai _setProductionModeEnabled(false), TSS sẽ ký firmware tùy ý cho thiết bị vma2 công khai, làm giảm nhu cầu dùng phương pháp vma2pwn trước đây
  • Để khởi động thực tế cần các bản vá kernel và hệ thống đụng tới kiểm tra nền tảng của XNU, system keybag, kiểm tra kích thước IOMFB, ramdisk, launchd, mount, DYLD shared cache, lockdownd, mobileactivationd
  • Vấn đề lớn nhất còn chưa giải quyết là khả năng tương thích system keybag; cũng chưa xác nhận liệu nhập liệu cảm ứng có thể thực hiện qua API không công khai của Virtualization.framework hay không

Mục tiêu và điểm xuất phát của thử nghiệm

  • Sau quá trình chuyển sang Apple silicon và Mac Catalyst, iOS và macOS đã gần nhau hơn; khi ảo hóa macOS trở nên khả thi, câu hỏi cốt lõi là liệu iOS cũng có thể được ảo hóa bằng cách sửa đổi chuỗi khởi động cùng họ hay không
  • Công việc trước đó, vma2pwn, là dự án tạo chuỗi khởi động macOS vma2 có thể chỉnh sửa cho VM khách macOS, và trở thành nền tảng cho thử nghiệm lần này
  • Một ví dụ công khai đã hoàn chỉnh về ảo hóa/mô phỏng iOS là sản phẩm virtual iPhone cloud của Corellium
  • qemu-t8030, các công việc dựa trên QEMU và bài viết của Zhuowei Zhang cũng được tham khảo; đặc biệt, mối quan hệ giữa IOSurfaceRoot của macOS và IOCoreSurfaceRoot của iOS đã giúp ích cho việc tìm kiếm các bản vá kernel về sau
  • Bài viết của Zhuowei Zhang cho rằng ứng dụng macOS GUI không thể chạy trên iOS, nhưng ứng dụng iOS đồ họa có thể chạy trên macOS; tính chất này cũng áp dụng cho phần lớn hệ thống đồ họa iOS

Các tính năng không công khai của Virtualization.framework

  • Virtualization.framework của Apple có hàm private chưa được tài liệu hóa _setProductionModeEnabled(false)
  • Lệnh gọi này cùng chức năng tương ứng trong cấu hình VM hạ VM xuống Chip Fuse Mode CPFM 01, cấu hình thiết bị ảo ở trạng thái vừa “secure” vừa “non-production”
  • Trên thiết bị vật lý, TSS từ chối ký SHSH blob cần thiết cho các thiết bị non-production/non-secure như CPFM 00 hoặc 01
  • Với thiết bị vma2 công khai, TSS ký firmware tùy ý được cung cấp, nên nhu cầu dùng phương pháp vma2pwn để tạo chuỗi firmware đã sửa đổi giảm đi đáng kể

Cách cấu hình VM iOS

  • Cách tiếp cận thành công nhất là dùng nguyên chuỗi khởi động macOS 12.0.1, rồi thay image OS hệ thống bằng image và các tệp liên quan của bản dựng iOS 15.0.2 cho iPhone XR
    • Các mục được thay thế là image hệ thống, mtree, root_hash, trustcache
    • Cách này tránh được phần lớn nhu cầu sửa đổi chuỗi khởi động và ramdisk khôi phục ở giai đoạn trước khi iOS khởi tạo
  • Bản dựng iPhone XR được chọn vì hỗ trợ arm64e và khả năng có độ phân giải thấp
  • Các cấu hình thiết bị arm64e khác cũng có thể thành công, nhưng kernel vma2 được hardcode để trả về "iPad8,6" cho một số khóa sysctl
  • Bản dựng arm64 gặp thêm vấn đề và không tương thích nhị phân, nên được đánh giá là ít đáng thử
  • Để chạy VM, thử nghiệm dùng super-tart, một fork của tart, ứng dụng bên thứ ba để quản lý VM Apple silicon
    • super-tart cho phép dùng các tính năng không công khai cần thiết của Virtualization.framework
    • Một số thay đổi, như thay đổi thiết lập _setProductionModeEnabled(false), hiện chưa được push đầy đủ
    • Công cụ Virtualization.framework dùng private API cần tắt SIP, và có thể cũng cần tắt AMFI
  • Công cụ khôi phục được dùng là một fork của idevicerestore

Bản vá kernel

  • Có thể cần các bản vá kiểm tra chữ ký đã dùng trong vma2pwn, nhưng với cách CPFM 01 thì chưa chắc có bắt buộc hay không
  • Các bản vá liên quan đến chữ ký trong kernel vma2 có dạng làm cho các hàm sau trả về 0
    • _apfs_extract_root_hash_arm
    • _authenticate_root_hash
    • __img4_firmware_property_callback
    • _is_root_hash_authentication_required
    • _img4_firmware_evaluate
  • Cần vá lookup_in_static_trust_cache để trả về 1
  • Vì binary iOS không phải binary nền tảng simulator, ban đầu chúng bị kết thúc với lỗi EXEC, [0xe] Binary with wrong platform
    • Vấn đề được giải quyết bằng cách vá để bỏ qua dòng kiểm tra PLATFORM_IOS của XNU
    • Trên kernel vma2, việc này được áp dụng bằng cách đổi B.NE thành B
  • Do không tương thích system keybag, PreBoard.app hiển thị “Swipe up to upgrade.” thay vì Setup.app
    • Nếu áp dụng hai bản vá cho ipc_make_system_keybag để ép hàm không trả về lỗi, có thể đi tới PreBoard.app
    • Giới hạn này vẫn chưa được giải quyết hoàn toàn
  • Sự không khớp kích thước struct IOMFB giữa framework hệ thống iOS và kernel macOS gây kernel panic kèm chuỗi CLCDTransaction size mismatch. Returning error 0x%X.
    • Nếu loại bỏ kiểm tra kích thước trong IOMobileFramebufferUserClient::swap_submit, panic sẽ dừng

Chuẩn bị vá tệp hệ thống

  • Ramdisk khôi phục và các tệp hệ thống iOS đều được ký, nên nếu không ký lại sau khi vá, chúng sẽ bị kết thúc khi chạy
  • Trong môi trường chỉnh sửa, khuyến nghị dùng ldid của Procursus
    • Ví dụ cài đặt: brew install ldid-procursus
    • Ví dụ ký lại: ldid_macosx_arm64 -S -M <binary>
    • -S pseudo-sign binary, còn -M giữ nguyên entitlements hiện có
  • Nhiều binary kiểm tra identity, nên trước khi ký lại cần đổi tên thành identity rồi đổi lại tên ban đầu
    • keybagd xác nhận Identifier=com.apple.keybagd bằng codesign -d -v keybagd
    • mv keybagd com.apple.keybagd
    • ldid_macosx_arm64 -S -M com.apple.keybagd
    • mv com.apple.keybagd keybagd
  • Các hàm không tự động được gắn symbol có thể tìm bằng cách tìm XRef của chuỗi, rồi lần theo hàm gọi thông qua tham chiếu tới lời gọi logging
  • Có thể port Bash và LaunchDaemon để có shell tương tác trên serial terminal
    • Cách được dùng là sao chép các tệp liên quan từ payload jailbreak iOS tương thích phiên bản như Procursus

Sửa DMG và ramdisk

  • Để vá hệ thống hoặc ramdisk khôi phục, cần sửa trực tiếp volume DMG
  • Trong ví dụ iOS 15.0.2, iOS System volume trong IPSW được chuyển sang dạng có thể đọc/ghi
    • hdiutil convert -format UDRW -o 018-66258-074-rw.dmg 018-66258-074.dmg
    • Sau khi mount: sudo mount -uw /Volumes/Sky19A404.N104N841OS
    • Sau khi sửa: hdiutil convert -format ULFO -o 018-66258-074.dmg 018-66258-074-rw.dmg
    • Sau đó: asr imagescan --source 018-66258-074.dmg
  • Trước khi khởi động iOS, cần sửa /usr/local/bin/restored_external trong ramdisk khôi phục
    • Phiên bản iOS của restored_external cố tạo system keybag bằng MKBKeyBagCreateSystem, nhưng không tương thích với kernel macOS
    • Bỏ qua bằng cách loại bỏ kiểm tra lỗi
    • Vá điều kiện gọi ramrod_set_NVRAM_variable để đặt allow-root-hash-mismatch thành true, tức 1, và bỏ qua xác thực root hash
  • Cũng cần sửa /usr/sbin/asr trong ramdisk khôi phục
    • Có thể dùng asr64_patcher của iSuns9
    • Tìm hàm in chuỗi "Image failed signature verification.", rồi trong hàm tham chiếu tới nó, đổi lệnh gọi ARMv8-A BL thành nhảy B tới đường dẫn "Image passed signature verification"
    • Trong binary asr của iOS 15.0.2, áp dụng b #0x7c tại file offset 0x27A18

Sửa volume hệ thống iOS

  • Để bản thân iOS khớp với kernel macOS, cần chuyển phần lớn các tệp sẽ được cài vào filesystem root từ system volume sang /System/Library/Templates/Data
  • Khi hệ thống khởi động, các tệp này sẽ tồn tại ở /
  • Các thư mục rỗng ở root thông thường có thể vẫn cần tồn tại trong system volume ngay cả khi thực sự rỗng
    • Ví dụ là /Applications
    • Phần này chưa được kiểm thử đầy đủ

Vá launchd và keybagd

  • Ở giai đoạn đầu khởi động iOS, /sbin/launchd được chạy; để bắt đầu quá trình khởi động ban đầu mà không lỗi, cần vá nó
  • Bản vá đầu tiên được áp dụng cho plist cấu hình nhúng trong binary
    • Tìm chuỗi <key>SIGTERMTimeout</key> và nhìn lùi khoảng 172 byte để thấy cấu hình tương ứng
    • Thêm <key>PerformAfterUserspaceReboot</key><true/> vào các mục mount-phase-2, fips, tzinit, finish-demo-restore, fud, xpcroleaccountd, prng_seedctl, MSUEarlyBootTask
    • Đổi RequireSuccess trong mục data-protection thành <false/>
  • Thay đổi data-protection là cần thiết vì /usr/libexec/init_data_protection thất bại khi chạy trong VM
    • Tệp đó là symbolic link tới /usr/libexec/seputil
  • Thay đổi plist nhúng có thể vượt quá không gian chuỗi hiện có, nên có thể dùng XML minimizer để nén XML rồi dán vào, sau đó ghi đè vùng còn lại bằng ký tự khoảng trắng thân thiện với XML
  • launchd cũng khởi tạo /usr/libexec/keybagd, nhưng binary này thất bại do khác biệt kernel nêu trên
    • Một cách bỏ qua là biên dịch một executable chỉ thoát với exit code 0 để thay thế keybagd
    • Dự án fixkeybag cũng đã được xem xét, nhưng mã tạo system keybag của app đó cũng gọi MKBKeyBagCreateSystem, nên vẫn thất bại ngay cả trong trạng thái iOS đã khởi động
  • launchd cần thêm bản vá để NOP nhánh điều kiện TBZ gây chuỗi panic Userspace reboot changed system version: previous %s != current %s

Sửa mount, DYLD shared cache và tầng đồ họa

  • Vì quá trình khôi phục được xử lý bằng chuỗi khởi động macOS và ramdisk macOS, /sbin/mount của iOS không xử lý đúng các APFS volume được tạo
  • Giải pháp là lấy binary mount từ system volume macOS, sửa metadata Mach-O để có thể chạy trên iOS, rồi thay thế
    • Có thể làm thủ công, hoặc dùng vtool có sẵn trong macOS
  • Bản sửa khó hơn là vá DYLD shared cache
    • IOSurfaceRoot của macOS và IOCoreSurfaceRoot của iOS về cơ bản là cùng một driver, nhưng không tương thích do khác tên
    • Trong DYLD shared cache của iOS có chuỗi dài hơn "IOCoreSurfaceRoot", nên đổi chuỗi này thành "IOSurfaceRoot" và lấp các byte còn lại bằng 0x00
  • Công cụ ipsw của blacktop được dùng để phân tích và trích xuất DYLD shared cache
    • Tách dylib nhúng bằng ipsw dyld split <dsc file>
    • Trong binary /System/Library/Frameworks/IOSurface.framework/IOSurface, tìm tham chiếu "IOCoreSurfaceRoot" của hàm __iosConnectInitalize
    • Chuyển địa chỉ ảo thành file offset bằng ipsw dyld a2o
    • Trong ví dụ, patch offset 0x28fde373 của dyld_shared_cache_arm64e
  • Sau khi sửa DYLD shared cache, cdhash ở vị trí khác không khớp nên phát sinh exception
    • Dùng GDB stub do frontend Virtualization.framework cung cấp để đặt breakpoint vào hàm cs_validate_hash của kernel và xác định toàn bộ cdhash
    • Trong ví dụ iOS 15.0.2, vá các byte cũ tại file offset 0x5a9cffc0 bằng cdhash mới

Vá daemon hệ thống và activation

  • watchdogd kiểm tra liệu nó có đang chạy trong VM không và gây crash-loop vì không có code path macOS để thoát bình thường, nhưng crash này được coi là không gây hại
  • Với backboardd, đã thử vá các lệnh gọi liên quan đến di trú dữ liệu có thể kích hoạt PreBoard.app, nhưng không thấy khác biệt ngoài việc dừng ở logo Apple
  • Trong hàm get_device_type_internal_block_invoke của lockdownd, lệnh gọi getMGInt cho "ShouldHactivate" được vá thành mov x0, #1 để ép hactivation, qua đó bỏ qua hạn chế activation iOS thông thường trong môi trường phát triển
  • mobileactivationd cũng có thể được vá để cho phép hactivation
    • Đổi hàm shouldHactivate thành các lệnh ARMv8-A mov x0, #0ret
  • Các sửa đổi bổ sung cần thiết cho vma2 device tree được để lại như bài tập cho người đọc
  • Một số hành vi có thể cần biện pháp bất thường như chmod -R 777 /

Các giới hạn còn lại và nhập liệu cảm ứng

  • Để vượt qua vấn đề system keybag, cần hiểu thêm cấu trúc tương ứng trong hệ thống iOS và kernel, rồi tạo thêm bản vá
  • Dự án đã tốn ít nhất vài trăm giờ, và trạng thái tiến triển công khai hiện tại là khởi động tới PreBoard.app
  • Chưa xác nhận liệu chức năng cảm ứng có hoạt động thông qua kernel và firmware Mac vma2 công khai hay không
  • Virtualization.framework có các API không công khai liên quan tới cảm ứng
    • _VZAppleTouchScreenConfiguration
    • _VZUSBTouchScreenConfiguration
    • _VZTouch
    • _VZMultiTouchEvent
  • Các API này có thể gửi sự kiện cảm ứng, nhưng cách dùng tham số chính xác chưa được nắm rõ hoàn toàn
    • enum TouchPhase là enum đơn giản triển khai các giá trị cùng tên với NSTouch.Phase
    • Mã ví dụ đôi khi có thể tạo exception
    • Chưa xác nhận các giá trị tọa độ có được ánh xạ theo cách VM kỳ vọng hay không, cũng như VM có xử lý được chúng hay không
  • Demo cho thấy chuỗi khởi động, trong đó đoạn chờ khoảng 30 giây ở giữa đã được cắt bỏ

1 bình luận

 
GN⁺ 2024-10-08
Ý kiến trên Hacker News
  • Corellium đã thắng trong tranh chấp pháp lý, nên giờ có thể cho thuê VM iOS trên đám mây phục vụ nghiên cứu bảo mật https://hn.algolia.com/?query=corellium
    Nếu có thể ảo hóa iOS trên MacBook Apple Silicon, nhu cầu với các dịch vụ ảo hóa iOS thương mại có thể giảm
    Mức giá khoảng $400/tháng cho cá nhân, $60.000/năm cho doanh nghiệp https://support.corellium.com/subscriptions/pricing

    • Trời ơi, $4~$8 mỗi giờ, không biết ai lại trả tiền cho những VM kiểu này
  • Hay đấy. Lần tới hy vọng họ cũng tìm ra cách cài macOS lên iPad, để cuối cùng ta có thể dùng được chiếc máy tính đó mà ta vẫn mong Apple làm ra

    • Có thể bắt đầu từ Windows XP
      https://www.theverge.com/2024/7/22/24200536/windows-xp-ipad-...
    • Theo phần nghiên cứu trước đó, [Zhuowei Zhang] kết luận rằng ứng dụng macOS có GUI không thể chạy trên iOS, nhưng ứng dụng iOS đồ họa có thể chạy trên macOS
      Mac Catalyst dường như cũng chỉ hoạt động một chiều như dự đoán
    • Đồng cảm thật sự, gấp 1000 lần. Trong vài tuần qua tôi cũng đang tìm đúng chủ đề này, tức là một chiếc tablet chạy hệ điều hành dùng cho phát triển
      Xét về kích thước thì iPad Mini rất ổn, nhưng iPadOS vô dụng, nên hiện tôi đang xem Surface Go. Có điều nó hơi lớn
      Tôi biết là không có sản phẩm nào chạy MacOS, nhưng nếu có gợi ý về tablet nhỏ chạy được Win11 thì mong được chỉ giúp. Nếu cần tôi cũng sẵn sàng đặt từ Trung Quốc
    • iPad Pro là thiết bị nhanh nhất dùng M4
    • Nếu gọi nó là MacBook Air có phần lồi bị lật ngược trên dưới và bàn phím tháo rời thì đã đủ chưa?
  • Nhìn hồ sơ GitHub của tác giả thì có vẻ vừa là sinh viên tốt nghiệp ngành khoa học máy tính, nhưng đây thực sự là một công trình ấn tượng

    • Chắc sắp có lời mời tuyển dụng từ Apple thôi
  • Tôi có cảm giác lý do Apple không biến Simulator thành Emulator là vì họ không muốn mọi người đào sâu vào lớp nền bên trong iOS

    • Một lý do khác khiến nó vốn là Simulator chứ không phải Emulator có thể là vì vào thời đó, nhiều thành phần của iOS hoặc iPhone OS là các bản fork từ thư viện Mac OS X hiện có
    • Các lập trình viên vẫn còn dùng Intel Mac, và trên đó không thể ảo hóa ARM iOS
    • Giờ iPhone, Mac, iPad đều là arm64, lại còn dựa trên Apple Silicon, tôi thật sự tò mò bootloader của iOS và macOS khác nhau đến mức nào
      Sau khi qua bootloader, đặc biệt trong bối cảnh Apple kiểm soát cả phần cứng, tôi tự hỏi liệu có lý do gì để tiếp tục duy trì nhiều khác biệt giữa hai hệ điều hành như vậy không
  • Người tạo qemu-t8030 đã chạy được SpringBoard https://mastodon.social/@ntrung03/109712247237110967, nhưng không công bố mã nguồn
    Nếu tiến triển đó có thể được kết hợp với công trình này thì sẽ rất tuyệt

  • Bình luận trước đây: https://news.ycombinator.com/item?id=40219423

  • Bài liên quan: https://worthdoingbadly.com/hv/
    Nói về máy ảo tăng tốc bằng phần cứng trên iPhone 12 đã jailbreak / iOS 14.1

  • Hơi lạc đề một chút, nhưng tôi tò mò liệu đã có ai từng ảo hóa ARM macOS trên x86-64 chưa

    • Không thể. Thông thường “ảo hóa” nghĩa là chạy hệ điều hành bằng ảo hóa phần cứng, trong đó CPU host chạy mã một cách native và chuyển toàn bộ I/O cho hypervisor
      Vì vậy chỉ có thể ảo hóa hệ điều hành được build cho cùng kiến trúc CPU với hệ thống host
      Với các trường hợp còn lại, như chạy phần mềm ARM trên x86 hoặc ngược lại, phải dùng mô phỏng, tức là diễn giải mã hoặc biên dịch lại động
      Theo định nghĩa thì thứ gì cũng có thể được mô phỏng trên bất kỳ thứ gì khác. Gần đây còn có trường hợp boot Linux cho MIPS trên Intel 4004, bộ vi xử lý đầu tiên, nhưng hiệu năng có thể là vấn đề
    • Nếu thử ảo hóa ARM thông thường bằng QEMU, bạn sẽ thấy hiệu năng còn không bằng Raspberry Pi. Các phiên bản gần đây chắc có sẵn mặc định
      Ảo hóa CPU Mn có lẽ còn ít hữu ích hơn
    • Nên xem qua các dự án Hackintosh
  • Apple đã cung cấp iOS Simulator trong Xcode rồi, nên tôi tò mò dự án này tốt hơn công cụ Apple cung cấp ở điểm nào

    • Simulator không chạy iOS thật hay bản build iOS của ứng dụng. Khi chạy ứng dụng trong Simulator, ứng dụng được biên dịch sang tập lệnh native của chiếc Mac hiện tại, rồi được link với các framework và thư viện Mac mô phỏng hành vi iOS kỳ vọng hoặc đôi khi chỉ cung cấp lớp vỏ
      Ví dụ, bạn không thể lấy một binary iOS từ App Store rồi chạy nguyên trạng trong iOS Simulator, đặc biệt càng không thể trên Intel Mac
      Vì Simulator không chạy iOS đầy đủ, bạn cũng không thể khảo sát và học cách nội bộ iOS thật sự hoạt động. Nếu đào đủ sâu vào framework của Simulator, cuối cùng bạn sẽ quay lại macOS
      Ngược lại, emulator chạy toàn bộ bản build iOS giống như trên thiết bị thật. Về lý thuyết, nó có thể chạy bất kỳ binary iOS nào mà không cần sửa đổi và cho phép khảo sát cách hệ điều hành thật vận hành
      Nó giống khác biệt giữa chạy ứng dụng bằng Wine và chạy ứng dụng trong VM Windows. Tuy nhiên với Simulator, tình huống còn gần với việc phải biên dịch lại và link riêng ứng dụng Windows cho phù hợp với môi trường Wine trước khi chạy hơn
      Nếu muốn nghiên cứu nội bộ Windows, chỉ chạy bằng Wine thì không học được nhiều, nhưng khảo sát một VM Windows sẽ học được nhiều hơn rất nhiều
  • Đây sẽ là món quà Giáng sinh sớm cho các click farm