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