서랍 속에 쓰지 않는 안드로이드 폰이 하나쯤 굴러다닌다. 부트로더 잠금을 풀고 커스텀 롬을 올려 보는 일은 꽤 익숙하지만 여기에 아이폰 운영체제인 iOS를 올려 볼 생각은 좀처럼 하지 못한다. 당연한 일이다. iOS는 애플이 만든 칩 위에서만 돌아가고 아이폰은 애초에 커널을 마음대로 갈아 끼울 수 없게 단단히 잠겨 있다. iOS가 켜질 때 실제로 어떤 과정을 거치는지, 커널 위에서 시스템 프로세스들이 어떤 순서로 깨어나는지 눈으로 직접 확인하고 싶어도 들여다볼 구멍이 없다.

그런데 애플이 iOS의 심장부인 XNU 커널 소스코드를 오래전부터 일반에 공개해 왔다는 사실은 의외로 잘 알려져 있지 않다. 물론 커널 소스만 달랑 있다고 해서 iOS가 켜지지는 않는다. 화면을 그리는 그래픽, 보안 암호화, 터치 입력, 무선 통신처럼 실제 하드웨어 부품과 맞닿는 드라이버들은 여전히 애플이 비공개로 닫아 두었기 때문이다. 그동안 아무도 안드로이드 폰에서 iOS를 부팅하지 못했던 이유가 바로 이 거대한 빈칸에 있다.

OOSEX GANG이라는 팀이 공개한 ‘HackiOS’는 이 빈칸을 처음부터 직접 메워 샤오미의 안드로이드 폰인 POCO X5 Pro 5G에서 iOS 16.5를 잠금 화면부터 사파리 브라우저까지 그대로 띄워 냈다. 놀라운 건 정작 iOS 시스템 파일은 단 한 바이트도 고치지 않았다는 점이다. 어떻게 손대지 않은 iOS를 낯선 안드로이드 하드웨어 위에서 속여 넘겼는지, 지금 무엇이 돌아가고 무엇이 막혀 있는지 하나씩 뜯어본다.

커널 아래의 바닥을 통째로 새로 깔았다

안드로이드 폰 하드웨어 위에 UEFI와 로더, XNU 커널, 손대지 않은 iOS 사용자 공간이 층층이 쌓인 그림
맨 위의 iOS는 그대로 두고 그 아래를 전부 새로 깔았다.

HackiOS가 바탕으로 삼은 커널은 xnu-8796.121.2다. 실제 iOS 16.5에 들어간 바로 그 버전이다. 개발팀은 애플이 공개한 이 커널 소스에 직접 짠 플랫폼 계층을 덧붙여서 안드로이드 폰의 두뇌인 퀄컴 스냅드래곤 778G 칩에서 돌아가도록 손봤다. 맨땅에서 시작하는 대신 원래 XNU 소스에 남아 있던 라즈베리 파이용 칩(BCM2837) 설정 코드를 출발점으로 삼아 살을 붙였다.

그 커널 위에 올라가는 사용자 공간(우리가 눈으로 보고 만지는 앱과 시스템 프로그램 영역)은 순정 iOS 16.5 그대로다. 첫 번째 프로세스인 launchd가 깨어나고 그 뒤를 이어 logd, notifyd, cfprefsd, runningboardd, backboardd 같은 핵심 배경 데몬들이 차례대로 뜬 다음 마침내 홈 화면을 그리는 SpringBoard가 올라온다. 이 과정에서 iOS 기본 프로그램이나 프레임워크, 공유 라이브러리 캐시(dyld 공유 캐시)는 단 한 바이트도 수정하지 않았다. 하드웨어가 달라서 생기는 빈틈은 전부 커널 밑단이나 실행 중에 끼워 넣는 바깥 라이브러리에서 대신 받아 준다.

커널 아래쪽에도 보이지 않는 주춧돌이 하나 더 놓여 있다. 안드로이드 폰에는 당연히 애플 전용 부트로더인 iBoot가 없으니 윈도우 구동 프로젝트인 Project Silicium의 UEFI 펌웨어(Mu-Silicium)를 빌려 쓰고 그 위에 xnuloader라는 전용 부트 로더를 직접 만들어 얹었다. 이 로더는 커널이 완전히 켜진 뒤에도 메모리 한구석에 살아서 컴퓨터와의 USB 연결이나 시스템 멈춤 감시(워치독)를 도맡고 커널이 뱉어 내는 로그를 차곡차곡 받아 둔다.

결국 이 프로젝트는 iOS를 뜯어고친 게 아니라 순정 iOS가 아이폰이라고 믿고 발을 디딜 수 있는 가짜 바닥을 안드로이드 폰 위에 정교하게 새로 깔아 준 셈이다. 그래서 코드 저장소 안에는 애플의 저작권이 걸린 파일이 단 하나도 들어 있지 않다. 사용자가 빌드 스크립트를 실행하면 그제야 애플 공식 서버(CDN)에서 정식 iOS 설치 파일(IPSW)을 직접 내려받아 필요한 알맹이만 뽑아 쓴다.

닫힌 드라이버 자리를 무엇으로 채웠나

애플이 공개하지 않은 조각과 HackiOS가 그 자리에 넣은 대체품을 짝지어 보여 주는 그림
닫힌 조각마다 리눅스나 직접 짠 코드로 대역을 세웠다.

애플이 소스를 공개하지 않은 핵심 부품들은 하나씩 똑같은 규격의 대역을 만들어 끼워 넣었다. 시스템 전반의 암호 계산을 맡는 corecrypto 자리에는 직접 만든 minicrypto를 꽂았고 앱의 디지털 서명을 깐깐하게 검사하는 AMFI와 앱의 권한을 가두는 Sandbox는 무조건 통과 도장을 찍어 주는 대역 모듈로 바꿨다. 화면 픽셀 버퍼를 주고받는 IOSurface와 IOMobileFramebuffer, 암호 키 보관소인 AppleKeyStore, 심지어 네트워크 통신 스택까지 전부 새로 작성해 빈자리를 메웠다.

까다로운 부품 드라이버는 이미 잘 돌아가는 리눅스 생태계에서 똑똑하게 빌려 왔다. 폰에 달린 와이파이 칩(WCN6750)은 리눅스용 ath11k 드라이버를 가져다가 LinuxKPI라는 호환 통역 계층 위에 올려 그대로 돌린다. 그래픽 칩인 Adreno 642L은 오픈소스 그래픽 드라이버인 Mesa의 freedreno로 구동하고 그 위에서 iOS의 화면 효과 엔진인 CoreAnimation이 OpenGL ES 방식으로 그림을 그린다. 터치스크린(Goodix GT9916) 입력은 /dev/redwood-touch라는 장치 파일을 거쳐 올라온다.

커널 드라이버만으로 해결되지 않는 마지막 조각은 프로그램이 실행될 때 메모리에 보조 라이브러리를 몰래 끼워 넣는 방법(DYLD_INSERT_LIBRARIES)으로 풀었다. 터치와 화면 이벤트를 관리하는 backboardd, 홈 화면인 SpringBoard, 소리를 다루는 mediaserverd 세 프로세스가 뜰 때 맞춤형 라이브러리를 함께 밀어 넣는 식이다. 이 라이브러리가 가짜 입력 장치(HID) 신호를 만들어 주고 내부 Objective-C 함수 몇 개를 실시간으로 가로채 바꿔치기한다. 오디오 쪽에도 RedwoodAudio.driver라는 가상 출력 장치를 붙여서 소리가 나게 했다. 이 모든 속임수가 디스크의 원본 파일은 건드리지 않은 채 오직 RAM 메모리 위에서만 일어난다.

카메라는 찍히지만 앱 스토어는 열리지 않는다

HackiOS에서 동작하는 기능과 아직 동작하지 않는 기능을 두 칸으로 나눈 그림
화면과 입력은 거의 다 되고 보안 칩이 필요한 것은 안 된다.

실제로 켜진 화면에서 돌아가는 기능 목록은 생각보다 훨씬 길다. 잠금 화면을 밀어서 풀고 두 페이지짜리 홈 화면을 넘기는 건 기본이고 화면 아래에서 위로 쓸어 올리거나 가장자리를 밀어 뒤로 가는 제스처, 제어 센터 호출까지 매끄럽게 먹힌다. 설정, 시계, 캘린더, 사진, 메모, 사파리 같은 기본 앱이 정상적으로 열리고 날씨와 캘린더 위젯도 제자리에 뜬다. 여러 손가락을 동시에 쓰는 멀티터치와 폰 옆면의 실제 전원·볼륨 버튼, 스피커와 마이크는 물론이고 전·후면 카메라로 HEIC 포맷 사진과 동영상, 라이브 포토까지 찍힌다.

성능도 장난감 수준을 넘어선다. 스냅드래곤 칩의 CPU 코어 8개를 전부 깨워 고성능 코어를 2.4GHz 클럭까지 돌리기 때문에 부팅을 시작하고 약 20초면 잠금 화면이 나타난다. 설정 앱에서 와이파이를 잡아 사파리로 웹서핑을 하면 55~90Mbit/s 속도가 나오고 탈옥 생태계에서 쓰는 패키지 관리자(Sileo, Procursus 기반 dpkg·apt)와 각종 트윅, 원격 접속용 SSH까지 그대로 올려 쓸 수 있다.

반면 아직 막혀 있는 벽은 한결 근본적이다. 이동통신(셀룰러)과 블루투스는 아직 붙지 않았고 커스텀 커널 상태에서는 배터리 충전 회로가 동작하지 않아 켜 둔 동안에는 배터리가 줄어들기만 한다. 사용자 입장에서 가장 아쉬운 대목은 App Store 다운로드와 Apple ID 로그인인데 이건 소프트웨어만으로는 어쩔 도리가 없다. 안드로이드 폰 기판에는 애플 고유의 물리 보안 칩인 ‘Secure Enclave’가 아예 존재하지 않기 때문이다. 같은 이유로 디지털 저작권(DRM)을 검증하는 FairPlay 데몬도 켜지자마자 바로 종료된다. 일반 앱들이 쓰는 그래픽 엔진인 Metal 지원은 아직 개발 중이며 현재는 시스템 기본 그래픽 셰이더 456개 가운데 293개가 Adreno GPU 위에서 돌아간다.

폰을 건드리지 않고 RAM 위에서만 15분씩 켜 본다

안드로이드에서 로더로, RAM에 이미지를 올리고 커널을 띄운 뒤 다시 안드로이드로 돌아오는 순서를 보여 주는 그림
전부 RAM 안에서 벌어지고 재부팅하면 안드로이드로 돌아온다.

여기서 꼭 짚고 넘어갈 점이 있다. HackiOS는 기존 안드로이드를 밀어내고 폰에 영구적으로 설치하는 커스텀 롬이 아니다. 개발팀 스스로도 이를 “정해진 시간 동안만 돌아가는 연구용 실험대(research bench)”라고 부른다. 폰의 내장 저장 공간(플래시 메모리)에는 아무것도 굽지 않는다. fastboot boot 명령으로 UEFI와 부트 로더를 폰의 휘발성 메모리(RAM)에 잠시 올리고 그 안에서 모든 일을 처리한다.

부팅 과정은 저장소에 포함된 xl 스크립트로 간단히 조종한다. 먼저 ./xl enter를 치면 안드로이드 상태이던 폰이 fastboot 모드를 거쳐 전용 로더 화면으로 넘어간다. 이어서 ./xl ramdisk를 실행하면 약 80초에 걸쳐 2.5GB짜리 iOS 시스템 이미지를 통째로 폰의 RAM에 밀어 넣는다. 이 작업은 로더가 켜져 있는 동안 한 번만 해 두면 된다. 마지막으로 ./xl run을 치면 드디어 XNU 커널이 깨어나며 iOS가 부팅된다. XL_SECS 설정값(기본 예시 900초, 즉 15분)만큼 시간이 흐르면 커널이 스스로 실행을 멈추고 로더로 돌아가 그동안 모은 로그를 컴퓨터로 넘긴다. 다 끝난 뒤 ./xl reboot를 치면 폰은 아무 일도 없었다는 듯 원래의 안드로이드로 다시 켜진다.

당장 손에 POCO 폰이 없어도 리눅스 컴퓨터만 있으면 가상 머신(QEMU)으로 똑같이 띄워 볼 수 있다. 64비트 리눅스 환경에 빈 디스크 공간 약 12GB와 여유 RAM 4GB만 있으면 충분하다. 7.4GB짜리 순정 IPSW 파일을 내려받아 압축을 푸는 데 5~15분쯤 걸리고 애플 전용 파일시스템(APFS)을 읽으려면 7-Zip 23 이상 버전이 깔려 있어야 한다. 가상 머신에서는 부팅부터 잠금 화면까지 2~3분, 홈 화면이 뜬 뒤 기본 앱들이 등록되는 데 30~40초가 더 걸린다. 화면 위에서 마우스 왼쪽 버튼을 꾹 누르고 움직이면 손가락 터치로 인식된다.

실제 스마트폰에서 돌려 보려면 부트로더가 풀린 POCO X5 Pro 5G(코드명 redwood)가 있어야 한다. GPU나 와이파이, 오디오, 진동 모터를 깨우는 제조사 전용 펌웨어 파일들은 저작권 문제로 저장소에 들어 있지 않아서 내 폰에 깔린 안드로이드 파티션에서 직접 추출해 와야 한다. 만약 다른 안드로이드 기기로 이식해 보고 싶다면 저장소의 common/devices/ 폴더 아래 기기 설정 파일들과 docs/PORTING.md 안내서를 이정표 삼아 도전해 볼 수 있다.

잠긴 아이폰에서는 절대 볼 수 없는 장면

소식이 전해지자 GeekNews 댓글창에는 “아이폰 사서 쓰면 그만인데 왜 굳이 안드로이드 폰에서 이 고생을 하느냐”는 질문이 여럿 올라왔다. 답은 앞서 말했듯 이 프로젝트가 일상용 롬이 아니라 ‘연구용 실험대’라는 데 있다. 실제 아이폰에서는 보안 잠금에 막혀 절대 해 볼 수 없는 실험, 즉 커널 밑단과 하드웨어 드라이버, 보안 검사 모듈을 전부 내 손으로 뜯어고치고 갈아 끼운 상태에서 순정 iOS가 어떻게 반응하는지 관찰할 수 있는 유일한 창구이기 때문이다. 모든 밑바닥이 투명하게 열린 iOS는 역설적이게도 아이폰 바깥에서만 만들 수 있다.

왜 최신 버전이 아니라 하필 iOS 16.5를 골랐는지도 많은 이들이 궁금해했다. 공개된 문서에는 당시 작업에 쓴 XNU 오픈소스 버전이 iOS 16.5의 커널이라는 사실만 담백하게 적혀 있다. 댓글창에서는 iOS 17 이후로 추가된 까다로운 보안 장치들 때문에 포팅 난도가 훨씬 높아졌을 거라는 추측이 오갔지만 개발팀이 밝힌 공식적인 이유는 아니다.

법적인 경계선도 아주 조심스럽게 그어 두었다. 저장소 안에 애플 소유의 코드나 바이너리는 단 한 줄도 넣지 않았고 이 프로젝트가 애플과 무관한 독립 연구이며 애플의 승인을 받지 않았다는 점을 분명히 못 박았다. 공개된 XNU 수정본과 로더, 빌드 스크립트는 애플의 오픈소스 라이선스인 APSL 2.0으로 배포된다. 낯선 샤오미 폰 위에서 순정 iOS가 잠금 화면을 밝히고 와이파이를 잡아 사진을 찍는 이 기묘한 풍경은 운영체제와 하드웨어 사이의 약속만 정확히 맞춰 주면 그 위를 달리는 소프트웨어는 자기가 어디에 올라타 있는지조차 모른다는 사실을 가장 극적으로 보여 준다.

출처: oosexgang/hackios-xnu-kernel, GeekNews 소개글