转自:https://bbs.pediy.com/thread-249739.htm
https://github.com/CyanogenMod
https://github.com/CyanogenMod/android_packages_apps_Calculator
三天前,同事拿来了一个定制过的平板,问我能不能自己装个应用上去,我心想这能有多难,就接过来了
第一天,设备上手
拿到手点了一会儿,发现是个叫天奇健教育培训机构给学生定制的PAD(提分派)。它自己开发的桌面,上面只显示学习相关的应用(背单词,答题,校园通知相关的东西)。桌面上唯一一个和Android相关的就是系统设置,点开发现也裁掉了绝大部分功能。除了WIFI设置和关于设备以外几乎没有其他选项,而关于设备里面反复点击版本,即便提示开发者模式已经打开,实际也看不到这个菜单。 看来定制的思路完全就是怕学生拿PAD玩耍而不是学习。
平板用的是MTK的MT6580的芯片,设备名字叫k960N_MT6580_32_N,Android 7,内核3.18.35+,连淘宝上都没得卖,只有aliexpress上有个链接,估计是个贴牌机之类的产品。自带的应用都是连接校园内网才能使用,看了一圈也没发现什么一下就能实现下载安装的功能(实在不想花时间琢磨这些应用了)。
试了一会儿发现设备开关和音量上组合可以进bootloader模式,并且fastboot oem unlock竟然能解锁。首先想到的是通过解锁,设备肯定会重置用户数据,也许这个定制的桌面就跟着被删除了。要是回到Android原生的桌面,就有转机了。遗憾的是,重置以后桌面还在,只是应用少了很多。这个桌面应该是把原生桌面直接从/system/app替换了。
不过bootloader已经解锁了,按说现在的权限已经可以改分区,替换掉它这些自定义的东西了。但麻烦在于,这么个无名无姓的平板,无论是源码还是官方固件,网上搜不到任何信息,没有东西让你能替进去的。索性还是下载了一些其他MT6580芯片设备的ROM或者TWRP,挨个尝试fastboot boot xxx.img,看能不能有个奇迹,要的不多,只要不崩,系统能启动。这样好歹能有个img开始改起啊。第一天就在试来试去中度过了,发现非Android 7的boot.img和recovery.img,导致的都是快速重启,Android 7的的img则是启动后卡顿十几秒后重启。
第二天,读取分区
boot.img和recovery.img还是挺娇气的,稍微有点差异就不能正常引导系统,还是得想办法把PAD里的原始镜像DUMP出来自行修改。
搜到MTK芯片有个模式叫MTK Preloader(工厂刷机模式),工厂量产设备时用它可以快速刷写系统,配套的工具叫SP Flash Tool,基本被用来救砖。这种工厂刷机模式非常类似高通的QPST(9008模式),都是由固化在芯片里率先启动的bootrom提供的功能。由于bootrom没法篡改,系统总能黑砖下起死回生。
进入这种模式时差不多都是组合键或者直接短接SOC上的特定触点,手机启动后就会开启一个串口。然后PC端按照约定协议,发送一个用于继续执行的第2阶段的程序文件过去(高通叫prog_emmc_xxx.mdn,MTK一般是MTK_AllInOne_DA.bin)。接下来这个二进制程序会开始执行,并且继续和PC通信,实现改写分区的任务。
SP Flash Tool就是PC端用于和进入这种模式的MTK设备通信的软件,相比高通设备要四处寻找prog_emmc文件不同,MTK设备有个比较通用的 MTK_AllInOne_DA.bin文件作为第二阶段的代码。工厂模式除了可以刷写分区,还能读取分区内容回传。
一般使用这种模式时,读写分区要有个配置文件MT6580_Android_scatter.txt,里面用于配置各个分区所在的磁盘偏移,这样软件才知道你要读的分区究竟在哪。随手打开了一个之前下载的MT6580设备的ROM,就找到了这种配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
|
配置文件和手里的设备难免有差,只能作为一个参考。系统一般会分成三个大区EMMC_BOOT_1, EMMC_BOOT_2, EMMC_USER。 我们关心的boot.img位于EMMC_USER分区,至于是不是从0x1D200000开始就不好说了。
一般进入这种刷机模式,需要把电池扣下来,让设备完全断电,然后再把电池放回去,这时插上USB线后就能检测到串口了。软件必须提前执行读或者写的指令,因为该模式可能只有几秒钟的时间窗,窗内没有收到第二阶段的文件就逾期不候了。麻烦又开始了,这个PAD拆开后盖看,电池是焊在板子上的,哪有电池让我扣啊。实在不得已,只能把红色VCC的电源线线焊下来了。
每次进入这种模式时的步骤就变成了:右手食指把红线压回原触点,左手迅速把USB线插入。
经过一段时间的练习,我已经可以大概率地进入工厂刷机状态了。接下来,软件上配置好READ BACK,点击按钮,然后进行左右手互搏后,就完成了一次分区读取。显然,按照之前的剧本惯性来看,仍然没有那么顺利,从 0x1D200000读取回来的果然不是boot.img
于是干脆读了EMMC_USER分区开头0地址开始,长度0x1000的部分,里面有磁盘分区表,可以根据这个自己计算偏移。分区表的开头大概长这个样子:
1 2 3 4 5 |
|
继续往后找就看到各个分区的说明字段了,其中boot分区开始sector是0xF600,sector结束位置是0x175FF
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
每个sector能存放512字节,所以改写成SP Flash Tool的格式就是:
Start Address: 0xF600 * 512 = 0x1EC00000
Length: 512 * (0x175FF - 0xF600 + 1) = 0x1000000
第二天最后一次左右互搏后,拿到了PAD的boot.img和recovery.img,fastboot boot xxx.img试了一下,可以正常启动
第三天,改分区
现在有了boot.img和recovery.img的镜像,可以动手修改再fastboot flash boot xxx.img刷回了,目的就是让启动后的系统开放一些,比如增加个ADB ROOT。
下面的步骤多少稍微绕了点弯路,主要原因是硬刚boot.img没刚过(无论如何都没法通过修改init.xxx.rc实现开机启动ADB)。
修改img用的工具是mkbootimg_tools,先修改recovery.img:
在/default.prop增加ro.debuggable=1,这样进入recovery后会启动adb;
接下载再patch位于/sbin的adbd,具体就是把drop_privileges函数里执行的东西一个大B跳过,这样ADB就不降权了;
考虑到selinux的限制,不降权的ADB也许没法正常运行,就把/sepolicy也修改一下。
用到sepolicy_inject(附件是用cygwin编译的sepolicy_inject),把可能惹麻烦的域都改成permissive:
1 2 3 4 |
|
重打包的recovery启动后就带ADB ROOT了,不过只能push和pull,因为/system/bin/sh并不存在,如果recovery像我一样刚好带了挂载/system的功能,可以挂载后再执行adb shell。或者找个类似设备,把/system/bin和/system/lib拷贝一份,手动adb push上去也可以。
利用这个高权限接口,把自己的应用传到/data/app下,再重启进入主系统,应用就会自动安装。不过Android 6开始,即便APK带有android.permission.RECEIVE_BOOT_COMPLETED权限,如果从来没有没有被打开过,也是不会开机启动的(它自定义的桌面不显示我们装的应用,所以没法点击打开)。
所以我在/data/app放了两个应用,其中一个是第三方Launcher,装好后再按home键就会弹出选项,启动自定义的Launcher。另一个放在/data/app下的应用就会在第三方桌面下显示了,而他里面就一行代码,用于启动com.android.settings.developmentsettings,为的就是在图形界面下把usb调试打开。
所以,以上繁琐的步骤,其实只为了打开usb调试而已。
最后,然后再把boot.img里的adbd也修改一下,重启就有了ADB ROOT。看/mt6580.fstab知道设备本身没开dm-verity,干脆把它的桌面从/system里给删除了,再后面就随意发挥了