使用 binwalk 对家庭路由器进行逆向工程。 您信任您的路由器软件吗?

使用 binwalk 对家庭路由器进行逆向工程。 您信任您的路由器软件吗?

几天前,我决定使用 binwalk 对路由器的固件进行逆向工程。

我自己买的 TP-Link Archer C7 家用路由器。 不是最好的路由器,但足以满足我的需求。

每次我购买新路由器时,我都会安装 OpenWRT的。 为了什么? 一般来说,制造商不太关心支持他们的路由器,随着时间的推移,软件会变得过时,出现漏洞,等等,一般来说,你就明白了。 因此,我更喜欢OpenWRT固件,它得到了开源社区的良好支持。

下载了OpenWRT后,我也 下载了最新的固件镜像 从官方网站下我的新Archer C7并决定对其进行分析。 纯粹为了好玩,谈谈binwalk。

什么是宾步行道?

Binwalk 是一个用于分析、逆向工程和固件映像提取的开源工具。

binwalk 由 Craig Heffner 于 2010 年创建,可以扫描固件映像并查找文件、识别和提取文件系统映像、可执行代码、压缩档案、引导加载程序和内核、JPEG 和 PDF 等文件格式等等。

您可以使用 binwalk 对固件进行逆向工程以了解其工作原理。 搜索二进制文件中的漏洞、提取文件并查找后门或数字证书。 您还可以找到 opcodes 对于一堆不同的CPU。

您可以提取文件系统映像来查找特定的密码文件(passwd、shadow 等)并尝试破解密码哈希。 您可以在两个或多个文件之间执行二进制解析。 您可以对数据执行熵分析以查找压缩数据或编码的加密密钥。 所有这一切都无需访问源代码。

一般来说,您需要的一切都在那里:)

Binwalk 是如何工作的?

binwalk的主要特点是它的签名扫描。 Binwalk可以扫描固件镜像来搜索各种内置文件类型和文件系统。

你知道命令行实用程序吗 file?

file /bin/bash
/bin/bash: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=12f73d7a8e226c663034529c8dd20efec22dde54, stripped

团队 file查看文件头并查找签名(幻数)以确定文件类型。 例如,如果文件以字节序列开头 0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A,它知道这是一个 PNG 文件。 在 维基百科 有一个常见文件签名的列表。

Binwalk 的工作原理相同。 但 binwalk 不会仅在文件开头查找签名,而是会扫描整个文件。 此外,binwalk 可以提取图像中找到的文件。

工具 file и binwalk 使用图书馆 libmagic 识别文件签名。 但 binwalk 另外还支持自定义魔术签名列表来搜索压缩文件、固件头、Linux 内核、引导加载程序、文件系统等。

我们来玩点乐子吧?

Binwalk安装

Binwalk 支持多种平台,包括 Linux、OSX、FreeBSD 和 Windows。

要安装最新版本的 binwalk,您可以 下载源代码 并关注 安装说明 или 快速指南,可在项目网站上找到。

Binwalk 有许多不同的参数:

$ binwalk

Binwalk v2.2.0
Craig Heffner, ReFirmLabs
https://github.com/ReFirmLabs/binwalk

Usage: binwalk [OPTIONS] [FILE1] [FILE2] [FILE3] ...

Signature Scan Options:
    -B, --signature              Scan target file(s) for common file signatures
    -R, --raw=<str>              Scan target file(s) for the specified sequence of bytes
    -A, --opcodes                Scan target file(s) for common executable opcode signatures
    -m, --magic=<file>           Specify a custom magic file to use
    -b, --dumb                   Disable smart signature keywords
    -I, --invalid                Show results marked as invalid
    -x, --exclude=<str>          Exclude results that match <str>
    -y, --include=<str>          Only show results that match <str>

Extraction Options:
    -e, --extract                Automatically extract known file types
    -D, --dd=<type:ext:cmd>      Extract <type> signatures, give the files an extension of <ext>, and execute <cmd>
    -M, --matryoshka             Recursively scan extracted files
    -d, --depth=<int>            Limit matryoshka recursion depth (default: 8 levels deep)
    -C, --directory=<str>        Extract files/folders to a custom directory (default: current working directory)
    -j, --size=<int>             Limit the size of each extracted file
    -n, --count=<int>            Limit the number of extracted files
    -r, --rm                     Delete carved files after extraction
    -z, --carve                  Carve data from files, but don't execute extraction utilities
    -V, --subdirs                Extract into sub-directories named by the offset

Entropy Options:
    -E, --entropy                Calculate file entropy
    -F, --fast                   Use faster, but less detailed, entropy analysis
    -J, --save                   Save plot as a PNG
    -Q, --nlegend                Omit the legend from the entropy plot graph
    -N, --nplot                  Do not generate an entropy plot graph
    -H, --high=<float>           Set the rising edge entropy trigger threshold (default: 0.95)
    -L, --low=<float>            Set the falling edge entropy trigger threshold (default: 0.85)

Binary Diffing Options:
    -W, --hexdump                Perform a hexdump / diff of a file or files
    -G, --green                  Only show lines containing bytes that are the same among all files
    -i, --red                    Only show lines containing bytes that are different among all files
    -U, --blue                   Only show lines containing bytes that are different among some files
    -u, --similar                Only display lines that are the same between all files
    -w, --terse                  Diff all files, but only display a hex dump of the first file

Raw Compression Options:
    -X, --deflate                Scan for raw deflate compression streams
    -Z, --lzma                   Scan for raw LZMA compression streams
    -P, --partial                Perform a superficial, but faster, scan
    -S, --stop                   Stop after the first result

General Options:
    -l, --length=<int>           Number of bytes to scan
    -o, --offset=<int>           Start scan at this file offset
    -O, --base=<int>             Add a base address to all printed offsets
    -K, --block=<int>            Set file block size
    -g, --swap=<int>             Reverse every n bytes before scanning
    -f, --log=<file>             Log results to file
    -c, --csv                    Log results to file in CSV format
    -t, --term                   Format output to fit the terminal window
    -q, --quiet                  Suppress output to stdout
    -v, --verbose                Enable verbose output
    -h, --help                   Show help output
    -a, --finclude=<str>         Only scan files whose names match this regex
    -p, --fexclude=<str>         Do not scan files whose names match this regex
    -s, --status=<int>           Enable the status server on the specified port

图像扫描

让我们首先在图像中搜索文件签名(图像来自网站 TP-LINK).

使用 --signature 参数运行 binwalk:

$ binwalk --signature --term archer-c7.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
------------------------------------------------------------------------------------------
21876         0x5574          U-Boot version string, "U-Boot 1.1.4-g4480d5f9-dirty (May
                              20 2019 - 18:45:16)"
21940         0x55B4          CRC32 polynomial table, big endian
23232         0x5AC0          uImage header, header size: 64 bytes, header CRC:
                              0x386C2BD5, created: 2019-05-20 10:45:17, image size:
                              41162 bytes, Data Address: 0x80010000, Entry Point:
                              0x80010000, data CRC: 0xC9CD1E38, OS: Linux, CPU: MIPS,
                              image type: Firmware Image, compression type: lzma, image
                              name: "u-boot image"
23296         0x5B00          LZMA compressed data, properties: 0x5D, dictionary size:
                              8388608 bytes, uncompressed size: 97476 bytes
64968         0xFDC8          XML document, version: "1.0"
78448         0x13270         uImage header, header size: 64 bytes, header CRC:
                              0x78A267FF, created: 2019-07-26 07:46:14, image size:
                              1088500 bytes, Data Address: 0x80060000, Entry Point:
                              0x80060000, data CRC: 0xBB9D4F94, OS: Linux, CPU: MIPS,
                              image type: Multi-File Image, compression type: lzma,
                              image name: "MIPS OpenWrt Linux-3.3.8"
78520         0x132B8         LZMA compressed data, properties: 0x6D, dictionary size:
                              8388608 bytes, uncompressed size: 3164228 bytes
1167013       0x11CEA5        Squashfs filesystem, little endian, version 4.0,
                              compression:xz, size: 14388306 bytes, 2541 inodes,
                              blocksize: 65536 bytes, created: 2019-07-26 07:51:38
15555328      0xED5B00        gzip compressed data, from Unix, last modified: 2019-07-26
                              07:51:41

现在我们有很多关于这张图片的信息。

图片用途 潜艇 作为引导加载程序(图像标题位于 0x5AC0 和压缩的引导加载程序映像 0x5B00)。 根据0x13270处的uImage头,我们知道处理器架构是MIPS,Linux内核版本是3.3.8。 并根据在该地址找到的图像 0x11CEA5,我们可以看到 rootfs 是一个文件系统 squashfs.

现在让我们使用命令提取引导加载程序(U-Boot) dd:

$ dd if=archer-c7.bin of=u-boot.bin.lzma bs=1 skip=23296 count=41162
41162+0 records in
41162+0 records out
41162 bytes (41 kB, 40 KiB) copied, 0,0939608 s, 438 kB/s

由于图像是使用LZMA压缩的,因此我们需要对其进行解压缩:

$ unlzma u-boot.bin.lzma

现在我们有了一个 U-Boot 映像:

$ ls -l u-boot.bin
-rw-rw-r-- 1 sprado sprado 97476 Fev  5 08:48 u-boot.bin

如何找到默认值 bootargs?

$ strings u-boot.bin | grep bootargs
bootargs
bootargs=console=ttyS0,115200 board=AP152 rootfstype=squashfs init=/etc/preinit mtdparts=spi0.0:128k(factory-uboot),192k(u-boot),64k(ART),1536k(uImage),14464k@0x1e0000(rootfs) mem=128M

U-Boot环境变量 bootargs 用于向 Linux 内核传递参数。 而从上面,我们对设备的闪存有了更多的了解。

如何提取 Linux 内核映像?

$ dd if=archer-c7.bin of=uImage bs=1 skip=78448 count=1088572
1088572+0 records in
1088572+0 records out
1088572 bytes (1,1 MB, 1,0 MiB) copied, 1,68628 s, 646 kB/s

我们可以使用命令检查图像是否已成功提取 file:

$ file uImage
uImage: u-boot legacy uImage, MIPS OpenWrt Linux-3.3.8, Linux/MIPS, Multi-File Image (lzma), 1088500 bytes, Fri Jul 26 07:46:14 2019, Load Address: 0x80060000, Entry Point: 0x80060000, Header CRC: 0x78A267FF, Data CRC: 0xBB9D4F94

uImage 文件格式基本上是带有附加标头的 Linux 内核映像。 让我们删除这个标头以获得最终的 Linux 内核映像:

$ dd if=uImage of=Image.lzma bs=1 skip=72
1088500+0 records in
1088500+0 records out
1088500 bytes (1,1 MB, 1,0 MiB) copied, 1,65603 s, 657 kB/s

图片已经被压缩了,我们来解压一下:

$ unlzma Image.lzma

现在我们有了一个 Linux 内核镜像:

$ ls -la Image
-rw-rw-r-- 1 sprado sprado 3164228 Fev  5 10:51 Image

我们可以用内核镜像做什么? 例如,我们可以在图像中进行字符串搜索,找到 Linux 内核的版本,并了解用于构建内核的环境:

$ strings Image | grep "Linux version"
Linux version 3.3.8 (leo@leo-MS-7529) (gcc version 4.6.3 20120201 (prerelease) (Linaro GCC 4.6-2012.02) ) #1 Mon May 20 18:53:02 CST 2019

尽管该固件是去年(2019 年)发布的,但在我撰写本文时,它使用的是 3.3.8 年发布的旧版本 Linux 内核 (2012),也是自 4.6 年以来使用非常旧版本的 GCC (2012) 进行编译的!
(大约翻译。您仍然信任办公室和家里的路由器吗?)

有选项 --opcodes 我们还可以使用 binwalk 查找机器指令并确定图像的处理器架构:

$ binwalk --opcodes Image
DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
2400          0x960           MIPS instructions, function epilogue
2572          0xA0C           MIPS instructions, function epilogue
2828          0xB0C           MIPS instructions, function epilogue

那么根文件系统呢? 让我们使用该选项,而不是手动提取图像 binwalk --extract:

$ binwalk --extract --quiet archer-c7.bin

完整的根文件系统将被提取到一个子目录中:

$ cd _archer-c7.bin.extracted/squashfs-root/

$ ls
bin  dev  etc  lib  mnt  overlay  proc  rom  root  sbin  sys  tmp  usr  var  www

$ cat etc/banner
     MM           NM                    MMMMMMM          M       M
   $MMMMM        MMMMM                MMMMMMMMMMM      MMM     MMM
  MMMMMMMM     MM MMMMM.              MMMMM:MMMMMM:   MMMM   MMMMM
MMMM= MMMMMM  MMM   MMMM       MMMMM   MMMM  MMMMMM   MMMM  MMMMM'
MMMM=  MMMMM MMMM    MM       MMMMM    MMMM    MMMM   MMMMNMMMMM
MMMM=   MMMM  MMMMM          MMMMM     MMMM    MMMM   MMMMMMMM
MMMM=   MMMM   MMMMMM       MMMMM      MMMM    MMMM   MMMMMMMMM
MMMM=   MMMM     MMMMM,    NMMMMMMMM   MMMM    MMMM   MMMMMMMMMMM
MMMM=   MMMM      MMMMMM   MMMMMMMM    MMMM    MMMM   MMMM  MMMMMM
MMMM=   MMMM   MM    MMMM    MMMM      MMMM    MMMM   MMMM    MMMM
MMMM$ ,MMMMM  MMMMM  MMMM    MMM       MMMM   MMMMM   MMMM    MMMM
  MMMMMMM:      MMMMMMM     M         MMMMMMMMMMMM  MMMMMMM MMMMMMM
    MMMMMM       MMMMN     M           MMMMMMMMM      MMMM    MMMM
     MMMM          M                    MMMMMMM        M       M
       M
 ---------------------------------------------------------------
   For those about to rock... (%C, %R)
 ---------------------------------------------------------------

现在我们可以做很多不同的事情。

我们可以搜索配置文件、密码哈希、加密密钥和数字证书。 我们可以分析二进制文件 故障排除 和漏洞。

и chroot 我们甚至可以从映像运行(模拟)可执行文件:

$ ls
bin  dev  etc  lib  mnt  overlay  proc  rom  root  sbin  sys  tmp  usr  var  www

$ cp /usr/bin/qemu-mips-static .

$ sudo chroot . ./qemu-mips-static bin/busybox
BusyBox v1.19.4 (2019-05-20 18:13:49 CST) multi-call binary.
Copyright (C) 1998-2011 Erik Andersen, Rob Landley, Denys Vlasenko
and others. Licensed under GPLv2.
See source distribution for full notice.

Usage: busybox [function] [arguments]...
   or: busybox --list[-full]
   or: function [arguments]...

    BusyBox is a multi-call binary that combines many common Unix
    utilities into a single executable.  Most people will create a
    link to busybox for each function they wish to use and BusyBox
    will act like whatever it was invoked as.

Currently defined functions:
    [, [[, addgroup, adduser, arping, ash, awk, basename, cat, chgrp, chmod, chown, chroot, clear, cmp, cp, crond, crontab, cut, date, dd, delgroup, deluser, dirname, dmesg, echo, egrep, env, expr, false,
    fgrep, find, free, fsync, grep, gunzip, gzip, halt, head, hexdump, hostid, id, ifconfig, init, insmod, kill, killall, klogd, ln, lock, logger, ls, lsmod, mac_addr, md5sum, mkdir, mkfifo, mknod, mktemp,
    mount, mv, nice, passwd, pgrep, pidof, ping, ping6, pivot_root, poweroff, printf, ps, pwd, readlink, reboot, reset, rm, rmdir, rmmod, route, sed, seq, sh, sleep, sort, start-stop-daemon, strings,
    switch_root, sync, sysctl, tail, tar, tee, telnet, test, tftp, time, top, touch, tr, traceroute, true, udhcpc, umount, uname, uniq, uptime, vconfig, vi, watchdog, wc, wget, which, xargs, yes, zcat

伟大的! 但请注意,BusyBox 版本是 1.19.4。 这是 BusyBox 的一个非常旧的版本,于 2012 年 XNUMX 月发布。

因此,TP-Link 在 2019 年发布了使用 2012 年的软件(GCC 工具链、内核、BusyBox 等)的固件映像!

现在你明白为什么我总是在路由器上安装OpenWRT了吗?

这不是全部

Binwalk还可以执行熵分析、打印原始熵数据并生成熵图。 通常,当图像中的字节是随机的时,会观察到更大的熵。 这可能意味着图像包含加密、压缩或混淆的文件。 硬核加密密钥? 为什么不。

使用 binwalk 对家庭路由器进行逆向工程。 您信任您的路由器软件吗?

我们还可以使用参数 --raw 在图像或参数中查找自定义原始字节序列 --hexdump 执行十六进制转储比较两个或多个输入文件。

自定义签名 可以通过使用参数在命令行上指定的自定义签名文件添加到 binwalk --magic,或者将它们添加到目录中 $ HOME / .config / binwalk / magic.

您可以在以下位置找到有关 binwalk 的更多信息 官方文档.

binwalk 扩展

应用程序编程接口 binwalk,作为一个 Python 模块实现,任何 Python 脚本都可以使用它以编程方式执行 binwalk 扫描,并且 binwalk 命令行实用程序几乎可以通过两行 Python 代码完全复制!

import binwalk
binwalk.scan()

使用 Python API 您还可以创建 Python插件 配置和扩展 binwalk。

也存在 IDA插件 和云版本 Binwalk Pro.

那么为什么不从互联网上下载固件映像并尝试 binwalk 呢? 我保证你会玩得很开心:)

来源: habr.com

添加评论