找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1499

积分

0

好友

190

主题
发表于 4 天前 | 查看: 14| 回复: 0

环境配置

本次分析的固件版本为 AX3000_Pro_V16.03.49.26,其软件源码基于 openwrt

固件分析

首先,使用 binwalk -E 命令分析固件的熵值。虽然固件已经过解密,但其特殊格式导致 binwalk 无法有效识别内部结构。

AX3000固件的熵

binwalk US_AX3000.Pro_V16.03.49.26_cn_JAX01.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
64            0x40            Flattened device tree, size: 3625955 bytes, version: 17
296           0x128           LZMA compressed data, properties: 0x6D, dictionary size: 8388608 bytes, uncompressed size: 10719240 bytes
3607560       0x370C08        Flattened device tree, size: 16962 bytes, version: 17
5273660       0x50783C        PGP RSA encrypted session key - keyid: 3B592D4E D1353F41 RSA (Encrypt or Sign) 1024b

然而,使用 file 命令可以成功识别出固件包含的 u-boot 引导程序和 Linux 内核信息。

file US_AX3000.Pro_V16.03.49.26_cn_JAX01.bin
US_AX3000.Pro_V16.03.49.26_cn_JAX01.bin: u-boot legacy uImage, \002, Linux/ARM, OS Kernel Image (lzma), 14553088 bytes, Fri Jan 10 06:24:02 2025, Load Address: 0X46000000, Entry Point: 0XFFFFFFFF, Header CRC: 0XB19671AF, Data CRC: 0XC47DB558

使用 binwalk -Me US_AX3000.Pro_V16.03.49.26_cn_JAX01.bin 解压固件后,我们成功提取出了 Linux 内核文件。

binwalk 128

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             Linux kernel ARM64 image, load offset: 0x80000, image size: 11046912 bytes, little endian, 4k page size,
5498800       0x53E7B0        MPEG transport stream data
7561216       0x736000        ELF, 64-bit LSB shared object, version 1 (SYSV)
7580200       0x73AA28        gzip compressed data, maximum compression, from Unix, last modified: 1970-01-01 00:00:00 (null date)
7719424       0x75CA00        CRC32 polynomial table, little endian
...
10257728      0x9C8540        AES S-Box
10257984      0x9C8640        AES Inverse S-Box

使用 IDA 以 ARM64 位模式打开提取出的 128(内核)文件。虽然可以搜索到大量 squashfs 相关的函数字符串,但无法查看其调用地址和引用关系,这给逆向分析带来了困难。

AX3000函数分析

为了克服这一障碍,我们可以利用 OpenWrt 的源代码,编译生成一个带有完整调试符号的内核文件。然后,利用这个文件为 IDA 生成签名文件(.sig),从而实现对固件内核中函数的重命名,极大地提升逆向分析的效率。

内核编译

首先,通过分析内核配置信息,确认该固件是基于 OpenWrt 提交 f86f8e568461681fc85caf3c972489045367030e 版本构建的。

  1. 下载并检出对应版本的OpenWrt源码

    git clone https://github.com/openwrt/openwrt.git
    cd openwrt
    git checkout openwrt-21.02
    git checkout f86f8e568461681fc85caf3c972489045367030e
  2. 安装必要的编译环境(在Ubuntu/Debian系统中):

    sudo apt-get install subversion g++ zlib1g-dev build-essential git python3 libncurses5-dev gawk get truth unzip libssl-dev wget
  3. 更新并安装所有软件包

    ./scripts/feeds update -a
    ./scripts/feeds install -a
  4. 配置编译选项
    生成默认配置后,通过 menuconfig 界面进行详细配置。

    make defconfig
    make menuconfig

    openwrt menuconfig

    关键一步:在 Global build settings 选项中,将 Binary stripping method 设置为 none。这样可以确保编译出的内核保留所有符号信息,便于后续分析。
    openwrt strip

  5. 开始编译
    保存配置退出后,使用以下命令开始编译,-j8 指定并行编译的线程数,V=s 输出详细日志。

    make -j8 V=s

编译完成后,找到生成的带符号内核文件 vmlinux.debug

find . -name vmlinux.debug
./build_dir/target-aarch64_cortex-a53_musl/linux-armvirt_64/vmlinux.debug

将该文件导出到 Windows 系统,使用 IDA 加载它,并生成签名文件 vmlinux.sig。之后,在分析原始固件内核时加载此签名,即可恢复绝大部分函数的名称。
openwrt sig

格式分析

跳转到固件偏移地址 0x380040 处,可以发现固件格式的魔数(Magic Number)被修改过:

  • 原本 SquashFS 文件系统的魔数 SQUASHFS_MAGIC (hsqs) 被更改为了 nice
  • 原本 XZ 压缩流的头部魔数 lzma_header_magic (ý7zXZ) 被更改为了 Tenda

squashfs

在标准 OpenWrt 代码中,对 SQUASHFS_MAGIC 的检查通常位于 mtd_check_rootfs_magic 函数内。但在此修改过的固件中,该函数已被改名。我们可以通过追踪 mtd_check_oob_ops 等函数的交叉引用来定位到实际的检查函数,例如 sub_3AC088

nice flag

同理,对 lzma_header_magic 的检查原本在 xz_dec_run 函数中。通过追踪 xz_dec_reset 等引用,可以找到修改后的检查函数 sub_2B0DC0

xz flag

进一步分析发现,CRC32 校验表 crc32_table 的值也被修改了。

crc32 flag
crc32 flag

代码补丁

为了能够正常解压此修改过的固件,我们需要对相关工具的源代码打上补丁,使其识别修改后的魔数和校验表。

1. 修改 xz-5.2.5 库

xz 库的源码路径通常为:./build_dir/host/xz-5.2.5

  • coder.c 文件:
    374c374,375
    <    static const uint8_t magic[6] = { 0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00 };
    ---
    >   // static const uint8_t magic[6] = { 0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00 };
    >   static const uint8_t magic[6] = { 0x54, 0x65, 0x6E, 0x64, 0x61, 0x00 };
  • stream_flags_common.c 文件:
    15,16c15,16
    <
    < const uint8_t lzma_header_magic[6] = { 0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00 };
    ---
    > // const uint8_t lzma_header_magic[6] = { 0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00 };
    > const uint8_t lzma_header_magic[6] = { 0x54, 0x65, 0x6E, 0x64, 0x61, 0x00 };
  • crc32_table_le.h 文件:
    需要用固件中提取的新 CRC32 表替换整个文件内容(原文件内容很长,此处仅示意)。
    5,523c5,523
    <        0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
    <        0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
    <        ... (标准CRC32表数据)
    ---
    >       0x... , // 此处替换为从固件中逆向得到的新CRC32表数据
    >       ... 

2. 修改 squashfs-tools

squashfs-tools 的源码路径通常为:./build_dir/host/squashfskit-v4.14/squashfs-tools

  • 修改 Makefile
    启用 XZ 支持,并链接我们修改后编译的静态库。
    XZ_SUPPORT = 1
    LZMA_LIB := ../../xz-5.2.5/src/liblzma/.libs/liblzma.a
  • 修改 squashfs_fs.h 头文件:
    将 SquashFS 魔数定义改为 0x6563696E(对应 nice 的 ASCII 码)。
    #define SQUASHFS_CACHED_FRAGMENTS       CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE
    #define SQUASHFS_MAJOR                 4
    #define SQUASHFS_MINOR                 0
    //#define SQUASHFS_MAGIC               0x73717368
    #define SQUASHFS_MAGIC                 0x6563696E
    //#define SQUASHFS_MAGIC_SWAP          0x68737173
    #define SQUASHFS_MAGIC_SWAP            0x6E696365
    #define SQUASHFS_START                 0

固件解压

完成代码修改后,按以下步骤操作:

  1. 编译修改后的 xz 静态库

    cd ./build_dir/host/xz-5.2.5
    ./configure
    make
  2. 编译生成定制的 unsquashfs 程序

    cd ./build_dir/host/squashfskit-v4.14/squashfs-tools
    make

    编译成功后会得到 unsquashfs 可执行文件。

  3. 提取并解压文件系统
    首先,使用 dd 命令从固件指定偏移(0x380040)处提取 SquashFS 映像。

    dd if=US_AX3000.Pro_V16.03.49.26_cn_JAX01.bin of=US_AX3000.squashfs bs=1 skip=$((0x380040))

    然后,使用我们编译的 unsquashfs 程序解压该映像。

    ./unsquashfs US_AX3000.squashfs
    Parallel unsquashfs: Using 10 processors
    879 inodes (998 blocks) to write
    create_inode: could not create character device squashfs-root/dev/console, because you're not superuser!
    ...
    [==========================================================================================================================================| ] 991/998  99%
    created 697 files
    created 97 directories
    created 175 symlinks
    created 0 devices
    created 0 fifos

解压完成后,即可在 squashfs-root 目录中查看和分析路由器的完整文件系统。




上一篇:Fresh开源终端文本编辑器:基于Rust开发,轻松处理10GB大文件
下一篇:华硕Live Update供应链漏洞CVE-2025-59374被CISA列入KEV目录:风险分析与应对指南
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-24 20:53 , Processed in 0.341055 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表