QEMU에서 iPhone 에뮬레이션 하기
(eshard.com)iOS 14 QEMU 에뮬레이션 여정의 시작
- 기존 오픈소스 프로젝트인
alephsecurity/xnu-qemu-arm64를 사용했지만 읽기 전용(read-only)이라 확장성 부족 문제 있었음 - 이후
TrungNguyen1909/qemu-t8030프로젝트를 사용하며 다음 기능들 활용 가능했음:- iOS 복원 기능 (USB 연결용 QEMU 동반)
- iOS 14 실행
- 최신 QEMU 버전 기반
- 상세 위키 문서 제공
launchd.plist수정으로 쉘 및 SSH 접근 성공하며 좋은 출발점으로 삼음- 목표는 UI와 앱 실행 가능한 완전한 iOS 에뮬레이션 환경 구축임
커널 패치 및 PongoOS 도입
t8030프로젝트는 QEMU 내부에서 커널 패치하는 구조였음 → 유지보수 및 확장성 문제 발생- 탈옥 경험 바탕으로
PongoOS를 통해checkra1n패치를 적용하는 구조로 전환 - QEMU에서 SRAM 크기 증가시켜 PongoOS 실행하고, checkra1n-KPF 모듈 주입
- 부트 시 부트롬/iboot 기능 누락으로 FPU 미설정 이슈 발생 → ARM 문서 참고해 해결
- A13 이후 PAC(Pointer Authentication) 도입으로 일부 패치 무효화됨
task_for_pid0 (tfp0)예시로 PAC 도입 전후의 바이너리 비교
커널 패치 자동화 도구 개발
- 기존 checkra1n 동적 패치 방식은 읽기 어렵고 수정 불편 → 선언적 텍스트 기반 패치 방식 도입
- 두 개의
Mach-O바이너리 비교하여 어셈블리 차이점 추출 후 텍스트 패치 생성 - Pongo로 부팅 후 메모리 덤프하여 커널 재조립 → 전체 패치를 텍스트 파일로 정리 및 주석화
그래픽 렌더링: Metal vs 소프트웨어 렌더링
- iOS는 모든 UI 렌더링을
MetalAPI를 통해 수행 → GPU 필요 - GPU 에뮬레이션 복잡함으로 대안 고려:
- 소프트웨어 렌더링
- Metal 호출을 실기기로 프록시 전달
- iOS 14에서는
gpu=0bootarg 제거됨 → QuartzCore 분석해 fallback 동작 확인 - 탈옥폰에서
QuartzCore패치하여 소프트웨어 렌더링 작동 확인 (느리지만 가능) - Metal 프록시 방안도 실험하였으나 Objective-C 및 API 복잡성으로 중단
프레임버퍼 및 IOSurface 디버깅
t8030QEMU에는 프레임버퍼 구현 없음 →ChefKissInc/QEMUAppleSilicon포크 사용- 초기 부팅 시 Apple 로고와 진행 표시 보였지만 이후 검은 화면 → 디버깅 시작
- IOMFB kext 분석 결과, 두 가지 모드 존재:
- 고정 주소 프레임버퍼 (초기 표시용)
- DMA 기반 다중 평면 구성
- 시스템 부팅 중 DMA 기반 모드 사용 → QEMU의 트레이스로 커널 레지스터 설정 확인
- 하지만 여전히 화면에 출력 없음
주소 랜덤화 비활성화
- 커널 주소 랜덤화는 보드 초기화 코드에서 해제 가능
- 사용자 영역의 랜덤화는
_load_machfile패치하여 비활성화 - dyld 캐시는 모든 동적 라이브러리 포함한 큰 바이너리 → 부팅 시 고정 주소에 로드됨
- C 도구를 만들어 dlopen 후
_dyld_*함수로 주소 확인 - GDB로
dyld라이브러리 디버깅 가능하게 함 → 특히IOMFB,SpringBoard,QuartzCore관심 가짐
USB 로그 접근 및 lockdownd 우회
- 실기기에서는
idevicesyslog로 시스템 로그 수집 가능 → USB 인증 필요 - lockdownd는 키 저장에 SEP가 필요한 keybag 사용 → 에뮬레이터에 없음
- 기존 함수 자리에 쉘코드 삽입하여 키 파일에서 직접 로딩하게 함
- USB 연결된 QEMU 간 키 인증 우회 성공 → 로그 수집 가능
- QuartzCore 정상 초기화 및 소프트웨어 렌더링 사용 확인됨
PAC(Pointer Authentication) 우회
backboardd수정 중 PAC 오류 발생 → ARMv8.3에서 도입된 보안 기능- PAC 명령어를 NOP 대체하는 방식은 지나치게 침습적
- PAC 명령어는 호환 방식으로 컴파일 가능 → QEMU에서 PAC 무시하면 실행 가능
- QEMU 7은 PAC 우회 불가 → QEMU 8.2.1로 마이그레이션
- Apple 전용 명령어 및 GL 예외 레벨 등 수많은 QEMU 커스텀 코드 이식 필요
- 결과적으로 QEMU 8에서 iOS 부팅 성공 및 PAC 무력화 가능해짐
backboardd와 그래픽 출력 확인
backboardd동작하나 화면 표시 없음 → 여러 원인 가능성 존재- DMA 메모리 덤프해도 유의미한 출력 없음
iosurface_lock에서 주소 확인하고 프레임 덤프했으나 압축된 형태로 GPU에 전달되는 듯- iPhone X (t8015)에서는 비압축 출력 확인됨 → QEMU의 DTB를 수정하여
chip-id를 t8030 → t8015로 변경 - 결과적으로 부팅 후 Apple 로고 표시됨
진행 표시줄과 시스템 오류 추적
- 로고 이후 하얀색 진행 표시줄 출력 → 90%에서 정지
- 로그 분석 통해
mobileactivationd와SpringBoardFoundation문제 발견 → 패치 후 UI 변경됨 - 진행 막힘 문제 해결을 위해 다수의 시스템 로그 분석 필요
dyld 캐시 및 사용자 공간 패치 자동화
- 커널과 동일한 방식으로 사용자 공간도 텍스트 기반 패치 방식 사용
- dyld 캐시는 2GB 크기로 수정에 비효율적 → 내부 도구 개선하여:
- dyld 내 오프셋 추적
dd명령어로 특정 위치 직접 패치
- 커널 서명 검사 우회 패치 병행 필요
PreBoard 실행 및 UI 확인
PreBoard앱은 오류 시 표시되는 시스템 앱 → 직접 실행 가능- VNC 서버 추가하여 키보드로 화면 잠금 해제 시도
- unlock 이후
vImage프레임워크에서 AMX(Apple Matrix Coprocessor) 명령어 사용 → QEMU 미지원 vImage의 소프트웨어 fallback 경로로 패치하여 문제 해결- 패치 후 텍스트 입력 가능한 화면까지 표시 성공
결론
- SpringBoard 실행 직전까지 도달 → 이제 완전한 UI 실행은 시간 문제
- 커널, 사용자 공간, 그래픽, 보안 기능(PAC 등) 다각적 분석 및 패치 수행
- QEMU 기반의 실질적인 iOS 앱 디버깅 및 테스트 환경 가능성 확인
댓글과 토론
Hacker News 의견
- https://github.com/devos50/qemu-ios 프로젝트가 iPhone OS 3.x를 지원하도록 발전했으면 좋겠음. 이는 초기 iPhone 앱을 디지털 보존을 위해 경험할 수 있게 해줌
- https://github.com/touchHLE/touchHLE도 훌륭하지만, 기본 앱 외에는 패치가 필요함
- https://github.com/TrungNguyen1909/qemu-t8030/… 지침을 따라 실행했으나 여러 번 충돌했음. 그래도 꽤 멋짐
- QEMU로 NumWorks N0100과 HP Prime G1을 에뮬레이션한 적이 있음. 공식 펌웨어를 실행할 수 있을 정도로 성공적이었음
- 이 프로젝트를 재미있게 활용하는 방법: 하드웨어 지원이 좋은 폰에 postmarketOS를 설치하고, QEMU를 사용해 Android 폰에서 iOS를 부팅하는 것임. QEMU를 커스터마이즈하여 폰 하드웨어를 iOS VM으로 전달할 수 있을 것임
- Apple 하드웨어 없이 Linux 시스템에서 Safari 테스트 및 iOS 컴파일을 할 수 있다는 의미인지 궁금함
- https://github.com/ChefKissInc/QEMUAppleSilicon
- Apple Silicon 장치를 QEMU에서 에뮬레이션 중이며, 현재는 iPhone 11만 지원함
- 데모 비디오: https://nitter.poast.org/eshard/status/1908162866609311962
- 네트워크 연결에 대한 언급이 없음. WiFi나 셀룰러 모뎀 칩셋을 에뮬레이션하지 않는 것 같음. 에뮬레이션된 장치를 인터넷에 연결하는 방법이 궁금함. USB를 통한 이더넷 같은 방법일 수 있음
- 보관된 버전: https://archive.ph/l1CwO
- 이를 재현할 수 있는 저장소가 있는지 궁금함
- Apple이 멀티플랫폼 iOS 개발을 수용하려면 무엇이 필요할지 궁금함