三天前,同事拿来了一个定制过的平板,问我能不能自己装个应用上去,我心想这能有多难,就接过来了。
第一天,设备上手
拿到手点了一会儿,发现是个叫天奇健教育培训机构给学生定制的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,就找到了这种配置文件:
- partition_index: SYS0
partition_name: preloader
file_name: preloader_keytak6580_weg_n.bin
is_download: true
type: SV5_BL_BIN
linear_start_addr: 0x0
physical_start_addr: 0x0
partition_size: 0x400000
region: EMMC_BOOT_1
storage: HW_STORAGE_EMMC
boundary_check: true
is_reserved: false
operation_type: BOOTLOADERS
reserve: 0x00
- partition_index: SYS1
partition_name: pgpt
file_name: NONE
is_download: false
type: NORMAL_ROM
linear_start_addr: 0x0
physical_start_addr: 0x0
partition_size: 0x80000
region: EMMC_USER
storage: HW_STORAGE_EMMC
boundary_check: true
is_reserved: false
operation_type: INVISIBLE
reserve: 0x00
......
- partition_index: SYS8
partition_name: boot
file_name: boot.img
is_download: true
type: NORMAL_ROM
linear_start_addr: 0x1D20000
physical_start_addr: 0x1D20000
partition_size: 0x1000000
region: EMMC_USER
storage: HW_STORAGE_EMMC
boundary_check: true
is_reserved: false
operation_type: UPDATE
reserve: 0x00
配置文件和手里的设备难免有差,只能作为一个参考。系统一般会分成三个大区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的部分,里面有磁盘分区表,可以根据这个自己计算偏移。分区表的开头大概长这个样子:
00000200h: 45 46 49 20 50 41 52 54 00 00 01 00 5C 00 00 00 ; EFI PART....\...
00000210h: 18 37 4C D9 00 00 00 00 01 00 00 00 00 00 00 00 ; .7L?...........
00000220h: FF 7F CE 01 00 00 00 00 00 04 00 00 00 00 00 00 ; ?............
00000230h: FF 7B CE 01 00 00 00 00 00 00 00 00 00 00 00 00 ; {?............
00000240h: 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 ; ................
继续往后找就看到各个分区的说明字段了,其中boot分区开始sector是0xF600,sector结束位置是0x175FF:
00000700h: A2 A0 D0 EB E5 B9 33 44 87 C0 68 B6 B7 26 99 C7 ; 须骞3D嚴h斗&櫱
00000710h: 39 09 9B 1F 6B E1 C9 4B A5 BC DC 2E E9 69 D8 01 ; 9.?k嵘Kゼ?閕?
00000720h:[00 F6 00 00]00 00 00 00[FF 75 01 00]00 00 00 00 ; .?.....u......
00000730h: 00 00 00 00 00 00 00 00 62 00 6F 00 6F 00 74 00 ; ........b.o.o.t.
00000740h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000750h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000760h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000770h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000780h: A2 A0 D0 EB E5 B9 33 44 87 C0 68 B6 B7 26 99 C7 ; 须骞3D嚴h斗&櫱
00000790h: 21 C7 22 D7 EE 0D B8 4C 8A 83 2C 63 CD 13 93 C7 ; !?最.窵妰,c?撉
000007a0h: 00 76 01 00 00 00 00 00 FF F5 01 00 00 00 00 00 ; .v......?.....
000007b0h: 00 00 00 00 00 00 00 00 72 00 65 00 63 00 6F 00 ; ........r.e.c.o.
000007c0h: 76 00 65 00 72 00 79 00 00 00 00 00 00 00 00 00 ; v.e.r.y.........
000007d0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000007e0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000007f0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
每个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:
sepolicy-inject -Z adbd -P rout/ramdisk/sepolicy -o rout/ramdisk/sepolicy
sepolicy-inject -Z shell -P rout/ramdisk/sepolicy -o rout/ramdisk/sepolicy
sepolicy-inject -Z init -P rout/ramdisk/sepolicy -o rout/ramdisk/sepolicy
sepolicy-inject -Z recovery -P rout/ramdisk/sepolicy -o rout/ramdisk/sepolicy
重打包的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里给删除了,再后面就随意发挥了。
原文作者:txstc
原文链接:https://bbs.pediy.com/thread-249739.htm
转载请注明:转自看雪学院
更多阅读:
简单分析南邮实训平台pwn方向第二题 - Stack Overflow
XCTF 攻防世界 reverse 萌新入坑 alexctf-2017 re2-cpp-is-awesome writeup
Android ART invoke 代码生成
bugku新平台 baby_reverse wirteup