在之前文章中,我们介绍了 SpaceX Starlink 路由器二代的工作原理和逆向分析过程,以及该路由器在提供卫星互联网服务方面的重要性。接下来继续分析SpaceX Starlink 路由器二代的开源代码。
一、ATF安全启动
1. 在之前文章中,我们介绍了 SpaceX Starlink 路由器二代的开源代码UBOOT的启动方式,现在我们继续分析ATF相关的代码部分,ATF部分相关的核心编译代码如下。
#!/bin/bash -ex
cd "$(dirname "$0")/../ATF"
export CROSS_COMPILE=/usr/bin/arm-linux-gnueabihf-
if [[ "$NO_CLEAN" != "1" ]]; then
make distclean
fi
make \
PLAT=mt7629 \
ARCH=aarch32 \
AARCH32_SP=sp_min \
BOOT_DEVICE=snand \
NMBM=1 \
NAND_TYPE=2k+64 \
BL33=../bin/$VERSION/v2-$VERSION-uboot.bin \
MBEDTLS_DIR=../tools/mbedtls-mbedtls-2.16.2 \
TRUSTED_BOARD_BOOT=1 \
GENERATE_COT=1 \
ANTI_ROLLBACK_FIP_VERSION=$ANTI_ROLLBACK_REQUIRED_VERSION \
ROT_KEY=../keys/fip_private_key.pem \
BROM_SIGN_KEY=../keys/bl2_private_key.pem \
LOG_LEVEL=40 \
all fip
cp build/mt7629/release/bl2.img ../bin/$VERSION/v2-$VERSION-bl2.img
cp build/mt7629/release/bl2.img.signkeyhash ../bin/$VERSION/v2-$VERSION-bl2.img.signkeyhash
cp build/mt7629/release/fip.bin ../bin/$VERSION/v2-$VERSION-fip.bin
ARM Trusted Firmware(ATF)在引导过程中分为多个阶段,每个阶段都负责不同的任务。以下是 ATF 的主要阶段:
-
BL1(Boot Loader stage 1):BL1 是引导过程中的第一个阶段,它负责执行重要的硬件初始化任务。在引导过程开始时,BL1 会被加载到安全内存中,并从 Reset Vector 开始执行。它负责配置处理器的内存和中断控制器,然后加载并验证 BL2 镜像。验证成功后,BL1 将控制权转交给 BL2。
-
BL2(Boot Loader stage 2):BL2 是引导过程中的第二个阶段。在接管控制权之后,BL2 继续初始化硬件,例如内存控制器、时钟和其他外设。然后,BL2 加载并验证 FIP(Firmware Image Package)中的 BL3x 镜像。验证成功后,BL2 将控制权转交给 BL31。
-
BL31(Boot Loader stage 3-1):BL31 是 ATF 中的 EL3 运行时软件。它负责处理器的异常处理、异常路由和安全管理。BL31 还提供了一组 SMC(Secure Monitor Call)接口,用于从非安全世界(例如运行操作系统的 Normal World)请求安全服务。BL31 将控制权转交给 BL33。
-
BL32(Boot Loader stage 3-2):BL32 是可选的安全运行时环境,通常用于实现可信执行环境(TEE)例如 OP-TEE。BL32 运行在 Secure-EL1 异常级别。它可以提供一组受信任的应用程序和服务,用于处理敏感数据和操作。BL32 由 BL31 加载,但在 BL33 启动之前运行。
-
BL33(Boot Loader stage 3-3):BL33 是引导过程中的最后一个阶段,通常是 U-Boot 或其他引导加载程序。在 BL31 接管控制权后,它将最终负责加载操作系统(如 Linux)并将控制权转交给它。
-
这些阶段共同实现了 ARM Trusted Firmware 的安全启动和运行时服务。每个阶段都负责特定的任务,并将控制权安全地传递给下一个阶段。
-
2. 在之前文章中,我们介绍了 SpaceX Starlink 路由器二代的开源代码UBOOT的启动方式,现在我们继续分析ATF相关的代码部分,ATF部分相关的核心编译代码如下。
2. 生成的带有签名的文件(包含uboot),被存放到了指定目录下面。
cp build/mt7629/release/bl2.img ../bin/$VERSION/v2-$VERSION-bl2.img
cp build/mt7629/release/bl2.img.signkeyhash ../bin/$VERSION/v2-$VERSION-bl2.img.signkeyhash
cp build/mt7629/release/fip.bin ../bin/$VERSION/v2-$VERSION-fip.bin
二、编译OPENWRT
编译opwnwrt脚本如下,编译存在问题,这里只是分析他的编译逻辑,暂时不去深入分析编译问题的错误所在。
#!/bin/bash -ex
cd "$(dirname "$0")/../openwrt"
echo "$OVERLAY" > package/base-files/files/etc/overlay
echo "$VERSION" > package/base-files/files/etc/version
cp spacex-mtk-openwrt.config .config
if [[ "$NO_CLEAN" != "1" ]]; then
make dirclean
fi
make -j4 FORCE_UNSAFE_CONFIGURE=1
cp bin/targets/mediatek/mt7629/lede-mediatek-mt7629-SPACEX-WIFI-V2-squashfs-sysupgrade.bin ../bin/$VERSION/v2-$VERSION-openwrt.img
三、编译UBI存储镜像
#!/bin/bash -ex
cd "$(dirname "$0")/../storage"
mkdir -p bin
# Make UBI image
ubinize -o bin/ubi.img -p 128KiB -m 2048 -s 2048 cfg.ini
cp bin/ubi.img ../bin/$VERSION/v2-$VERSION-storage.img
重点的函数是下面的这个:
ubinize -o bin/ubi.img -p 128KiB -m 2048 -s 2048 cfg.ini:
使用ubinize工具根据cfg.ini文件创建一个UBI镜像,参数解释如下:
-o bin/ubi.img:指定输出文件为bin/ubi.img。
-p 128KiB:设置物理擦除块大小为128KiB。这个选项用于设置物理擦除块(PEB,Physical Erase Block)的大小。物理擦除块是闪存设备上的基本擦除单位。
-m 2048:设置最小I/O单位大小为2048字节。在这里,-m后面的参数2048表示将最小I/O单位大小设置为2048字节(2KB)。
-s 2048:设置子页面大小为2048字节。在这里,-s后面的参数2048表示将子页面大小设置为2048字节(2KB)。
cfg.ini:指定配置文件。
需要注意的是:了解NAND闪存芯片的特性在配置UBI文件系统时非常重要。在为特定硬件和应用场景创建UBI镜像时,需要根据NAND闪存芯片的实际规格和特性来调整擦除块大小、最小I/O单位大小等参数。
四、将编译文件存入UBI存储镜像
#!/bin/bash -ex
# The single image is a binary blob that can be written to raw NAND on our
# router, starting from byte 0. The intention is that the factory flashes the
# single image during the manufacturing process. Single images are not used to
# perform a router upgrade.
#
# Image Layout, size 0x8000000, 128M(存储空间)
# 0x00000000 BL2
# 中间存储512KB
# 0x00080000 FIP0
# 中间存储空间2M
# 0x00280000 FIP1
# 中间存储空间2M
# 0x00480000 Config
# 0x00500000 Factory Calibration # Not used by our driver
# 0x00600000 AUTOFUSE string offset (Set in release script rather than at build time)
# 0x00610000 Starting version record
# 0x02000000 OpenWRT FIT 0
# 0x04000000 OpenWRT FIT 1
# 0x06000000 UBI Partition
# 0x06000000 Config volume
# 0x06800000 Log volume
cd "$(dirname "$0")/../bin"
#64K Blocks, 0x10000
BLOCK_SIZE=65536
# Generate a single image at path
OUT="$VERSION/v2-$VERSION-single.bin"
# Pad up to UBI partition - 0x06000000
dd if=/dev/zero of=$OUT bs=$BLOCK_SIZE seek=0 count=1536 # 1536 *64KB = 96M
# Write BL2 at 0x0.
dd if="$VERSION/v2-$VERSION-bl2.img" of=$OUT bs=$BLOCK_SIZE seek=0 conv=notrunc
# Write FIP0 (contains the uboot) to output binary, at 0x080000
dd if="$VERSION/v2-$VERSION-fip.bin" of=$OUT bs=$BLOCK_SIZE seek=8 conv=notrunc
# Write FIP1 (contains the uboot) to output binary, at 0x280000
dd if="$VERSION/v2-$VERSION-fip.bin" of=$OUT bs=$BLOCK_SIZE seek=40 conv=notrunc
# Record version we were built with.
echo -n "$VERSION" | dd of=$OUT bs=$BLOCK_SIZE seek=97 conv=notrunc
# OpenWRT FIT0
dd if="$VERSION/v2-$VERSION-openwrt.img" of=$OUT bs=$BLOCK_SIZE seek=512 conv=notrunc
# OpenWRT FIT1
dd if="$VERSION/v2-$VERSION-openwrt.img" of=$OUT bs=$BLOCK_SIZE seek=1024 conv=notrunc
# Write storage UBI image
dd if="$VERSION/v2-$VERSION-storage.img" of=$OUT bs=$BLOCK_SIZE seek=1536
# Update convenience symlink.
ln -sf $OUT flashimage.bin
最后将编译的各种镜像,安全启动fip.bin(含uboot)、openwrt等存储入flashimage。
以上便是starlink的路由器开源代码的大致逻辑,更详细的讨论和分析,可从文末尾github处获取。
五、总结
1. 本文主要介绍了 SpaceX 推出的 Starlink 路由器设备的硬件固件安全分析方法,以及其相关的通信协议和安全机制。
2. 本文所提到的固件及相关代码资料可从下面链接获取:
https://github.com/MasterTaiBai/Sat-Hacking
Sat-Hacking愿景:成为一名合格的卫星黑客需要长时间的学习和实践。只有通过持续的努力,掌握各种卫星安全知识和技能,才能真正成为一个专业的卫星白帽子。
在此祝愿安全爱好者及从业人员都能够取得成功,实现自己的梦想,为网络安全贡献自己的力量!