TL;DR: 탈옥 방법을 찾고 싶으신 분들은 https://github.com/perillamint/RP4JailbreakKit 의 스크립트 셋을 사용하십시오.
들어가며
3월 21 일, 책을 (말도 안 되는) 할인가로 사면 리디 페이퍼 4를 덤으로 끼워주는 급의 “대란” 이벤트가 있었다. 이 이벤트를 통해 리디 페이퍼 4를 덤으로 얻게 되었다.
리디북스 페이퍼 4는, 리디의 전용기여서 기본적으로는 타사 앱 실행이 불가능하다. 하지만 “절대” 는 (특히 회사가 안드로이드 커스터마이징에 있어 락다운을 신경을 그렇게 쓰지 않았다면) 높은 확률로 존재하지 않는 법. 개조를 통해 타사 앱을 사이드로드해 보자.
이미지 얻기
리디북스는 공식적으로 리디 페이퍼에 대한 리커버리 이미지를 제공하지 않는다. 하지만, 공식적으로 제공하지 않는다면 뜯어내면 되는 법, OTA 업데이트를 통해 시스템 이미지를 얻어 보자.
리디 페이퍼는 다음과 같은 OTA URL 포멧을 사용한다.
https://viewer-api.ridibooks.com/app/versions?platform=<platform_name>&serial_number=<device_sn>
이 중, serial number 는 꼭 유효한 시리얼 넘버일 필요는 없으며, 중요한 부분은 platform_name 부분이다. 이를 알아내기 위해, mitmproxy 를 이용해 트래픽을 살펴보자.
(셀 수 없는 올바르지 않은 인증서 경고 속에서 캡쳐된) 리디 서버와의 통신 일부를 통해 리디 페이퍼 4의 플랫폼 이름이 ridipaper_4 임을 알 수 있다.
이를 이횽해 해당 API 를 요청하면 2023-04-22 기준, 다음과 같은 API 응답을 돌려준다
{ "version_name": "1.0.8", "version_code": 2022071901, "update_url": "https://viewer-ota.ridicdn.net/ridipaper_4/update-1.0.8-2022071901.zip", "description": "<b>[기능 개선]</b><br>- 구매목록 필터링 기능 개선 및 사용성 개선<br>- 사용자 책장 내의 연재/시리즈에서 전체 다운로드 기능 추가<br>- 시스템 업데이트 다운로드 후 파일 검사 단계 추가 및 업데이트 안정화<br><br><b>[버그 수정]</b><br>- 기기 잠금 설정 후 슬립 상태로 전환 시의 오동작 수정<br>- 사용자 책장에서 작품 제거 기능 오동작 수정<br>- 가로모드에서 페이지 넘김 버튼 설정 팝업이 잘리는 문제 수정<br>- 기타 버그 수정" }
이 응답을 통해서, Android update.zip 이 어디에 존재하는지를 알게 되었다. 해당 upate.zip 을 받아서 열어보자.
해당 업데이트 패키지는 일반적인 안드로이드 10 update.zip 의 구조를 띄고 있다. 이 업데이트 파일로부터 system, vendor, 그리고 중요한 recovery.img 와 boot.img 를 획득할 수 있다.
이제 (boot 파티션 문제에 한정한다면) 안전하게 되돌아갈 길이 있으니, Magisk 를 설치해서 부팅시켜 보자.
… 부팅이 된다! 이는 해당 부트로더가 (처음 걱정과 다르게) 잠겨 있지 않다는 것을 의미한다. 하지만 이제 다음 문제가 있다. Magisk 는 설치되었지만, Magisk 와 상호 작용 하려면
- adb 나 기타 방법으로 Magisk.apk 를 설치
- Magisk App 을 실행 후, Magisk 디렉토리 셋업 진행 후 시스템 재 시동
의 과정이 필요하지만, 리디 페이퍼 4에서는 (부트로더가 잠겨 있지 않음에도) adb (와 파일 관리자, 제대로 된 런쳐, etc…) 의 부재로 인해 해당 과정을 수행하지 못한다. 이를 우회하기 위해서 어떻게든 adb 를 활성화할 방법을 찾아 보자.
ADB 켜기, 어떻게?
adb 를 켜기 위해서는 여러 방법을 생각해볼 수 있다.
sytem.transfer.dat 과 vendor.transfer.dat 을 보면, 거의 system / vendor 이미지의 전체를 담고 있는 것을 확인할 수 있다. 이를 https://github.com/xpirt/sdat2img 툴을 이용해 이미지로 바꾼 뒤 분석해 보자.
system 파티션에는 여러 시스템 앱들이 존재한다. 이 앱들을 apktool 을 이용하여 disassemble 한 뒤, 이 중에 adb 를 켜는 기능이 있는 지점들을 찾아보자.
SettingsProvider.apk 를 제외하면, RIDIDeviceManager.apk 와 ERD850HWTest.apk 두 가지가 보인다. 이 중, RIDIDeviceManager 의 경우를 살펴보자. RIDIDeviceManager 는 첫 셋업 이후 깨어나서 ro.build.type 이 engineering build 일 경우에 adb 를 활성화하고, user 빌드일 경우, adb 를 비활성화하도록 되어 있다. 더불어, ERD850HWTest.apk 는 팩토리 테스트 기능을 구현하기 위해, user 빌드일 경우 adb 를 활성화하도록 되어 있는 것을 확인할 수 있지만, 해당 앱을 순정 상태에서 호출하기 위해서는 매직 키 콤보가 필요하다. (이 키 콤보는 하단 부록에 추가 기술하였다) 우선은 이 매직 키 콤보를 제외한 방법을 생각해 보자.
이 상황에서 adb 를 켜기 위해, 다음과 같은 방법을 생각해 볼 수 있다.
- system.img 를 패치하여 엔지니어링 빌드 상태로 만든다
- 첫 셋업이 완료되기 전 Magisk 를 통해 adb 를 임시 활성화한 뒤, LSPosed hook 을 통해 엔지니어링 빌드로 스푸핑한다
하지만 1안의 경우에는 (boot.img 의 Verified Boot 를 비활성화 한다 하더라도) 아직 우리가 풀 super.img 를 획득하지 못하였으며, 풀 플래싱이 아닌 부분 플래싱을 사용하고자 하여도 리커버리의 fastbootd 또한 망가져 있는 상태이기에 아직은 사용이 불가능하다.
2안의 경우,
- 첫 셋업이 끝나지 않았을 때
- adb wireless 를 prop 설정을 통해 활성화하여
- ᅟadb wireless 를 통해 셋업을 진행한 뒤
- RIDIDeviceManager의 engineering mode 기능을 통해 지속적으로 ADB 를 활성화 시킨다
의 과정을 계획해 볼 수 있다.
Magisk 패칭
ADB Wireless 를 prop 설정을 통해 활성화하기 위해서는, 우리가 지금 사용할 수 있는 유일한 통로인 boot.img 를 통한 코드 주입을 생각해볼 수 있다. 이를 가장 손쉽게 달성하기 위해서는 magisk 를 패치하여, 각 부트 시퀸스를 진행하는 동안 우리가 원하는 단계에서 원하는 코드를 실행하는 것을 생각해볼 수 있다.
이를 위해, Magisk 의 부트 스테이지 관련 코드가 있는 native/src/core/bootstages.cpp 를 수정하여, prop 을 변경해 보도록 하자.
다음과 같은 패치를 사용하여 부트 완료 후 adb wireless 관련 prop 을 설정하자.
diff --git a/native/src/core/bootstages.cpp b/native/src/core/bootstages.cpp index 4a7d56264..264df8fb5 100644 --- a/native/src/core/bootstages.cpp +++ b/native/src/core/bootstages.cpp @@ -456,8 +456,14 @@ void boot_stage_handler(int client, int code) { break; case MainRequest::BOOT_COMPLETE: close(client); - if ((boot_state & FLAG_SAFE_MODE) == 0) + if ((boot_state & FLAG_SAFE_MODE) == 0) { boot_complete(); + setprop("ro.build.type", "eng", true); + setprop("ro.adb.secure", "0", true); + setprop("service.adb.tcp.port", "5555", true); + setprop("sys.usb.config", "adb", true); + setprop("sys.testmode.adb", "start", true); + } break; default: __builtin_unreachable();
이 패치를 적용한 Magisk 를 빌드 후 부팅해 보자.
ADB Wireless 접속
현재 기기의 상태는,
- 첫 기기 설정이 Wi-Fi 세팅을 제외하면 진행되지 않았고
- 커스텀 패치된 Magisk 가 적용된 부트 이미지를 통해 부팅되어
- adb 가 TCP 5555 에서 listening 하고 있는
상태이다. 이제, 호스트에서 기기로 adb connect 후 셸 접속을 해 보자.
$ adb connect xxx.xxx.xxx.xxx:5555 $ adb shell exynos850:/ $
접속에 성공하였다. 이제 빌드한 Magisk.apk 를 설치 후, 루트를 획득해 보자.
$ adb shell exynos850:/ $ su exynos850:/ #
루트 권한 획득에 성공하였다.
보너스 1: 쓸모있게 만들어 보자
리디 페이퍼 4의 안드로이드는 상당히 많이 수정된 안드로이드 10을 사용중이다. 이 커스터마이징에는 대표적으로 다음과 같은 것들이 포함된다:
- 안드로이드 상태바(Status Bar) 에 홈, 뒤로가기, 밝기 설정, 와이파이, 블루투스, 시스템 설정 버튼
- 안드로이드 내비게이션 바의 삭제
- 홈 런쳐 앱의 삭제 (대신 HOME Intent 를 RIDIDeviceManager 가 듣고 있다)
- 개발자 옵션 접근의 삭제
이러한 제약 사항을 이겨내고, 기기를 타사 앱 구동에 쓸 수 있도록 만들기 위해, SystemUI 에 훅을 걸어, 해당 기능 버튼들을 리매핑하기 위한 LSPosed 모듈을 만들 수 있다.
이 과정 자체는 일반적인 SystemUI.apk 를 디컴파일하고, 훅 포인트들을 찾은 뒤, 훅을 심는 방법이므로, 추가적으로 기술하지는 않고, 이를 구현한 프로젝트의 코드로 대체하고자 한다.
https://github.com/perillamint/RP4Posed/
보너스 2: 매직 키 콤보
리디 시스템 프레임워크에는 팩토리 테스트용 매직 키 콤보가 존재한다. 각 키 콤보는 다음과 같다:
- KEYCODE_DEMO_APP_1 (301): 전원 버튼과 페이지 다운을 길게 (5초) 누른다.
- KEYCODE_FEATURED_APP_4 (300): 페이지 다운과 페이지 업을 길게(5초) 누른다
- KEYCODE_F1: 본체 좌측 퀵 버튼
각 키의 역활은 다음과 같다.
- KEYCODE_DEMO_APP_1: 팩토리 리셋 실행
- KEYCODE_FEATUERD_APP_4 이후 KEYCODE_F1: 팩토리 테스트 모드
전원이 꺼진 상태에서의 매직 키는 다음과 같다:
- 페이지 업과 전원 버튼: Fastboot 진입
- 페이지 다운과 전원 버튼: Recovery 진입
감사합니다. 저도 기존 범용리더기를 처분하고 리디페이퍼4 대란에 동참한 1인입니다.
타앱들 쓸 수 있게 되어서 너무 좋네요.
사용하다 한가지 문제점이 있어 혹시 아실까 남깁니다.
블루투스 리모컨을 통해 페이지넘김을 사용하려고 하다 발견한 문제입니다.
본 글 처음의 RP4JailbreakKit 을 사용해 루팅했습니다.
블루투스를 활성화한 상태에서 슬립모드로 빠지면 전원버튼이 더이상 동작하지 않는 문제가 있습니다
(블루투스 설정만 활성화하고 아무 장치도 연결하지 않았을때도 동일하게 문제발생합니다.)
시간 설정에 의해서 슬립모드로 빠지거나, 전원버튼을 눌러서 슬립모드로 빠지거나
어떤 경우에도 그 다음부터는 전원버튼을 통한 화면 켜기가 안됩니다.
전원버튼을 눌러 길게 눌러 종료후 재부팅하고 블루투스를 비활성화하면 정상동작합니다.
어찌어찌하여 루팅까지는 성공했습니다만, 이걸 손볼 능력은 되지 않아 여쭤봅니다.
해결할 방법이 있을까요?
해당 부분 한번 확인해 보겠습니다. 같은 문제를 겪은 적이 있었는데, 블루투스 관련 문제라고는 생각을 못 했었네요 (매번 공초로 해결했었음)
감사합니다
우선 저는 해당문제는 자동화어플(macrodroid)로 스크린오프시 블루투스를꺼지게하고 스크린온시에는 다시 켜지게 설정해서 문제없이 사용하고있습니다
그리고 혹시 이글을 네이버 이북 카페에 링크또는 언급해도 될런지요? 루팅을 기다리시는 분들이 꽤 많아보여요.
카페에 가입되어있는데 혼자만 혜택을 보는것같아 괜히 미안해지네요
정신이 없어서 이제 남기네요.
네, 여기로 링크해도 괜찮습니다. 어느 글인지도 알려주시면 좋구요<
정보공유 감사드립니다.
하지만 이러한 Code 에 문외한으로서 아무리 읽어도 이해가가지 않내요..
초보자도 따라할 수 있는 방법을 알려주시면 감사하겠습니다.
좋은 정보 감사드립니다!
순정 리커버리 진입시 현재 update.zip 펌웨어 플래싱이나, 현재 상태 백업/복원 등이 가능한가요?
혹시 리커버리 부팅을 시도하니 시스템 업데이트중… 만 나오는데 리커버리 진입은 어떻게 할 수 있을까요?
안녕하세요, 바빠서 이제야 보네요.
현재로서는 순정 리커버리에서는 CWM 혹은 TWRP 만큼 자유로운 무언가가 힘든 상황입니다. 더불어, eInk 디스플레이가 변칙적으로 구현되어 있어(유저랜드 앱이 엑시노스 FB 를 USB로 연결된 eInk 에 복사하도록 되어 있음), 단순하게 zImage + DTB 교체만으로 기존 TWRP 를 포팅하는 것도 힘든 상황이고… 추가 작업이 필요합니다.
순정 리커버리에서 할 수 있는 건 저도 리커버리 이미지를 자세히 뜯어보진 않아서 잘은 모르겠네요.
교수님 진도가 빨라요
리디페이퍼4 마개조의 현장.png