AdBox 折腾记
对 GF-WM28H 广告盒子的折腾

对家里几年前办宽带给的联通 IPTV 盒子的一些折腾。

UP: 2019-02-25 11:18:24 星期一


盒子build.prop的部分产品信息

...
ro.build.version.release=4.4.2
...
ro.product.model=GF-WM28H
ro.product.brand=HiSTBAndroidV5
ro.product.name=Hi3798MV100
ro.product.device=Hi3798MV100
ro.product.board=bigfish
ro.product.cpu.abi=armeabi-v7a
ro.product.cpu.abi2=armeabi
ro.product.manufacturer=Hisilicon
...

最开始拿着GF-WM28H(盒子后面有写) Google 一下,第一页全是卖它的遥控器的… 还好第二页有个靠谱的 V2EX 上的折腾,看了看貌似还不是一个版本?从build.prop来看我家这个貌似是某为海思半导体的 SOC ?至于 RAM 我估计就1G,ROM 根据自带系统设置里面显示貌似也就剩几百 MB 了,粗略估计2G ROM…

然后他是拆机串口进去的root shell,我在学校倒是有USB-TTL的模块(折腾树莓派的时候入的),可是家里没有,还得拆机,手残党必然妈见打系列啊,只好作罢。

虽然不甘心的我还是试了试放 apk 文件到 U盘 进自带的文件管理里面,真找不到文件,屏蔽后缀关键词海星。当然天真的我最开始还以为是专门识别特定后缀,为此还用 shell 脚本复制 apk 为各种后缀组合(也不知道我为啥假定后缀名是三位 :relaxed:

for i in {a-zA-Z}{a-zA-Z}{a-zA-Z};
do
    cp xx.apk xx.$i
done

当然结果可想而知,就三位可能性也太多,试了几百种后缀然后放弃。

然后尝试使用各种什么当贝市场之类的工具通过局域网内 WIFI 云投送方式安装时才发现,设置突然要起了密码,去搜了几个试了试6321进去了,然后连接设置没有了 WIFI 连接,猜测是系统更新后,修补这个可能的漏洞:joy:,无奈再次作罢。

折腾背景

前不久给家里另一个老电视在 pdd 入了一个裴讯T1,帯了双公头 USB 刷机线,给 裴讯T1 刷了几次系统后,突然想起来这个 AdBox 也有 USB 口 会不会有啥进展,然后就去试了试。

AdBox 一共两个 USB 口盒子旁边的一个口 adb 没什么反应,后面各种接口里面藏的 USB 口,能直接 adb 连进去,还是熟悉的# root 用户,那不是装个 app 轻轻松松的事情

装了在恩山论坛给 T1 找的一个桌面,安装可以直接用 adb 也可以直接复制到对应系统目录

# 在用户终端下

adb install xx.apk
## or
adb push xx.apk dir # dir -> system: /system/app or user: /data/app/
adb shell chmod 644 /dir/to/apk

## 注:安装为系统软件需先挂载 /system 可写
adb shell mount -o rw,remount /system/

然后问题又来了,这个 AdBox 直接连的光猫的一个口,走的是 IPTV 的内网,并没有连接互联网,装个什么小电视tv版还没有网…

下面大概记一下对 AdBox 内部的一些调教

  • wifi 连接
  • busybox
  • supersu
  • adb_over_net
  • 网络切换

wifi 连接

连上 USB 通过adb shell进入 AdBox 之后,通过ip addr发现了一个叫wlan0的接口,看来只是在设置里面隐藏了而已嘛,结合对一堆文件的各种cat, more找到了 wifi 配置文件/data/misc/wifi/wpa_supplicant.conf,按照树莓派 wifi 配置经验,添加对应 wifi 配置文件,重启 wifi 即可,大致操作如下

# 在用户终端下
## 先把配置文件拉过来修改了再放回去,我试了试这盒子貌似并没有编辑器,vi nano 都没有
adb pull /data/misc/wifi/wpa_supplicant.conf
## 利用 wpa_passphrase 生成 wifi 配置 写入 配置文件
sudo wpa_passphrase ap_name ap_passwd >> wpa_supplicant.conf
## 把配置文件放回去
adb push wpa_supplicant.conf /data/misc/wifi/wpa_supplicant.conf

## 如添加多个 wifi 配置 可为其分配不同的优先级 
### 用你喜欢的工具 修改配置文件 在单个配置文件中 添加 priority=num 
### num 越大 优先级越高 更改后文件示例如下
...
network={
        ssid="testAP"
        #psk="........"
        psk=07e6ec3fe54e703b7cc97c1d904831cc885a35e1e0846fcf024c93c7c796efa1
        priority=2
}
network={
        ssid="dlink"
        #psk=",,,,,,,,"
        psk=e333a9536c3eff494847ea639cd73316eb0fdb9a3e533edad240e730cd259bf2
        priority=1
}
### 上述就是我最终的具体配置情况(当然密码做了处理,
### testAP 是我在本机建立的用来测试的热点,优先级比dlink高,方便调试

## 重启 wifi
svc wifi disable
svc wifi enable

busybox

由于电视遥控器操作的烦琐(其实 某悟空遥控 还算是做得挺好的,就是不太纯粹,鼠标操作也只是能用),或者想用一些对 TV 操作不太友好的 app 就只好通过在其他平台上配置完毕,备份配置,在盒子上恢复,不过某些 app 的配置想要利用像钛备份之类的 Android 神器恢复,可惜需要 ROOT ,说到 ROOT 我就去找了新锐Magsik Manager,安装之后,在安装界面,只好选择Patch boot img,然后我就去找这个系统的boot.img。

Magisk?

最开始我尝试直接去/dev/block里面去找 boot 分区,然后用 cat 大法直接读取,找了一会儿在/dev/block/platform/hi_mci.1/by-name目录找到了所有设备,ls一下

/dev/block/platform/hi_mci.1/by-name # ls
baseparam    facrootbox   kernel       pqparam      sdcard
bootargs     fastboot     loaderdb     private      stbid
cache        fastplay     logo         qbdata       system
deviceinfo   fastplaybak  logobak      qbflag       userapi
fackernel    hibdrv       misc         recovery     userdata

很好,并没有叫boot的块设备,只好提取一些去分析分析找找看了,随即

# AdBox 终端 位于上述目录 获取
cat xx > /tmp/xx.img
# 用户终端下 拉取文件
adb pull /tmp/xx.img
# 利用如 file 之类工具验证文件类型
file xx.img

开始尝试找,还好在尝试到kernel.img时

file kernel.img
kernel/kernel.img: Android bootimg, kernel (0x3008000), ramdisk (0x4000000), page size: 16384

虽然貌似找到了,但还是不太确认,开始像通过检测更新抓包看能不能有所发现,后面尝试发现不知道是不是限制只能内网检测,通过我的测试热点的更新请求返回状态都是error,不管是尝试更改build.prop版本,更新重试,还是直接修改请求版本参数,返回值都同样如此,只好作罢。

开始用 Magisk Manager 打补丁,放置到系统根目录,安装第三方文件管理,选择文件,然后,unzip error不能解压,随即去搜了搜,他们说叫更新 busybox 试试,然后又回到了 busybox。

busybox?

其实在adb shell里面,对基本的系统的可执行文件目录/system/bin和/system/xbin看了看之后,我发现这 AdBox 上其实有 busybox 版本貌似是1.4x,记不太清了,13年编译的版本,只软链接ln -s出了很少的东西,像vi,xargs,sed,awk...那是都没链接出来。

之前折腾过交叉编译,貌似有编译过 busybox 去找了找,还真有,版本 v1.28.0 适合 armeabi,下载地址,一顿操作放到/system/bin/下,然后链接你想要的命令

/system/bin/busybox ln -sf busybox the_command

重新链接了unzip然后再次打开 Magisk Manager 还是错误,想起来之前在找 boot.img 时通过 adb 重启至 recovery fastboot

# 用户终端
adb reboot recovery
adb reboot fastboot

结果盒子均重启进入了系统,通过 recovery 刷入的方法行不通,只好作罢。那就去看看老将 SuperSU 好了。

SuperSU

既然进不去 recovery (没有? 那么就只好在有 root 权限的 adb shell 里面手动安装SuperSU,去大神 Chainfire 网站下载,解压缩后有如下目录结构

# 缩略其他架构目录
...
.
├── armv7
│   ├── libsupol.so
│   ├── su
│   ├── suinit
│   ├── sukernel
│   └── supolicy
├── common
│   ├── 000000deepsleep
│   ├── 99SuperSUDaemon
│   ├── avb
│   │   ├── BootSignature_Android.jar
│   │   ├── supersu.pk8
│   │   └── supersu.x509.der
│   ├── fbe_bypass.sh
│   ├── file_contexts
│   ├── file_contexts_image
│   ├── formats
│   │   ├── bzip2
│   │   ├── gzip.1
│   │   ├── gzip.2
│   │   ├── legz4
│   │   ├── lz4.1
│   │   ├── lz4.2
│   │   ├── lzma
│   │   ├── lzo
│   │   └── xz
│   ├── frp_install
│   ├── hexpatch
│   ├── init.supersu.rc
│   ├── init.supersu.rc.24
│   ├── init.supersu.rc.24.bindsbin
│   ├── init.supersu.rc.bindsbin
│   ├── install-recovery.sh
│   ├── launch_daemonsu.sh
│   ├── supersu_is_here
│   └── Superuser.apk
├── LICENSE
├── META-INF
│   ├── CERT.RSA
│   ├── CERT.SF
│   ├── com
│   │   └── google
│   │       └── android
│   │           ├── update-binary
│   │           └── updater-script
│   └── MANIFEST.MF
...

对应架构的文件,公共文件,许可协议,一个什么信息包?不太清楚,不过我知道那个目录里面的update-binary文件是一个sh脚本文件,也就是 SuperSU 的安装步骤。

打开META-INF/com/google/android/uptate-binary,你会发现,在脚本之前有两百多行的安装指导(不能对 boot 进行刷入,只好选择 "SYSTEM" INSTALL方式,V2.82-SR5 文档部分摘取如下,其他机型手动安装请参考 SuperSU_Manual_Install_V2.82-SR5.txt

# ----- "SYSTEM" INSTALL -----
# To install SuperSU properly, aside from cleaning old versions and
# other superuser-type apps from the system, the following files need to
# be installed:
#
# API   source                        target                              chmod   chcon                       required
#
# 7-19  common/Superuser.apk          /system/app/Superuser.apk           0644    u:object_r:system_file:s0   gui
#
# 17+   common/install-recovery.sh    /system/etc/install-recovery.sh     0755    *1                          required
# 17+                                 /system/bin/install-recovery.sh     (symlink to /system/etc/...)        required
# *1: same as /system/bin/toolbox: u:object_r:system_file:s0 if API < 20, u:object_r:toolbox_exec:s0 if API >= 20
#
# 7+    ARCH/su *2                    /system/xbin/su                     *3      u:object_r:system_file:s0   required
# 7+                                  /system/bin/.ext/.su                *3      u:object_r:system_file:s0   gui
# 17+                                 /system/xbin/daemonsu               0755    u:object_r:system_file:s0   required
# *2: su.pie for 17+ x86(_32) only
# *3: 06755 if API < 18, 0755 if API >= 18
#
# 17+   common/99SuperSUDaemon *6     /system/etc/init.d/99SuperSUDaemon  0755    u:object_r:system_file:s0   optional
# *6: only place this file if /system/etc/init.d is present
#
# 17+   'echo 1 >' or 'touch' *7      /system/etc/.installed_su_daemon    0644    u:object_r:system_file:s0   optional
# *7: the file just needs to exist or some recoveries will nag you. Even with it there, it may still happen.
#
# After installation, run '/system/xbin/su --install', which may need to
# perform some additional installation steps. Ideally, at one point,
# a lot of this script will be moved there.

简单来说就是按照他的要求对应系统 API 等级,将对应文件放在对应位置,给予适当权限 chmod ,正确的对象安全上下文 chcon。

对与 AdBox 来说,因为 Android 4.4.2 其 API = 19 架构 armeabi 是属于 armv7的,按照上述文档具体操作如下

# 假设以将下载 zip 文件放入盒子 /tmp 目录 在 /tmp 目录下
mount -o rw,remount /system # 挂载 /system/ 可读写

unzip file_name.zip
cp ./common/Superuser.apk /system/app/ 
chmod 0644 /system/app/Superuser.apk
chcon u:object_r:system_file:s0 /system/app/Superuser.apk

cp ./common/install-recovery.sh /system/etc/install-recovery.sh
chmod 0755 /system/etc/install-recovery.sh
chcon u:object_r:system_file:s0 /system/etc/install-recovery.sh
ln -s /system/etc/install-recovery.sh /system/bin/install-recovery.sh

cp ./armv7/su /system/xbin/su
chmod 0755 /system/xbin/su
chcon u:object_r:system_file:s0 /system/xbin/su

mkdir -p /system/bin/.ext/ # 创建这个目录
cp ./armv7/su /system/bin/.ext/.su
chmod 0755 /system/bin/.ext/.su
chcon u:object_r:system_file:s0 /system/bin/.ext/.su

cp ./armv7/su /system/xbin/daemonsu
chmod 0755 /system/xbin/daemonsu
chcon u:object_r:system_file:s0 /system/xbin/daemonsu

echo 1 > /system/etc/.installed_su_daemon # 将 1 写入这个文件,创建这个文件
chmod 0644 /system/etc/.installed_su_daemon
chcon u:object_r:system_file:s0 /system/etc/.installed_su_daemon

/system/xbin/su --install
# 最好删掉 原来的/system/bin/su 如果有的话,文档里没有在这里放置 su
rm /system/bin/su

mount -o ro,remount /system # 挂载回 /system 只读

完成上述步骤之后,重启进入 超级授权 应该就可用了。

有了 ROOT 权限就能装很多有意思的 app 了,比如 钛备份,Tasker,afwall。

adb_over_net

其实这里要解决的问题只要就是,AdBox 默认有一条 iptables 规则过滤了 adb_over_net 要用到的 5555 端口。

在折腾上面那一堆东西之前,其实我就在尝试通过自建的热点,通过adb connect ip去尝试连接,当然发现失败是报错time out,猜想就是被过滤了。通过 USB adb 进去iptables --list-rules,确实发现了一条过滤规则,DROP 掉到 5555 的连接,由于找不到配置文件,最开始就写了个脚本去删掉它

# adbox_iptables file in /system/bin/
INPUTL=$(iptables --list INPUT --line-numbers -n | grep '^[0-9]' | grep 5555)
echo "$INPUTL"
# LENTH=$(echo "$INPUTL" | wc -l)

DROPINPUTL=$(echo "$INPUTL" | grep DROP)
if [ -n "$DROPINPUTL" ];then
        echo "delete DROP rule"
        num=$(echo "$DROPINPUTL" | awk '{print $1}')
        echo "$num" | xargs -I {} iptables --delete INPUT {}
fi

INPUTL=$(iptables --list INPUT --line-numbers -n | grep '^[0-9]' | grep 5555)
# add rule
if ! echo "$INPUTL" | grep -q 5555;then
    iptables -A INPUT -p tcp -m tcp -s 192.168.12.0/24 --dport 5555 -j ACCEPT
fi

echo "now INPUT rule contain port 5555 list"
iptables --list INPUT --line-numbers -n | grep '^[0-9]' | grep 5555

也很容易看出,其实就是找到规则删掉它,并添加一条新的规则,允许特定网段连接(即我的 testAP 的网段

之后,又给 AdBox 添加了init.d支持,通过这个 XDA 帖子作者提供的脚本,实现了开机自启动应用这条规则,即简单写个 sh 脚本调用我上面的adbox_iptable。

在我装完 Afwall 想对应用进行防火墙控制之后~~(其实是天真的想,我禁用了你的 LAN 联网,你是不是就只有去用 WLAN 了呢?见后文网络切换~~,由于其也依赖 init.d 开机自启动初始化 iptables ,造成了可能我刚改完规则,afwall 的启动脚本后来就全部iptables -F xx了。

现在我使用 Tasker 手动(自动也行,主要是等 afwall 改完)实现对规则的修改,建一个任务直接运行上面脚本即可,改都不用改 :laughing:

网络切换

由于 IPTV 走内网,在同时连接 wifi 和 PPP0E 的情况下,默认是走 PPPOE 的,而这里面又没有连接互联网,所以得进行网络切换。

最开始我一直在研究 iptables 对特定应用转发其在 ppp0 上的包到 wlan0 上,然后发现按照 sf 上面一顿操作之后,还是没好使。还通过各种教程研究 iptables 的使用…,是不是只能对应端口转发?是不是得去操作路由啊?

说到路由,我去ip route看了看,好嘛,默认是走 PPPOE 的 gateway,改改看看ip route replace default via 192.168.12.1,去打开小电视看了看,还真行,然后通过 Tasker 自动更改默认路由 的方案全票通过了。实际上发现这个操作之前在 iptables 上鸽了很久

去 Tasker 官网下载了 Android 4.4 能用的版本,在手机上弄好配置文件,adb push到盒子,导入,测试,启用。**通过简单地打开特定应用,再根据网络连接情况,得到网关地址,更改网关地址,关闭特定应用,获取网关地址,改回网关地址。**算是实现了自由的网络切换。

贴上一张具体任务实现「任务编辑界面图」,就一目了然了

通过 shell 运行命令,获取地址(广播地址 brd /远端接口 peer),相应修改为网关地址,在运行ip route replace default via xx更改即可

提供下我的「网络切换+adb_over_net端口打开」Tasker 配置文件,如果有人需要(应该不会有:joy:,供参考。

Other

在准备利用 Wireshark 抓包找固件下载地址获取 boot.img 的时候,其实还有更多的发现,在茫茫 http 请求中,发现了一些 POST 上传,根据地址命名应该是上传系统 log 之类的东西,倒是确实没发现什么应用列表啊之类的数据问题,谁知道呢,或与在非 ASCII 数据里面有些什么呢?在这个隐私毫无的时代

回到这个盒子来看,在装了第三方桌面后,我才发现,这个 Android 4.4.2 真是深度定制阉割,连个系统设置都被阉割了,开始还想着装了第三方桌面进设置去连个 wifi 结果发现,连设置都没有,然后搞出了上面的一堆操作,或许将来升个级就啥都得重新来过了,ban 掉升级的 ip 的想法出现了,但没真去 ban ,或许将来升级之后操作会更有挑战性呢?(通过驱动层面封掉后面的 USB 口?装的 app 全删掉,装进系统的也顺便重置,真是美滋滋呢!

完


Last modified on 2019-02-25