728x90

도입: 시뮬레이터가 아니라 "진짜 iOS"가 뜬다

모바일 앱 CI 파이프라인 붙여본 사람은 다 아는 통증이 있다. Xcode Simulator는 x86/arm64 macOS 바이너리를 돌리는 물건이라 진짜 iOS 커널이 아니다. 그래서 코드사이닝, 키체인, 백그라운드 태스크, 디바이스 특성 타는 SDK(결제, 지문/FaceID, DRM)는 시뮬레이터에서 재현이 안 된다. 결국 랙에 실기기를 꽂아놓고 USB 허브와 씨름하게 된다. 나도 사무실 구석에 아이폰 8대 물린 맥미니를 몇 년 굴려봤는데, 케이블 접촉 불량과 배터리 스웰링이 진짜 장애 원인 1, 2위였다.

vphone-cli가 HN 상위에 오르면서 9천 스타를 넘긴 이유가 이거다. Apple이 macOS에 넣어둔 Virtualization.framework — 원래 macOS/Linux 게스트 부팅용으로 공개된 그 프레임워크 — 안에 Apple의 PCC(Private Cloud Compute) 리서치 VM 인프라 경로가 있고, 이걸 타고 실제 iPhone IPSW를 게스트로 부팅시킨다. 시뮬레이터가 아니라 iOS 커널이 뜨고, SSH가 붙고, VNC로 화면이 나온다.

brew install zqxwce/tap/vphone-cli

# 다운로드 → 패치 → DFU 복원 → CFW 설치 → 첫 부팅까지 한 방
vphone-cli vm create myphone -V jb
vphone-cli vm launch myphone

핵심: PCC 리서치 VM이라는 뒷문과 "패치 개수"의 의미

동작을 거칠게 비유하면 이렇다. Apple은 PCC 보안 검증을 위해 연구자에게 "제한된 Apple OS를 VM으로 띄워 뜯어보라"는 경로를 열어뒀다. 이때 하이퍼바이저 쪽에 PV=3 같은 사적(private) entitlement가 필요하고, 이건 원래 Apple이 서명한 바이너리만 쓸 수 있다. vphone-cli는 이 문을 열기 위해 호스트에서 SIP/AMFI를 완화하고, 서명 안 된 자기 바이너리에 그 entitlement를 얹는다. 즉 게스트가 아니라 호스트의 보안 정책을 먼저 깎는 구조다. 이 지점이 실무 도입의 핵심 판단 포인트다.

그 다음이 게스트 쪽. 그냥 iPhone IPSW를 던진다고 부팅되지 않는다. iBoot → 커널 → AMFI/SSV(서명된 시스템 볼륨)/Img4/TXM으로 이어지는 부트체인 검증이 VM 환경을 거부한다. 그래서 도구가 IPSW를 받아 부트체인 바이너리를 패치하고, DFU 모드로 띄운 뒤 SHSH를 받아 복원하고, CFW(커스텀 펌웨어)를 호스트 마운트로 밀어 넣는다. README의 수동 절차를 보면 파이프라인이 그대로 드러난다.

vphone-cli vm new myphone                          # 1. 빈 번들
vphone-cli fw prepare myphone --iphone-version 26.1 # 2. IPSW 다운로드 + 병합
vphone-cli fw patch myphone --variant jb            # 3. 부트체인 패치
vphone-cli vm launch myphone --dfu                  # 4. DFU 부팅(백그라운드)
vphone-cli restore myphone --get-shsh                # 5. SHSH 획득
vphone-cli restore myphone                           #    DFU 복원
vphone-cli vm stop myphone
vphone-cli cfw install myphone --variant jb          # 6. CFW 설치 (sudo 요구)
vphone-cli vm launch myphone                         # 7. 첫 부팅

재밌는 건 --variant다. 보안 우회 강도를 5단계로 나눠놨고, README에 패치 개수와 CFW 단계 수가 명시돼 있다.

  • less — 4패치 / 2단계. 패치리스에 가깝고 iOS 완화 기능 대부분 유지
  • regular — 42패치 / 10단계. AMFI/SSV/Img4/TXM 우회
  • dev — 53패치 / 12단계. TXM entitlement·디버그 우회 추가
  • jb — 113패치 / 14단계. 풀 탈옥, 첫 부팅 시 Sileo·TrollStore 자동 설치
  • exp — 141패치 / 18단계. jb 상위집합 + 안티-VM-디텍션 리서치 패치

이 숫자를 "많을수록 좋다"로 읽으면 안 된다. 패치를 많이 할수록 부팅한 iOS는 실기기와 멀어진다. 앱 동작 검증이 목적이면 오히려 lessregular가 진실에 가깝고, 내부를 뜯어보거나 파일시스템에 자유롭게 접근해야 하면 jb가 편하다. 안티-VM-디텍션이 붙은 exp는 이름 그대로 리서치용이다.

실무 관점: 도입 전에 계산해야 할 비용과 함정

1) 호스트 보안을 깎는다 = CI 러너로 쓰기 곤란하다

README가 제시하는 두 가지 길 중 A안은 SIP를 완전히 끄고 AMFI까지 부트아그로 무력화한다.

# 복구 모드 터미널
csrutil disable
csrutil allow-research-guests enable

# macOS 재부팅 후
sudo nvram boot-args="amfi_get_out_of_my_way=1 -v"

이 상태 머신을 사내 CI 러너로 쓰겠다는 건, 서명 검증이 꺼진 맥에 사내 코드사이닝 인증서와 App Store Connect API 키를 올려놓겠다는 뜻이다. 보안팀이 있는 조직이라면 그대로는 못 통과한다. B안(csrutil enable --without debug + vphone-amfidont로 해당 바이너리만 허용)이 그나마 낫지만, "debug 제한만 뺀 SIP"도 완전한 SIP는 아니다. 현실적인 타협은 격리 VLAN에 물린 전용 맥, 시크릿 없이, 결과물만 아티팩트로 뽑아내는 구조다.

2) 중첩 가상화 불가 — 클라우드 맥 대부분 탈락

이게 제일 크다. 실무에서 맥 인프라는 보통 클라우드 맥(호스팅 업체의 가상 맥)으로 굴리는데, 그런 환경에서는 아예 뜨지 않는다.

Virtualization is not available on this hardware

README FAQ가 명확히 짚는다. 호스트 맥 자체가 VM이면 PV=3 게스트 부팅을 중첩할 수 없다. 즉 비중첩 물리 Apple Silicon 맥 + macOS 15(Sequoia) 이상이 최소 조건이다. 베어메탈 맥미니를 새로 사거나, 물리 맥을 제공하는 업체를 찾아야 한다. 도입 검토서 첫 줄에 이 문장을 박아두는 게 좋다.

3) 실제로 만나는 에러들

가장 흔한 첫 관문은 이거다. 빌드도 됐고 실행했는데 그냥 죽는다.

$ ./vphone-cli --help
zsh: killed     ./vphone-cli

커널이 SIGKILL을 쐈다는 뜻이고, 원인은 십중팔구 AMFI다. amfi_get_out_of_my_way=1 부트아그가 안 먹었거나(=SIP가 완전히 꺼져 있지 않았거나), vphone-amfidont로 allowlist를 안 걸었거나. 특히 A안에서 csrutil disable 없이 nvram만 건드리면 부트아그 자체가 무시된다. nvram boot-args로 값이 남아 있는지, csrutil status로 SIP 상태가 어떤지 둘 다 확인해야 한다.

다음으로 삽질 유발 1위는 cfw install이 시스템 바이너리 재서명 중에 멈추면서 메모리가 무한정 올라가는 현상이다. README에 원인이 꽤 상세히 적혀 있는데, ldid-procursus 2.1.5-procursus7까지의 버그다. bytes(uint64_t)__builtin_clzll(0)을 제로 가드 없이 호출해 UB가 되고, 그 결과 길이가 0으로 잡히면서 unsigned 루프 카운터가 언더플로 → 1바이트씩 무한히 버퍼에 쓰며 종료하지 않는다. entitlements plist에 정수 값 0이 들어 있는 Apple 시스템 바이너리를 만나면 터진다. 대응은 이렇다.

sudo kill -9 <hung ldid pid>      # 이미 걸렸으면 먼저 죽이고
brew install --HEAD ldid-procursus
brew link --overwrite ldid-procursus

업스트림에서 고쳐졌지만 아직 태그된 릴리스에 안 들어가서, Homebrew stable을 쓰면 그대로 밟는다. 나 같으면 사내 프로비저닝 스크립트에 이 --HEAD 설치를 아예 박아두겠다.

그 밖에 실제로 자주 걸리는 것들:

  • "Press home to continue"에서 멈춤 — VNC(vnc://vm-ip:5901)로 붙어서 우클릭(두 손가락 클릭)이 홈 버튼이다. 하드웨어 버튼이 없으니 당연한데 모르면 5분 날린다.
  • 시스템 앱이 설치되지 않음 — iOS 초기 설정에서 지역을 일본이나 EU로 고르면 안 된다. VM이 만족시킬 수 없는 규제 검사가 추가로 붙는다. 미국 같은 지역을 선택하라는 게 README 권고다. 이거 모르고 "한국 옆이니까 일본" 골랐다가 재설치하는 사람 나온다.
  • 앱이 EXC_GUARD / GUARD_TYPE_MACH_PORT로 크래시vphone-cli fw patch <name> --variant <v> --force-exc-guard로 다시 패치한 뒤 재복원·재설치. iOS 18 베이스에서는 항상 켜야 한다고 명시돼 있다.

4) 그래도 매력적인 지점: 자동화 소켓

실무자 입장에서 제일 눈이 간 건 사실 이 부분이다. VM 번들 안에 vphone.sock 호스트 컨트롤 소켓이 있어서 스크린샷·터치·스와이프·하드웨어 키·클립보드를 프로그래밍으로 조작할 수 있고, 각 액션이 스크린샷을 인라인으로 반환한다. AI 기반 E2E 테스트를 염두에 둔 설계고, 이를 MCP 서버로 감싼 vphone-mcp도 같이 언급돼 있다.

실기기 팜에서 이걸 하려면 WebDriverAgent 띄우고 USB 세션 관리하고 스크린샷 파이프 뚫느라 인프라가 꽤 나온다. VM이면 vm clone이 APFS 클론이라 빠르고 디바이스 아이덴티티도 새로 발급된다. 테스트 케이스마다 깨끗한 기기를 몇 초 만에 찍어내는 그림은 확실히 탐난다.

vphone-cli vm clone myphone myphone-2   # APFS 클론 + 새 디바이스 아이덴티티
vphone-cli vm list --json               # 스크립팅용
vphone-cli vm export myphone --out ./backup/   # zstd, 기본 fast (--max = xz -9)

5) 트레이드오프와 대안

정리하면 이렇다. 얻는 것은 진짜 iOS 커널, 스냅샷/클론, 케이블 없는 팜, 루트 셸(ssh -p 22222 mobile@<vm-ip>, 비밀번호 alpine). 내주는 것은 호스트 보안 정책, 물리 맥 하드웨어 비용, 그리고 법적·정책적 리스크다. IPSW와 iOS는 Apple EULA 대상이고, 이 도구는 부트체인 패치와 탈옥을 포함한다. 회사 제품 테스트 인프라로 상용 도입하겠다면 법무 검토 없이는 못 간다. 개인 리서치나 보안 분석 목적과, 사내 CI 표준화는 완전히 다른 문제다.

대안은 여전히 셋이다. (1) 순수 기능 검증은 Xcode Simulator + XCUITest, (2) 실기기 커버리지는 클라우드 디바이스 팜(BrowserStack, Firebase Test Lab 계열) 또는 자체 실기기 팜, (3) 보안 리서치·펌웨어 분석이면 vphone-cli. 세 번째 칸의 대안이 사실상 없었다는 게 이 프로젝트의 진짜 가치다.

정리

한 줄로: Apple의 PCC 리서치 VM 경로를 이용해 물리 Apple Silicon 맥 위에 실제 iPhone 펌웨어를 부팅시키는 도구이고, 그 대가로 호스트의 SIP/AMFI를 깎는다.

  • 지금 써볼 사람 — iOS 보안 리서처, 펌웨어/커널 분석가, 탈옥 생태계 도구 개발자, "실기기 없이 iOS 내부를 뜯어보고 싶다"는 사람. 여기엔 대체재가 사실상 없다.
  • 관망할 사람 — 앱 CI/CD 담당자. 아이디어는 매력적이지만 SIP off 머신을 파이프라인에 넣는 순간 보안 리스크가 이득을 넘는다. 자동화 소켓 + MCP 조합이 어떻게 성숙하는지 6개월쯤 지켜볼 가치는 충분하다.
  • 쓰면 안 되는 사람 — 클라우드 맥(중첩 VM)만 있는 팀. 하드웨어부터 다시 사야 한다.

테스트된 조합도 README에 표로 정리돼 있는데, 호스트 macOS 26대, 게스트 iPhone 펌웨어 18.6.2부터 27.0 베타대까지 꽤 넓다. 다만 표에 없는 조합은 언제든 깨질 수 있는 성격의 프로젝트로 보이니, 실제 검증 전에 Tested Environments 표부터 확인하는 게 맞다.

참고 자료

728x90

+ Recent posts