黑盒到灰盒再到PWN - 分析某智慧课堂平板

starryloki 2021-11-17 09:41:00

0x00 概述

一部分学校采用智慧课堂教学,所谓智慧课堂就是使用一台安卓平板加以娱乐功能的限制,并集成可以与教师互动的相关软件。这些平板往往由多家公司合作,比如某创公司负责定制Android以及开发MDM等功能,某飞公司负责开发定制的教育APP以及与学校对接。

0x01 环境

拿到平板之后简单观察了一下,大概可以总结出以下几点:

  • 平板采用高度定制的Android 7.1.1
  • 存在网络防火墙,仅允许白名单内的IP或域名通过,没有限制10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
  • Bootloader可被解锁
  • 存在一个“管理员设置”并有密码保护,密码可能随云端更新

管理员设置

接下来就可以开始折腾了。

0x02 黑盒测试

要想解除限制,我们必须要知道限制是如何产生的。而我们现在很难获取任何信息,需要获得更多细节(相关apk或framework用于逆向分析)。

目标明确后就能规划方法了,大概规划了几个方法来获取相关文件:

  • 使用adb直接获取
  • 进入boot loader&recovery获取相关文件
  • 摘下EMMC直接读取文件

很遗憾这两种方法都行不通,系统将外接USB设备设为仅充电,并且禁用了物理按键进入bootloader&recovery的接口。这么一来看似行不通了,但是又极其偶然地发现了一个Bug。

Android系统的启动可以简单分为以下几个流程:

Android Boot Flow

而adb的守护进程adbd则是在Start System Services阶段启动,启动完成后才进入Start Home Activity,也就是在这两个阶段之间,可以短暂地进入平板的adb,随后很快就被禁用。

这个现象非常奇怪,启动时可以无授权进入adb多见于以eng编译的Android。Android的编译选项有三种:eng、userDebug和user,我们常见的系统固件都是user或userDebug,前者需要在开发者选项中手动开启USB调试,后者则默认开启USB调试但是全程都需要信任的设备才能操作。而eng就特殊多了,在启动时可以无须授权进入adb,多用于抓取启动时的日志。而eng也是类似userDebug,默认开启adb,结合adb很快被禁用这一点我们可以推断adb是在后期被禁用了。

由于这时候Package Management Service并未加载,所以无法用过adb来dump相关apk,但是不要紧,可以直接执行adb reboot bootloader进入bootloader,再解除BL锁刷入第三方Recovery,再通过第三方Recovery dump整个系统。

0x03 灰盒分析

Dump系统后就可以进行分析了,初步分析可以得到下面的概览:

image-20211110014215515

平板跑着定制的Android 7.1.1,并由某创公司开发的平板管理软件作为桌面 (com.android.launcher3),其中包含用户登陆,桌面以及管理员设置等功能,而里面跑的教育类APP则由其他厂商开发(比如某飞)。

尝试进入管理员设置

既然管理员设置在某平板管理里面,那我们就先分析这个apk。用JEB打开apk,很快就能定位到管理员登录的Activity(LoginActivity)并找到登录逻辑:

Login Activity

可以发现管理员密码可以用sPFTool.getString("password2","")读取,在没有办法安装第三方插件进行Hook的情况下,我们只能在源代码里面找有没有写入默认密码的逻辑,于是搜索password2,很快就在GuardSecureApplication这个类里面找到了相关方法:

Init Password

但是手上的平板已经联网同步过新密码了,于是再次用adb进入bootloader,恢复出厂设置后开机,在不联网的情况下打开管理员设置,用admin,xunfei!!@成功进入了管理员设置:

admin

这里唯一有用的是USB连接电脑的开关,解除限制按钮后期的逆向发现是解除服务端对平板的限制而非功能限制。

尝试安装应用

打开了USB连接电脑并链接电脑后,平板出现了USB调试对话框,于是使用adb安装第三方应用,提示没有权限安装应用,,原来平板存在应用白名单限制,这里可能的白名单方法有签名+包名包名检测,如果平板采用的是签名+包名那么难度会进一步加大,我们先尝试一下修改包名。

我们使用adb shell pm list packages列出包名,可以得到一些非系统的白名单内应用,再使用mt管理器将要安装apk包名修改成白名单内的非系统应用,再执行adb uninstall $packagename卸载原来的应用,否则会签名冲突无法覆盖安装,再执行adb install apk.apk,提示Success,安装成功。

image-20211116213433585

所以可以发现Package Manageme Service在安装时会检测应用包名,不在白名单内会拒绝安装。虽然我们可以修改包名达到安装任意应用,先不考虑修改包名后APP能否正常运行,白名单内的APP数量有限,无法随心所欲地安装应用。

分析管理员设置

既然管理员设置能打开USB,那么它是怎么打开的呢?其中的函数调用链是怎样的呢?我们需要继续分析管理员设置。

很容易找到管理员设置对应的类是AdminActivity,我们进入看伪代码,发现打开USB时调用了一个叫MDM.x.enableUSB()的方法:

image-20211110025904172

我们跟进去看,发现是一个这样的类:

MDM

由于手上的是联想的设备,我们继续跟到LenovoImpl()

image-20211114203847365

可以看到Lenovolmpl()类实现了IMDM的接口,提供了控制平板相关的方法。我们尝试深挖一下控制平板的方法,看到这个类import了android.app.mia.MiaMdmPolicyManager,我们继续跟下去。

image-20211114204412909

但是没有发现实现方法,估计是系统提供了相关API,毕竟系统被深度定制过。这没关系,我们已经掌握了平板管理的相关逻辑,可以总结出接口逻辑并进行利用了。

image-20211115014310911

(其中MDM.x识别型号并创建对应设备的类,并由这个类实现IMDM接口)

漏洞利用

image-20211115025137095

平板控制相关的函数调用链如图,黑色框圈起来的部分是在APP内执行的,管理员设置或者后端下发的配置调用MDM.x,再到IMDM,最后再与system对接,于是我们可以想到两种利用方法:

  • 另外构造一个app实现MDM.x, IMDM, Device Impl等方法(可以照搬伪代码)
  • 劫持Admin Setting中调用的函数(Admin Setting可以主动触发)

1

第一种方法可以实现像这样的效果

image-20211115032744900

这时我们只需将写好的APP改成系统内置的包名就可以安装进去,进行相关的操作。

2

刚刚一直在审计Java伪代码,如果我们想要更改运行流,那么我们需要去修改其对应的smali代码。善用搜索功能我们很容易定位到相关的smali代码:

image-20211115175554746

这段代码转译成Java伪代码就是MDM.x.enableUsb(),我们只需要将enableUsb改成IMDM提供的其他方法,比如disableFirewall,addWhiteList等就能直接执行对应的方法了。

深度修改APP

破解管理员登录

首先为了后续的操作方便,我们先破解管理员登录这个Activity以实现任意用户登录。先分析smali逻辑:

image-20211115223142444

于是我们可以把密码判断的if-eqz替换成if-nez,这样如果用户输入错误的密码就不跳转,进行登录成功的流程,不仅如此,我们可以更进一步,在line 104中调用sPFTool来读取管理员密码时插入一个弹窗,把密码值通过弹窗弹出来,在move-result-object v1后面插入如下代码:

const/4 v5, 0x1
invoke-static {p0, v1, v5}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
move-result-object v4
invoke-virtual {v4}, Landroid/widget/Toast;->show()V

即可在登录中程序调用密码时将密码弹出来,由于我使用的是早期版本的平板管理软件,密码直接以明文方式存储,十分方便进行hook,而后续版本则存储了密码的MD5,但是实验表明这段MD5并没有使用任何数据加salt,对其进行解密难度不是特别大。

解除云端控制

前面提到后端能远程下发配置或发送指令直接控制客户端,我们需要找出这个方法,既然控制客户端需要用到MDM.x的方法,我们善用搜索全局搜索MDM.x,找到一个CmdManager的类:

image-20211115230504202

大致逻辑是收到指定的字符串指令就执行某些操作,我们同样可以修改这个判断指令,改成服务端永远也不会发送的一些字符串,那么服务端也永远控制不了客户端了。

解除网址白名单

每次重启设备网址白名单都会开启,而开启白名单的方法对应为MDM.x.enableFirewall(),我们可以在BootCheckReceiver这个类找到方法调用,这个类一看名字就知道跟启动有关,我们同样在smali把它改成disableFirewall即可实现自动解除网址白名单

一些信息泄漏

既然客户端会与后端通信,我们可以看看是如何通信的,于是继续审计源码,很容易就找到一个用来初始化应用白名单和管理员密码的方法:

image-20211115234809895

这个方法暴露了后端服务器的域名和端口,我们可以伪造请求或者别的攻击,这里就不多展开了。

应用白名单的解除

虽然我们已经可以任意控制IMDM方法,但是IMDM方法类并没有显式的应用白名单开关,只有写入白名单,显然每次安装APP之前写一次白名单不现实,那么有没有什么方法能解除限制呢?

我们可以分析一下逻辑,只要存在不在白名单内的APP系统就会触发自动卸载,这个卸载也是定制系统给的后门,非常强力,如果白名单被清空那意味着除了系统应用之外的用户应用都会被卸载,包括平板管理,那么平板就会报废–因为没有平板管理对接服务器写入新的白名单,那么应该可以推出如果白名单是空的,则不存在应用安装限制。我们可以构造一个exp来清空白名单:

ArrayList<String> arrayList = new ArrayList();
MDM.x.appWhiteListWrite(arratList);

把这个exp放入带有MDM.x的APP并执行,就能清空应用白名单并解除限制。至此,我们已经有了完全控制权。

0x04 总结

这是本人的第一个移动端逆向实战,有点简单,请各位大佬多多包涵。写这篇文章的目的在于分享自己漏洞挖掘的相关思路,如有错误,希望大佬们多多指教。

评论

misift_Zero 2021-11-17 10:10:32

请带带我

123321123321 2021-11-17 10:26:55

大佬666

E

en 2021-11-17 19:25:16

好强

lsf 2021-11-17 20:30:14

大佬tql

YQ 2021-11-17 21:09:20

我的天啊,在这都能碰见大佬starryloki!

云里雾里 2021-11-18 14:32:40

God of Android

o0xmuhe 2021-11-23 12:02:50

感谢分享,精彩~ 通过race拿adb也遇到过一次...感觉挺神奇的: )

starryloki

这个人很懒,没有留下任何介绍

twitter weibo github wechat

随机分类

XSS 文章:34 篇
业务安全 文章:29 篇
Java安全 文章:34 篇
逻辑漏洞 文章:15 篇
硬件与物联网 文章:40 篇

扫码关注公众号

WeChat Offical Account QRCode

最新评论

Yukong

🐮皮

H

HHHeey

好的,谢谢师傅的解答

Article_kelp

a类中的变量secret_class_var = "secret"是在merge

H

HHHeey

secret_var = 1 def test(): pass

H

hgsmonkey

tql!!!

目录