기기를 선물로 받았습니다. 나는 새 장치를 받을 때마다 그것을 빠르게 살펴봅니다. 특히 개인적이거나 비즈니스에 중요한 데이터를 초대하는 장치의 경우 더욱 그렇습니다. 이 경우에는 Ratta 회사가 내 데이터를 보호하기 위해 최선을 다할 것이라고 어느 정도 신뢰하지만, (일부) 중국 회사이기 때문에 그들이 할 수 있는 일에는 한계가 있다고 생각합니다. 우리 모두는 중국의 개인 정보 보호 법률 및 규정에 관한 대화를 알고 있습니다. 또한 장치가 중국 본토에 위치한 타사 OEM 제조업체에서 제조되고 있다고 믿을 만한 이유가 있었고 장치에서 또 어떤 일이 일어나고 있는지 알고 싶었습니다.
TL;DR 장치는 여러 공격 벡터를 통해 루팅될 수 있습니다. 소프트웨어 기반뿐만 아니라 하드웨어 기반.
좋은 소식: 장치를 조사한 결과 스파이웨어나 기타 침입 행위와 관련하여 명백하게 손상되는 항목을 찾을 수 없었습니다. 일부 Ratta 앱에는 부분적으로 난독화된 Tencent 구성 요소가 내장되어 있습니다. 장치는 귀하의 원격 측정 설정(Google, Apple 등 참고)을 존중하는 것으로 보이지만 최소한 위치 및 사용 패턴 측면에서 귀하를 추적할 수 있는 업데이트를 매우 정기적으로 확인하고 있습니다. 일부 서버는 분명히 중국에 있으므로 잠재적으로 중국 정부에 공개되어 있습니다. 회사가 주제를 알고 미국에서 서버를 출시하는 것 같습니다. 관점을 바꿔 보면 내장된 Google 또는 Amazon 장치, 널리 사용되는 운영 체제, 스마트폰 또는 인기 있는 소셜 미디어 앱은 제가 여기서 찾은 것보다 더 많은 정보를 수집합니다.
경고: 실제로 이 글을 따르면 기기를 사용할 수 없게 될 가능성이 높으므로 누구에게도 실제로 이 글을 따르라고 조언하지 않습니다. 이것의 대부분은 기억에서 기록됩니다. 내 경우에는 그다지 신뢰할 수 없습니다. 따라서 오류나 누락으로 인해 보증이 무효화되고 장치를 사용할 수 없게 될 위험이 커질 수 있습니다.
2022/08/08 업데이트: 저는 2주 전에 Ratta에게 이 정보를 공개하겠다고 알렸습니다. 예상대로 Ratta는 친절하게 답변하고 문제를 해결하겠다고 약속했습니다. 나는 또한 여기서 CHINA = EVIL을 암시하는 것이 결코 아니라는 점을 지적하고 싶습니다. 나는 내 데이터가 안전하고 비공개로 유지되기를 바라며 중국과 마찬가지로 미국, 유럽, 인도, 러시아 등의 개인 정보 보호 관행에서도 문제가 발생하기를 바랍니다.
위를 참조하세요. 물리적 접근이 가능하다면 이 장치는 매우 민감한 데이터에 대해 안전하다고 간주될 수 없습니다.
오래된 버전의 Android라는 특성과 보안 조치가 부족하다는 점을 감안할 때 어떠한 경우에도 신뢰할 수 없는 당사자에게 내 기기를 제공하지 않을 것입니다. 또한 이러한 공격 중 일부는 완전히 자동화된 방식으로 수행될 수 있으므로 알 수 없는 컴퓨터나 공용 충전 케이블에 연결하지 말라고 조언하고 싶습니다.
나는 보안 담당자가 아닙니다. 이로 인해 공개적으로 사용 가능한 데이터를 수집하는 데 두 주말이 걸렸습니다. 나보다 충분히 의욕이 넘치고 재능이 있는 사람이나 단체라면 누구나 더 빠를 것입니다. 또한 Ratta는 어쨌든 사이드로딩을 허용하고 사전 설치된 su 바이너리, 공개 테스트 키, 개방형 부트 로더, (비활성화됨, 쉽게 잠금 해제됨) adb 콘솔 인터페이스 및 기타 열린 문을 사용하여 장치가 활짝 열리는 것을 볼 수 있다고 약속했기 때문에 이것이 어떤 것도 생성하지 않을 것이라고 가정합니다. 예상치 못한 불편함.
어떤 방식으로든 이 문서는 공개 게시 2주 전인 2022년 7월 27일에 이메일을 통해 Ratta에 제공되었습니다.
아니요. 어떤 경우에도 나는 저작권 등의 보호를 받을 수 있는 파일을 배포하지 않을 것입니다. 당신이 무엇을 하고 있는지 알고 있다면 이 글에는 충분한 정보가 포함되어 있습니다. 그렇지 않은 경우 장치를 그대로 두고 Ratta에게 장치에 대한 쉘/루트 액세스를 요청하세요.
이 글을 쓰는 시점을 기준으로 기기의 통합 '앱 스토어'에서 유일하게 사용할 수 있는 앱인 킨들 앱을 설치하면 제한된 양의 기기 사양을 확인할 수 있습니다. 아니면 OTA update.zip의 압축을 풀면 됩니다.
이 장치는 1,5GHz 쿼드 코어 ARM Cortex-A35, 2GB RAM 및 1404x1872 eink 디스플레이로 구성된 Rockchip PX30 플랫폼에서 Android 8.1을 실행합니다. Rockchip 플랫폼은 사용자 인터페이스와 함께 제공되는 자동차 라디오 및 기타 내장 장치에서 흔히 볼 수 있는 것 같습니다. 따라서 인터넷 검색을 통해 공식 정보와 덜 공식적인 정보를 많이 찾을 수 있습니다.
예: rockchip.fr/PX30%20datasheet%20V1.1.pdf 또는: opensource.rock-chips.com/wiki_Main_Page
reddit에 /r/supernote 및 /r/supernote_beta가 있다는 사실을 고려하면 해당 장치에 대한 베타 프로그램이 존재합니다.
Ratta는 해당 웹사이트와 베타 업데이트 릴리스에 대한 정보를 제공합니다.
현재 비베타 버전은 support.supernote.com/article/3/how-to-update-your-supernote에서 다운로드할 수 있습니다.
베타는 배포가 SupernoteSettings.apk
에서 볼 수 있듯이 장치의 일련 번호에 연결되어 있으므로 현재 설치된 버전과 독립적으로 동일한 서버 및 URL에 연결될 수 없습니다. 자세한 내용은 아래를 참조하세요.
업데이트는 무료로 제공되는 도구를 사용하여 쉽게 압축을 풀고 분석할 수 있는 암호화되지 않은 일반적인 Android OTA 파일입니다. 자세한 내용은 아래를 참조하세요.
압축이 풀린 .br brotli 이미지가 포함된 update.zip:
update.zip:/시스템
장치는 device.supernote.com.cn
의 서버와 협력하여 사용 가능한 새 업데이트가 있는지 확인하여 업데이트합니다.
curl -X POST -k -H 'Content-Type: application/json' -i 'https://device.supernote.com/official/system/business/android/update/download' --data '{"language":"EN", "equipmentNo":"SN100Bxxxxxxxx", "logicVersion":"Chauvet 2.4.15(566)", "configureList":[{"type":"1", "version":"Chauvet.D002.2203101001.566_release"}]}'
오류 메시지는 중국어로 되어 있지만 일반적인 장치에는 업데이트가 필요하지 않습니다 . 일련 번호를 알 수 없습니다 .
업데이트가 가능한 경우 장치는 전체 변경 로그 등과 함께 다운로드 URL을 수신합니다.
{"성공":true,"errorCode":null,"errorMsg":null,"configureList":[{"type":"1","version":"Chauvet.xxxx.xxxxxxxxxx.xxx_xxxxxxx","fileName" :"Chauvet.xxxx.xxxxxxxxxx.xxx_xxxxxxx.zip","이름":null,"패키지 이름":null,"버전 아니요":null,"url":"https://prod-ratta-firmware.s3.ap-northeast-1.amazonaws.com/xxxxxx/update.zip","size":xxxxxxxx,"md5":" abcdefabcdefabcdefabcdef"}],"totalSize":xxxxxxxx,"fixPointList":[{"current":false,"version":"Chauvet xxxx(xxx)","고정점":"
...
","opTime":"xxxx-xx-xx xx:xx:xx"}],"logicVersion":" Chauvet xxxx(xxx)","deployDate":"xxxx-xx-xx xx:xx:xx"}
그런 다음 다운로드되어 복구 시스템으로 전달됩니다.
장치의 /EXPORT/
폴더에 update.zip 파일을 넣고 USB 케이블을 뽑아 수동 업데이트 지침을 따르는 경우에도 마찬가지입니다. 장치는 파일을 발견하고 설치를 계속할지 묻습니다.
정확한 메커니즘은 다음 코드에서 추론할 수 있습니다.
com.ratta.supernote.update.NetWorkConstant
public static final String DEV_BASE_URL = "http://10.20.22.32:9000" ;
public static final String DOWN_LOAD_URL = "" ;
public static final String NET_BASE_URL_PRODUCT = "http://10.20.22.32:8075/" ;
public static final String NET_BASE_URL_TEST = "https://test-ms-device.ratta.com.cn/" ;
public static final String RELEASE_BASE_URL = "https://device.supernote.com.cn/" ;
public static final String UAT_BASE_URL = "https://device.supernote.com" ;
public static final File DOWN_LOAD_PATH = new File ( "/cache" );
public static final String USBDisk_Path = Environment . getExternalStorageDirectory () + File . separator ;
public static final String FILE_TEST = USBDisk_Path + "EXPORT/test" ;
public static final String FILE_PRODUCT = USBDisk_Path + "EXPORT/product" ;
public static final String FILE_UAT = USBDisk_Path + "EXPORT/uat" ;
com.ratta.networklibrary.utils.C0598Utils
String str = Build . DISPLAY ; // i.E. Chauvet.D002.2203101001.566_release
boolean exists = new File ( Constant . FILE_USA ). exists ();
int lastIndexOf = str . lastIndexOf ( "_" );
if ( lastIndexOf != - 1 ) {
String substring = str . substring ( lastIndexOf + 1 );
String str2 = (( TextUtils . equals ( substring , "root" ) || TextUtils . equals ( substring , "hard" )) && exists ) ? Constant . USA_BASE_URL : Constant . RELEASE_BASE_URL ;
if ( new File ( Constant . FILE_TEST ). exists () || TextUtils . equals ( substring , "test" )) {
str2 = exists ? Constant . TEST_USA_BASE_URL : Constant . TEST_BASE_URL ;
} else if ( new File ( Constant . FILE_PRODUCT ). exists ()) {
str2 = Constant . DEV_BASE_URL ;
} else if ( new File ( Constant . FILE_UAT ). exists () || TextUtils . equals ( substring , "uat" )) {
str2 = Constant . UAT_BASE_URL ;
}
if (! TextUtils . equals ( substring , "release" ) && ! TextUtils . equals ( substring , "beta" )) {
return str2 ;
}
if ( exists ) {
return Constant . USA_BASE_URL ;
}
}
return Constant . RELEASE_BASE_URL ;
com.ratta.supernote.update.DownLoadService
@ POST ( "official/system/business/android/update/download" )
Call < DownResponse > downLoadFileInfo ( @ Body RequestBody requestBody );
com.ratta.supernote.update.UpDateAppService
LocalSystemInfoBean localSystemInfoBean = new LocalSystemInfoBean (); // see CURL request above for example values
localSystemInfoBean . setEquipmentNo ( DownPresenter . getDeviceVersion ());
localSystemInfoBean . setLanguage ( DownPresenter . getLanguage ( this ));
localSystemInfoBean . setLogicVersion ( DownPresenter . getLogicVersion ());
localSystemInfoBean . setConfigureList ( DownPresenter . getSystemAllPackageVersion ( this , new ArrayList ()));
RetrofitUtils retrofitUtils = RetrofitUtils . getInstance ();
final DownResponse downResponse = ( DownResponse ) retrofitUtils . execute ((( DownLoadService ) retrofitUtils . getService ( DownLoadService . class )). downLoadFileInfo ( DownLoadModel . getRequestBody ( localSystemInfoBean )));
com.ratta.supernote.update.UpDateAppService
if ( new File ( NetWorkConstant . DOWN_LOAD_PATH , "update.zip" ). exists ()) {
CacheInfoUtils . saveData ( CacheInfoUtils . updateFlagPath , UpDateAppService . USB_UPDATE_FLAG );
RecoverySystem . installPackage ( UpDateAppService . this , new File ( NetWorkConstant . DOWN_LOAD_PATH , "update.zip" )); // if unfamiliar: https://developer.android.com/reference/android/os/RecoverySystem
}
com.ratta.supernote.update.UpDateAppService
private void checkRestartUpdate () {
String str = SystemProperties . get ( ConstanceUtil . restartKey , Constance . FILE_SEVER_UFILE ); // FILE_SEVER_UFILE = "0"; restartKey = "ratta.launcher.restart";
LogUtils . m187d ( "ratta: " + str );
if (! str . equals ( "1" )) {
SystemProperties . set ( ConstanceUtil . restartKey , "1" );
this . firstSelectVersion = true ;
if ( new File ( Environment . getExternalStorageDirectory (). getAbsolutePath () + File . separator + "EXPORT" , "update.zip" ). exists ()) {
this . firstSelectVersion = false ;
usbUpdate ();
return ;
}
LogUtils . m187d ( "checkRestartUpdate: getVersionList" );
getVersionList ();
}
}
public void usbUpdate () {
if ( this . usbUpdateFlag ) {
return ;
}
final File file = new File ( Environment . getExternalStorageDirectory (). getAbsolutePath () + File . separator + "EXPORT" , "update.zip" );
if (! file . exists ()) {
LogUtils . m187d ( "onReceive: No USB upgrade file" );
return ;
}
GestureService . lockStatusbar = true ;
GestureService . lockSlidebar = true ;
this . usbUpdateFlag = true ;
LogUtils . m187d ( "usb update GestureService.lockStatusbar true" );
DialogUtils . getInstance (). build ( this ). createDefaultDelayDialog ( getString ( C0688R . string . usb_detection_tips ), 30 , new LibDialogDelayDefaultListener () { // "The upgrade pack is detected, do you want to install?"
// goes on with housekeeping like removing any existing update.zip and a couple of checks for enough battery etc and then moves the update.zip to /cache as seen above
보시다시피 온전성 검사나 어떤 유형의 암호 해독도 진행되지 않습니다. 따라서 기본적으로 모든 파일을 가져와서 /EXPORT/ 폴더로 옮긴 다음 시스템이 이를 복구에 넘겨주도록 할 수 있습니다.
확인해 본 적은 없지만 코드를 읽으면 USB를 통해 장치를 마음대로 업그레이드 및 다운그레이드할 수 있다고 가정합니다.
표준 Android 복구 메커니즘(저에게는 익숙하지 않음)이기 때문에 파일이 알려진 개인 키로 서명되었는지 확인합니다.
이 장치에는 폐쇄형 ADB 인터페이스가 함께 제공됩니다. 복구 adb reboot recovery
뿐만 아니라 fastboot adb reboot fastboot
또는 부트로더 모드 adb reboot loader
에 넣을 수 있는 adb reboot
명령이 사용됩니다.
복구 모드에서 장치는 루트로 실행되는 셸을 허용합니다. 제한된 명령 세트를 사용할 수 있지만 busybox가 설치되어 있으므로 신경쓰지 마세요. 논리적인 단계는 다음과 같은 스크립트를 작성하여 adb에 대한 전체 액세스를 잠금 해제하는 것입니다.
#! /bin/bash
echo " rebooting to recovery "
adb reboot recovery
ANSWER=0
while [ " $ANSWER " != " 1 " ] ; do
sleep 2
ANSWER= $( adb devices | grep rockchipplatform -c )
done
echo " device online, patching "
adb shell busybox mount -o rw,seclabel,relatime,data=ordered,inode_readahead_blks=8 /dev/block/by-name/system /system
adb shell sed -i " s/ro.debuggable=0/ro.debuggable=1/ " /system/etc/prop.default
echo " rebooting to system "
adb reboot
그 후 장치는 기본적으로 루트로 승격될 수 있는 표준 adb 셸을 통해 완전히 액세스할 수 있습니다.
기술적인 지식이 없는 사용자의 경우: 이는 장치가 기본적으로 모든 파일과 함께 열려 있음을 의미합니다. 의욕이 있는 사용자는 언제든지 USB 액세스가 가능한 장치의 파일을 복사하거나 수정할 수 있습니다.
부트로더가 잠금 해제되어 있으므로 장치를 이 모드로 재부팅하고 fastboot flash boot boot.img
사용하여 언제든지 커널이나 파티션을 플래시할 수 있습니다.
기술적인 지식이 없는 사용자의 경우: 이는 귀하가 눈치채지 못하는 방식으로 장치를 자유롭게 수정하여 귀하의 데이터와 개인정보를 위험에 빠뜨릴 수 있음을 의미합니다.
이 모드에서 장치는 RKDevTool과 같은 Rockchip 개발자 도구에 의해 "LOADER MODE"로 감지됩니다. 여기에서 파티션을 덮어쓸 수 있고 파티션 레이아웃을 변경할 수 있습니다...
...장치를 Maskrom 모드로 전환할 수 있습니다. 이에 대한 자세한 내용은 아래에서 확인하세요.
기술적인 지식이 없는 사용자의 경우: 이는 귀하가 눈치채지 못하는 방식으로 장치를 자유롭게 수정하여 귀하의 데이터와 개인정보를 위험에 빠뜨릴 수 있음을 의미합니다.
/system/build.prop
을 보았을 때 발견했습니다.
ro.build.description=px30_ht_eink-userdebug 8.1.0 OPM8.190505.001 Chauvet.D002.2206171001.629_beta test-keys
ro.build.fingerprint=Android/htfy_px30:/Chauvet.D002.2206171001.629_beta_:userdebug
test-keys
그다지 좋은 신호는 아닙니다. 당신이 개발자라면. 시스템에 활짝 열려 있는 문을 찾고 있다면 이는 아름다운 신호입니다.
Android OTA에 대해 자세히 설명하지는 않지만 여기에서 읽을 수 있습니다.
update.zip: /META-INF/com/android/otacert
를 보면 업데이트에 대한 공개 인증서를 볼 수 있습니다.
-----인증서 시작----
MIID+zCCAuOgAwiBAgIJAJKlKMdz16FBMA0GCSqGSIb3DQEBCwUAMIGUMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4g
VmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEQMA4GA1UE
AwwHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAe
Fw0xNDEyMjMwNjQ0MDhaFw00MjA1MTAwNjQ0MDhaMIGUMQswCQYDVQQGEwJVUzET
MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4G
A1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEQMA4GA1UEAwwHQW5kcm9p
ZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZI
hvcNAQEBBQADggENADCCAQgCggEBALLl71fjESroAzdrkBKrApCrK9qnZfH38S3U3
6jhBOQtrwxnh/AaRC3hOyO5ihjwv1MlSuTA1DygGMznwP8rOQbc9eH4uqdnerE87
v0bc8lPCj22AAterZBZESqgfRwND/25S6A22wA/kpR/CiXMuWHlQfS6Q9CHBOwVQ
5ZZUge2KC1TbH8EtDkxDacOeTbhN6UQxxm3jgaIzkwyrEEcYB1m93CrTFOtVV7Jw
wo7XE5LGwo6nTzNieXJqoYxcNAMpv9seKW+GZ1EGl78e9B37SMoxq0I7HuStz5tD
tS2Er2YrjQig+1ZqgroIvPfEJAEyoEr0r6kK7jBh878usWOuWB0CAQOJUUDBOMB0G
A1UdDgQWBBTV37ltjiIiA28uNs8Z1hb6zasy5UzAfBgNVHSMEGDAWgBTV37ltjiIA
28uNs8Z1hb6zasy5UzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAZ
7pvK3yDr+O0G8ggDfaISkEeg0agocRcXGT/MRiPBz+n45+bEoym4hC2SdCxvHXES
5AHkFxjWavoQqAD8We955NCmpGzDip4hUctlXzqxYfSTvGiLArG92+Hcbu5RNx/7
o3Of39Mdge2jVKQuKAALWnb8TgJ/2k3KAUFzVqMXPY4asmnWtyW2FIKLdZU/yYTX
+8Tp0AhP+N84HUGg5BwQRD10/OGGY54rLfFy2aSLPxUZQ+VTSZB9Z9XRLxohsF/V
XBcZyCdPP254wDYL5R0HGWZv7CeBlVjw3FqDRI9aljdYfLpAk+clnRBwWOWHsiOE
pJXgkkLmpq0uDXsSMJZ2
-----인증서 종료----
인증서의 일부를 인터넷 검색하면 누군가가 Android 8.1 Rockchip PX5 장치에 들어가려고 하는 xda-developers.com에서 하나 이상의 결과가 나옵니다.
그것은 더욱 나쁜 징조입니다. 아니면 나에게 더 아름다운 것.
다음으로 PX30 플랫폼 관련 SDK를 검색하여 여기에서 찾았습니다.
en.t-firefly.com/doc/download/page/id/63.html#other_206
여기에 문서와 함께:
wiki.t-firefly.com/en/Core-PX30-JD4/Android_development.html
그리고 여기:
wiki.t-firefly.com/en/Firefly-RK3399/customize_android_firmware.html
SDK를 다운로드하면 7z 아카이브의 압축을 풀고 다음을 통해 포함된 git 저장소를 초기화할 수 있습니다.
git clone PX30_Android8.1.0_LVDS_190706 directory_to_clone_into
오랜 시간 동안 복제한 후 /build/make/target/product/security
에서 SDK 테스트 키를 찾으면 됩니다.
재미있는 사실: 해당 폴더의 README에는 다음과 같은 내용이 나와 있습니다.
이 디렉터리의 테스트 키는 개발에만 사용되며 공개적으로 출시된 이미지의 패키지에 서명하는 데 절대 사용해서는 안 됩니다(이렇게 하면 주요 보안 허점이 열릴 수 있음).
응, 확인됐어.
기술은 여러분에게 맡깁니다. Windows에서 작업하는 동안 저는 Multi Image Kitchen을 사용하여 Android OTA의 포장을 풀고 다시 포장하고 서명합니다. testkey.x509.pem
및 testkey.pk8
도구의 bin
폴더로 이동해야 하며 거기서부터 수정된 업데이트를 생성할 수 있습니다. 장치를 EXPORT 폴더에 배치하면 장치를 설치할 수밖에 없습니다. .
글쎄요.
여기에서 수행하는 모든 작업은 오류가 발생하고 장치가 소프트 브릭화되기 쉽습니다. 내가 아는 한 모든 Rockchip 장치는 기본적으로 개방형 프로그래밍 인터페이스인 마스크롬 모드를 항상 제공하기 때문에 완전히 소프트 브릭으로 구성될 수 없습니다.
일반적으로 이 인터페이스는 CPU의 두 핀을 단락시켜 액세스할 수 있습니다. 이는 Supernote에서도 작동하지만 장치를 열면 남은 보증이 무효화될 가능성이 높습니다.
PX30 마스크롬에 대한 모든 정보와 장치 복구 방법은 아래를 참조하세요.
루트 adb 셸의 모든 파티션을 백업합니다.
adb shell
예를 들어 다음 명령을 실행하여:
cat /dev/block/mmcblk1p1 > /sdcard/EXPORT/uboot.img
cat /dev/block/mmcblk1p2 > /sdcard/EXPORT/trust.img
cat /dev/block/mmcblk1p3 > /sdcard/EXPORT/misc.img
cat /dev/block/mmcblk1p4 > /sdcard/EXPORT/resource.img
cat /dev/block/mmcblk1p5 > /sdcard/EXPORT/kernel.img
cat /dev/block/mmcblk1p6 > /sdcard/EXPORT/boot.img
cat /dev/block/mmcblk1p7 > /sdcard/EXPORT/recovery.img
cat /dev/block/mmcblk1p8 > /sdcard/EXPORT/backup.img
cat /dev/block/mmcblk1p9 > /sdcard/EXPORT/security.img
cat /dev/block/mmcblk1p10 > /sdcard/EXPORT/cache.img
cat /dev/block/mmcblk1p11 > /sdcard/EXPORT/system.img
cat /dev/block/mmcblk1p12 > /sdcard/EXPORT/metadata.img
cat /dev/block/mmcblk1p13 > /sdcard/EXPORT/vendor.img
cat /dev/block/mmcblk1p14 > /sdcard/EXPORT/oem.img
cat /dev/block/mmcblk1p15 > /sdcard/EXPORT/frp.img
잠재적으로 사용자 데이터를 저장할 수도 있습니다.
dd if=/dev/block/by-name/userdata bs=4096 count=1048576 of=/sdcard/EXPORT/userdata-1.img
dd if=/dev/block/by-name/userdata bs=4096 skip=1048576 count=1048576 of=/sdcard/EXPORT/userdata-2.img
dd if=/dev/block/by-name/userdata bs=4096 skip=2097152 count=1048576 of=/sdcard/EXPORT/userdata-3.img
dd if=/dev/block/by-name/userdata bs=4096 skip=3145728 count=1048576 of=/sdcard/EXPORT/userdata-4.img
dd if=/dev/block/by-name/userdata bs=4096 skip=4194304 count=1048576 of=/sdcard/EXPORT/userdata-5.img
dd if=/dev/block/by-name/userdata bs=4096 skip=5242880 count=1048576 of=/sdcard/EXPORT/userdata-6.img
backup -> /dev/block/mmcblk1p8
boot -> /dev/block/mmcblk1p6
cache -> /dev/block/mmcblk1p10
frp -> /dev/block/mmcblk1p15
kernel -> /dev/block/mmcblk1p5
metadata -> /dev/block/mmcblk1p12
misc -> /dev/block/mmcblk1p3
oem -> /dev/block/mmcblk1p14
recovery -> /dev/block/mmcblk1p7
resource -> /dev/block/mmcblk1p4
security -> /dev/block/mmcblk1p9
system -> /dev/block/mmcblk1p11
trust -> /dev/block/mmcblk1p2
uboot -> /dev/block/mmcblk1p1
userdata -> /dev/block/mmcblk1p16
vendor -> /dev/block/mmcblk1p13
rootfs / rootfs ro,seclabel,size=981980k,nr_inodes=245495 0 0
/dev/block/by-name/system /system ext4 ro,seclabel,relatime,data=ordered,inode_readahead_blks=8 0 0
/dev/block/by-name/vendor /vendor ext4 ro,seclabel,relatime,data=ordered,inode_readahead_blks=8 0 0
/dev/block/by-name/oem /oem ext4 ro,seclabel,noatime,nodiratime,block_validity,delalloc,barrier,noauto_da_alloc,user_xattr 0 0
/dev/block/by-name/cache /cache ext4 rw,seclabel,nosuid,nodev,noatime,nodiratime,discard,noauto_da_alloc,data=ordered 0 0
/dev/block/by-name/metadata /metadata ext4 rw,seclabel,nosuid,nodev,noatime,nodiratime,discard,noauto_da_alloc,data=ordered 0 0
/dev/block/by-name/userdata /data f2fs rw,lazytime,seclabel,nosuid,nodev,noatime,nodiratime,background_gc=on,discard,no_heap,user_xattr,inline_xattr,inline_data,inline_dentry,flush_merge,extent_cache,mode=adaptive,active_logs=6,alloc_mode=default,fsync_mode=posix 0 0
tmpfs /storage tmpfs rw,seclabel,relatime,mode=755,gid=1000 0 0
adb /dev/usb-ffs/adb functionfs rw,relatime 0 0
/data/media /mnt/runtime/default/emulated sdcardfs rw,nosuid,nodev,noexec,noatime,fsuid=1023,fsgid=1023,gid=1015,multiuser,mask=6,derive_gid 0 0
/data/media /storage/emulated sdcardfs rw,nosuid,nodev,noexec,noatime,fsuid=1023,fsgid=1023,gid=1015,multiuser,mask=6,derive_gid 0 0
/data/media /mnt/runtime/read/emulated sdcardfs rw,nosuid,nodev,noexec,noatime,fsuid=1023,fsgid=1023,gid=9997,multiuser,mask=23,derive_gid 0 0
/data/media /mnt/runtime/write/emulated sdcardfs rw,nosuid,nodev,noexec,noatime,fsuid=1023,fsgid=1023,gid=9997,multiuser,mask=7,derive_gid 0 0
내 장치에 있는 업데이트에는 이미 su 바이너리와 루트 adb 인터페이스에 쉽게 액세스할 수 있는 많은 바로가기가 함께 제공되었습니다.
제가 실험한 몇 가지 수정 사항은 다음과 같습니다.
/system/etc/prop.default
security.perf_harden=0
ro.debuggable=1
sys.rkadb.root=1
ro.debug.build=true
ro.oem_unlock_supported=1
ro.secure=0
ro.adb.secure=0
persist.sys.usb.config=mtp,adb
그 동안 매우 빈번한 업데이트 확인과 선택적 원격 측정을 차단했습니다(내장된 App Store도 차단했지만 이제 앱을 기기에 사이드로드할 수 있으므로 이는 거의 쓸모가 없습니다).
/시스템/등/호스트
127.0.0.1 device.supernote.com.cn
127.0.0.1 supernote.com.cn
127.0.0.1 www.supernote.com.cn
127.0.0.1 device.supernote.com
127.0.0.1 supernote.com
127.0.0.1 www.supernote.com
127.0.0.1 test-ms-device.ratta.com.cn
127.0.0.1 uat-ms-device.ratta.com.cn
127.0.0.1 ratta.com.cn
여기에서 작동하는 루트 adb 인터페이스가 있으며, mount -o remount,rw /system
실행한 후 앱을 사이드로드하고 원하는 대로 /system을 완전히 수정할 수 있습니다.
그 후 제가 한 첫 번째 단계는 제대로 작동하는 SuperSU 시스템 기반 루트 솔루션을 설치하는 것이었습니다. 이를 위해 최신 supersu.zip을 다운로드하고 압축을 푼 다음 설치 스크립트를 살펴보고 매우 해키적인 방식으로 수동으로 파일을 배치했습니다.
/system/.ext/.su # useless I think? Didn't bother to understand
/system/xbin/daemonsu
/system/xbin/su
/system/xbin/sugote
/system/xbin/sugote-mksh
/system/xbin/supolicy
/system/lib64/libsupol.so
/system/app/SuperSU/SuperSU.apk
그리고 /system/bin/install-recovery.sh
다음으로 끝나도록 수정하세요.
/system/xbin/daemonsu --auto-daemon &
/system/etc/install-recovery-2.sh
그런 다음 system_file_contexts.txt
를 수정하여 파일 컨텍스트와 액세스 권한을 수정합니다.
/system/app/SuperSU/SuperSU.apk u:object_r:system_file:s0
/system/xbin/su u:object_r:system_file:s0
/system/bin/.ext/.su u:object_r:system_file:s0
/system/xbin/daemonsu u:object_r:system_file:s0
/system/xbin/sugote u:object_r:zygote_exec:s0
/system/xbin/supolicy u:object_r:system_file:s0
/system/lib64/libsupol.so u:object_r:system_file:s0
/system/xbin/sugote-mksh u:object_r:system_file:s0
system_fs_config.txt
는 다음으로 끝납니다.
system/app/SuperSU 0 0 0755
system/app/SuperSU/SuperSU.apk 0 0 0644
system/xbin/su 0 2000 0755
system/bin/.ext 0 2000 0755
system/bin/.ext/.su 0 2000 0755
system/xbin/daemonsu 0 2000 0755
system/xbin/sugote 0 2000 0755
system/xbin/supolicy 0 2000 0755
system/lib64/libsupol.so 0 0 0644
system/xbin/sugote-mksh 0 2000 0755
완벽하게 잘 작동했습니다.
빠른 스크립트를 구현하는 것은 간단했지만 이 시점에서는 Android 루트에 들어가고 있었고 내 계획은 적절한 magisk 시스템리스 루트를 설치하는 것이었습니다.
Magisk는 수정되지 않은 boot.img를 공급하여 사전 수정된 "루팅된" boot.img 커널과 램디스크를 생성할 수 있습니다.
update.zip
의 루트에서 boot.img
가져와서 /storage/emulated/0/Download
에 복사하세요.
다음과 같이 최신 Magisk를 사이드로드하세요.
adb install Magisk-v25.x.apk
기기에서 Settings > Apps > My apps
으로 이동하여 시스템이 앱 목록을 새로 고치고 사이드바에 Magisk를 추가하도록 합니다. 런처 UI는 분명히 많은 앱을 사용하는 사람들을 위해 만들어지지 않았기 때문에 이를 찾으려면 거기로 스크롤해야 할 수도 있습니다.
Magisk에서 패치할 파일을 선택하기 전에 무료이고 매우 편리하기 때문에 Total Commander(다운로드)로 선택한 DocumentProvider를 설치해야 했습니다. 다음을 사이드로드했습니다.
adb install tcandroidxxxx-universal.apk
사이드바에 표시되도록 하려면 위와 동일한 작업을 수행합니다. 그것을 열고 오른쪽 상단을 맹목적으로 탭하여 "빈" 메뉴를 엽니다. 여기서 두 번째 마지막 항목을 탭하여 어두운 테마에서 밝은 테마로 전환하여 마침내 모든 것을 제대로 볼 수 있습니다.
Magisk를 열고(루트 액세스 권한 부여) 업데이트를 누르고 모든 것을 그대로 두고 다음을 누르고 "파일 선택 및 패치"를 누르고 공급자로 Total Commander(url...)를 선택한 다음 boot.img를 선택합니다.
결과 magisk_patched-xxx.img
기본 작업 폴더인 /storage/emulated/0/Download
에서 다시 컴퓨터로 복사합니다.
장치 부팅에서 fastboot로:
adb reboot fastboot
표준을 발행합니다.
fastboot flash boot magisk_patched-xxx.img
그리고
fastboot reboot
모든 것이 순조롭게 진행되면 장치가 시스템으로 부팅되고 magisk를 열 수 있으며 Ramdisk와 함께 설치된 버전이 보고됩니다: yes . 이전에 SuperSU를 설치했거나 사전 설치된 su 바이너리를 제거하지 않은 경우 설치가 손상되었음을 경고하고 이전 루트를 제거하라는 메시지가 표시됩니다. 추가한 모든 파일을 제거하거나 사전 설치된 su
및 libsupol.so
만 제거하면 됩니다.
슈퍼유저에게 작업이 제대로 작동하는지 확인하도록 요청하는 앱을 열고 익숙한 슈퍼유저 프롬프트가 표시됩니다.
v1.0.1(077)로 돌아가는 이전 펌웨어 파일 목록을 정리했습니다.
시간이 나면 완료하도록 하겠습니다.
장치에 무슨 일이 발생하면 장치를 열고 CPU에서 차폐를 제거한 후 전원 스위치 옆에 있는 재설정 스위치를 누른 상태에서 다음 두 핀 헤더를 단락시키십시오.
이렇게 하면 장치가 마스크롬 모드로 전환됩니다. 장치를 정확하게 복구하는 방법에 대해 자세히 설명하지는 않지만 가장 관련성이 높은 정보와 장치를 수정하기 전에 모든 파티션을 백업하라는 조언을 남겨드리겠습니다.
다음으로 마스크롬 드라이버를 설치합니다(Windows에서 서명되지 않은 드라이버를 활성화한 다음 RKImageMaker
및 AFPTool
과 같은 도구를 사용하여 마스크롬의 RKDevTool(여기에서)을 통해 플래시할 수 있는 update.img를 생성합니다. RKDevTool에는 위에서 언급한 두 가지 바이너리가 포함되어 있습니다. 업데이트 패키지.
RKDevTool은 기본적으로 중국어로 제공되며 .ini를 사용하여 끌 수 있는 펌웨어에 대한 다소 쓸모없는 유효성 검사가 포함되어 있습니다.
[Language]
Selected=2
그리고
FW_NOT_CHECK=TRUE
RB_CHECK_OFF=TRUE
CHECK_MACHINE_MODEL=FALSE
Rockchip SDK와 툴링 환경이 극도로 단편화되어 있기 때문에 프로세스를 알아내는 것은 재미있는 경험이었습니다.
이 파일은 완전한 update.img에 필요합니다. 위에서 언급한 SDK 또는 인터넷 검색의 일부와 파티션 백업과 같은 위치에서 소스를 소싱할 수 있습니다.
krnl 파일은 imgRePackerRK(다운로드)라는 도구를 사용하여 원시 .img 파일을 Rockchip 호환 형식(.img.krnl)으로 변환하는 도구 체인을 만들었기 때문에 거기에 있습니다.
이 도구는 RKImageMaker 및 AFPTool을 대체하기 위해 만들어진 것으로 보이며 Rockchip update.img를 생성하는 올인원 솔루션입니다. 그러나 그것은 나에게 일관된 결과를 가져오지 못할 것입니다.
그러나 Rockchip 복구와 호환되는 커널, 부팅 및 복구 이미지를 변환합니다.
Imageboot.img.krnl 대 Imageboot.img
그래서 저는 이를 사용하여 .krnl 파일을 편리하게 생성한 다음, .krnl 파일과 함께 원본 .img 파일을 유지하면서 내 toolchain.bat를 실행하여 작동하는 update.img를 빌드합니다.
move Imageboot.img Imageboot.img.tmp
move Imagerecovery.img Imagerecovery.img.tmp
move Imagekernel.img Imagekernel.img.tmp
move Imageboot.img.krnl Imageboot.img
move Imagerecovery.img.krnl Imagerecovery.img
move Imagekernel.img.krnl Imagekernel.img
copy Imageparameter.txt .parameter
Afptool -pack ./ Imagetmp-update.img
RKImageMaker.exe -RKPX30 ImageMiniLoaderAll.bin Imagetmp-update.img update.img -os_type:androidos
move Imageboot.img Imageboot.img.krnl
move Imagerecovery.img Imagerecovery.img.krnl
move Imagekernel.img Imagekernel.img.krnl
move Imageboot.img.tmp Imageboot.img
move Imagerecovery.img.tmp Imagerecovery.img
move Imagekernel.img.tmp Imagekernel.img
del Imagetmp-update.img
pause
이 과정에서 도움을 주기 위해 호환되는 /Image/parameter.txt
도 있습니다.