therealsaumil/emux

GitHub: therealsaumil/emux

基于 Docker 和 QEMU 的 IoT 固件模拟框架,支持 ARM/MIPS 架构设备的完整系统级仿真,用于安全研究和漏洞分析。

Stars: 843 | Forks: 101

# EMUX 固件模拟框架 作者 Saumil Shah [@therealsaumil][saumil] 2025年8月 ![EMUX Docker](https://static.pigsec.cn/wp-content/uploads/repos/2026/03/499390338b231912.jpg) ## 一个精简的 Docker 镜像,可在 Intel 和 Apple Silicon 上运行 最新版本的 EMUX 抛弃了所有外部实用程序,主要专注于在运行 Docker 的 Intel 和 Apple Silicon 平台之间的可移植性。 目前,支持以下模拟平台: * ARM32 * ARM64 * MIPS Little endian * MIPS Big endian ![EMUX Launcher](docs/img/01-emux-launcher.png "EMUX Launcher") 一个全新的运行 EMUX 的 Docker 容器。轻量、紧凑、精确。 ### 快速安装步骤 #### 步骤 0 - 确保已安装并运行 Docker! 通过运行 `hello-world` 测试 Docker 是否正常工作 ``` docker run hello-world ``` **注意:** Ubuntu(及其他 Linux 发行版)用户,请确保您当前的用户拥有以管理员身份运行 Docker 的权限: ``` sudo groupadd docker sudo gpasswd -a $USER docker sudo usermod -aG docker $USER ``` #### 步骤 1 - 克隆 EMUX 仓库 ``` git clone --depth 1 --single-branch https://github.com/therealsaumil/emux.git ``` #### 步骤 2 - 构建 EMUX docker 卷和镜像 ``` cd emux ./build-emux-volume ./build-emux-docker ``` **注意:** 如果 `build-emux-docker` 失败,请尝试通过禁用 `DOCKER_BUILDKIT` 再次运行 ``` - DOCKER_BUILDKIT=1 docker build -t $OWNERNAME/$IMAGENAME:$TAGNAME \ -f Dockerfile-emux . + DOCKER_BUILDKIT=0 docker build -t $OWNERNAME/$IMAGENAME:$TAGNAME \ -f Dockerfile-emux . ``` #### 步骤 3 - 运行 EMUX! 打开终端,并启动 `emux-docker` 容器: ``` ./run-emux-docker ``` 您将看到一个紫色的 Shell 提示符 `[EMUX-DOCKER 🐳:~$]`。一段时间后,通常会有多个终端连接到该容器。彩色的 Shell 提示符有助于您轻松记住当前所在的位置。 接下来,启动 EMUX `launcher`: ``` [EMUX-DOCKER 🐳:~$] launcher ``` 并选择您想要运行的任何模拟设备。 #### 步骤 4 - 启动模拟设备的用户态进程。 接下来,打开一个新终端并连接到正在运行的 `emux-docker` 容器: ``` ./emux-docker-shell ``` 所有已连接的容器 Shell 都有一个蓝色的 Shell 提示符。调用 `userspace` 命令以启动模拟目标的用户态进程: ``` [emux-docker shell 🐚:~$] userspace ``` 阅读文档以获取更多详细信息。 ## 介绍 ![EMUX](docs/img/emux-docker-banner.png "EMUX") EMUX 固件模拟框架是一系列脚本、内核和文件系统的集合,旨在配合 [QEMU][qemu] 使用,以模拟 ARM 和 MIPS Linux IoT 设备。EMUX 旨在通过尽可能多地虚拟化物理设备来促进 IoT 研究。这是我们最接近真实 IoT VM 的方案。 迄今为止使用 EMUX 成功模拟的设备: * [Damn Vulnerable ARM Router][DVAR] * **Damn Vulnerable MIPS Router (Little Endian) [新增!]** * **Damn Vulnerable MIPS Router (Big Endian) [新增!]** * Trivision NC227WF 无线 IP 摄像头 * [Tenda AC15 Wi-Fi 路由器][emulatingtenda] [(Github 文档)][md-emulatingtenda] * Archer C9 Wi-Fi 路由器 以下设备未包含在公开发布版本中,但它们已成功模拟并用于培训: * D-Link DIR-880L Wi-Fi 路由器 * Netgear Nighthawk R6250 Wi-Fi 路由器 * Netgear Nighthawk R6400 Wi-Fi 路由器 * 新增!Netgear Nighthawk R6700v3 Wi-Fi 路由器 * Cisco RV130 Wi-Fi 路由器 * COMfortel 1200 VoIP 电话 * Linksys EA9500 Wi-Fi 路由器 EMUX 的前身曾用于 Saumil Shah 广受欢迎的 [ARM IoT Exploit Laboratory][armfirmwarelab] 培训课程,学员们在课程中发现了~~四个~~若干个不同 ARM/Linux IoT 设备中的 0-day 漏洞。 ## EMUX 架构 EMUX 是位于 `/emux` 目录中的一组脚本、内核和文件系统集合。它使用 `qemu-system-arm`、`qemu-system-aarch64`、`qemu-system-mips` 和 `qemu-system-mipsel` 来启动虚拟 ARM、ARM64 和 MIPS Linux 环境。`/emux` 目录通过 NFS 导出,以便在 QEMU guest 内部也能访问这些内容。 运行 `qemu-system-arm|aarch64|mips|mipsel` 的主机系统被分配 IP 地址 `192.168.100.1`,而 QEMU guest 则通过 `tap0` 接口被分配 `192.168.100.2`。 ![Architecture](docs/img/emux-architecture.png "EMUX Architecture") EMUX被打包为一个 Docker 镜像。下图展示了 Docker 容器的组织方式: ![Docker Architecture](docs/img/emux-docker.png "EMUX Docker") 该 Docker 镜像包含: * 卷 `harambe`,包含 `/emux` 目录树。(🦍 赞美 Harambe!) * 容器 `emux-docker`。 * 主机上的 `workspace` 目录绑定挂载为容器中的 `/home/r0/workspace`,用于共享文件。 * 在容器内运行的 NFS 服务器,将 `/emux` 目录树提供给在 QEMU 下运行的模拟镜像。 * 使用 `socat` 将端口从主机转发到容器内运行的 QEMU。 ## /emux 目录 `/emux` 目录的组织结构如下: ![Directory Structure](docs/img/emux-dirstructure.png "EMUX Directory Structure") * `firmware/devices`:此文件包含设备定义,每行一个。 * `firmware-extra/devices`:包含未包含在正式发布版本中的额外模拟设备。建议您将自己模拟的设备添加到 `devices-extra` 中。 * `qemuopts`:针对各种类型 QEMU 机的抽象 QEMU 选项定义。 * `run/`:此文件夹包含解析设备配置、预加载 nvram 内容以及最终调用被模拟设备用户态进程所需的脚本。 * `run/launcher`:主脚本。`launcher` 解析 `devices` 文件并显示已注册设备的菜单。选择其中一个设备将依次调用 `qemu-system-arm`,并使用预定义的 QEMU 选项、相应的 Linux 内核和设备注册的提取根文件系统。 * `run/userspace`:一旦内核从 `launcher` 启动,便启动模拟设备的用户态进程。 * `debuglogs`:如果存在,它指示 EMUX 调试日志写入的位置。这在创建新模拟设备进行故障排除时非常有用。 * `template/`:新设备的示例配置和布局。在开始模拟新 IoT 设备时,请复制该模板。 `run/` 目录还包含一些命令,可从主机用于与 EMUX 模拟设备内运行的进程进行交互。 * `emuxhalt`:干净地关闭模拟设备,并卸载所有 NFS 挂载。如果没有干净地关闭,总是存在 NFS 句柄过期的风险。 * `emuxps`:远程枚举在 EMUX 内运行的进程。 * `emuxmaps`:远程转储 EMUX 内运行进程的进程内存布局。 * `emuxnetstat`:枚举 EMUX 内的网络套接字。 * `emuxkill`:远程终止 EMUX 内运行的进程。 * `emuxgdb`:将 `gdb` 附加到 EMUX 内运行的进程。 * `monitor`:连接到 QEMU monitor。 `emuxps`、`emuxmaps` 和 `emuxgdb` 在 [Debugging With EMUX][debuggingwithemux] 教程中有详细说明。 ## 模拟设备的内容 每个模拟设备包含以下文件/目录: * `config`:包含设备名称和描述、ASLR 设置、其根文件系统的位置以及内核启动并将控制权转移给用户态后要执行的命令。 * `nvram.ini`:设备的非易失性内存内容,用于存储配置设置。`nvram.ini` 的内容在调用用户态初始化脚本之前被预加载到模拟 nvram 中。 * `kernel/`:包含一个 Linux 内核(主要通过 Buildroot 编译),以紧密匹配模拟设备的属性,如内核版本、CPU 支持、VM_SPLIT、支持的外设等。 * `rootfs.tar.bz2`:包含从目标设备提取的根文件系统的压缩归档。名称 `rootfs.tar.bz2` 可在 `config` 文件中配置。EMUX 将在第一次调用时自动解压根文件系统。 * `flashmem/flash.tar.bz2`:包含两个 64MB 内存转储文件 `flash0.bin` 和 `flash1.bin` 的压缩归档。这些将显示为一个统一的 128MB MTD Flash 设备。 ## 在 EMUX 中运行模拟设备 下图描述了 EMUX 的每个阶段: ![EMUX Operations](docs/img/emux-operations.png "EMUX Operations") 运行模拟设备有五个步骤: 1. Launcher - 从可用模拟设备列表中选择 2. 选择一个设备并启动其内核及其 hostfs 3. Userspace - 从可用用户态操作列表中选择 4. 启动设备的用户态进程 5. 可选地进入 hostfs shell ### 步骤 1:Launcher 调用 `launcher`。 ![EMUX Launcher Command](docs/img/launcher-command.png "EMUX Launcher Command") 这将显示如下所示的菜单。在此示例中,我们选择 Trivision TRI227WF 无线 IP 摄像头。 ![EMUX Launcher](docs/img/emux-ipcam-launcher.png "EMUX Launcher") ### 步骤 2:启动设备 选择其中一个设备将在 QEMU 下启动它。包含在 Trivision IP 摄像头设备配置 `kernel/` 目录中的内核,在 `qemu-system-arm` 中启动,并使用预构建的 Buildroot 文件系统,称为 `hostfs.ext2`。主机和 guest IP 地址分别分配为 `192.168.100.1` 和 `192.168.100.2`。 ![EMUX Kernel Boot Up](docs/img/02-emux-kernel-boot-up.png "EMUX Kernel Boot Up") `hostfs-arm.ext2`、`hostfs-mips.ext2` 和 `hostfs-mipsel.ext2` 包含几个有用的脚本和工具,用于运行和分析模拟设备。`hostfs` 中的初始化脚本通过 NFS 挂载 `/emux` 目录。因此,`/emux` 的内容由主机和 QEMU guest 共享。 ### 步骤 3:Userspace 您需要连接到正在运行的 `emux-docker` 容器,并在 Shell 提示符下调用 `userspace` 命令。 ![EMUX Userspace Command](docs/img/userspace-command.png "EMUX Userspace Command") 在内部,`userspace` 命令仅使用 SSH `ssh root@192.168.100.2` 连接到 QEMU guest。这将显示如下所示的菜单: ![EMUX Trivision Init](docs/img/03-emux-trivision-init.png "EMUX Trivision Init") ### 步骤 4:启动用户态进程 选择启动设备用户态进程的选项将导致从 `/emux` 内相应的设备配置目录调用 `run-init`。首先,`nvram.ini` 的内容被加载到内核的模拟 nvram 驱动程序中。接下来,使用设备的 `rootfs` 创建一个 `chroot` 环境。最后,在新创建的 `chroot` 环境 `rootfs` 中调用注册的初始化命令,从而启动设备的服务和初始化脚本。 ![EMUX Trivision Started](docs/img/04-emux-trivision-started.png "EMUX Trivision Started") ### 步骤 5:设备启动并准备就绪 一旦设备在 EMUX 中完全“启动”,它就可以进行测试和分析。下图显示了在浏览器中加载的 IP 摄像头管理界面。注意,要访问 `192.168.100.2` 上的内部端口,我们将依赖 `socat` 执行的端口转发。默认情况下,转发以下端口: ``` localhost:20080 -> 192.168.100.2:80 localhost:20443 -> 192.168.100.2:443 localhost:28080 -> 192.168.100.2:8080 ``` 要访问已启动设备的 Web 管理界面,请打开浏览器并导航至 `localhost:28000`。这反过来会将您的请求转发到 `emux-docker` 容器内部的 `192.168.100.2:80`。 ![EMUX Admin Interface](docs/img/06-emux-trivision-browser.png "Trivision Admin Interface") #### 覆盖转发的端口 EMUX 端口转发由 `PORTFWD` 环境变量控制。它是一个包含 `FORWARDED_PORT:INTERNAL_PORT` 对的逗号分隔列表。要覆盖默认端口转发,只需在调用 `run-emux-docker` 之前设置 `PORTFWD` 的内容: ``` export PORTFWD="28000:8000,25800:5800" ./run-emux-docker ``` ## 创建您自己的模拟 IoT 设备 在开始模拟 IoT 设备之前,您需要以下内容: * 对 IoT 设备的详细分析 * CPU (ARMv5/ARMv6/ARMv7/MIPS) * Linux 内核版本 * 提取的 Flash 内存内容(可选) * 从 Flash 内存中提取的根文件系统 * nvram 的内容(可选) * 使用 Buildroot 或 Linux 内核源代码生成兼容的内核 * 一周的故障排除时间! 下图概述了 IoT 设备模拟的整体过程。 ![Adding a new device](docs/img/emux-newdevice.png "Adding a new device涉及的步骤: 1. 复制 `template` 目录以创建新的设备配置。 2. 从源代码编译匹配的内核,并将其放在 `kernel/` 目录中。如果您愿意,也可以符号链接现有内核。 3. 将从设备固件中提取的 `rootfs` 复制到 `rootfs/` 目录中。通常这些是 SquashFS 或 CramFS 文件系统,使用 `binwalk` 或 `unsquashfs` 或 `cramfsck` 解压。或者,您也可以创建根文件系统的压缩 `tar.bz2` 归档。 4. 将提取的 nvram 内容放在 `nvram.ini` 中 5. 如果您希望模拟 MTD flash,请转储设备 Flash 内存的内容,并创建两个名为 `flash0.bin` 和 `flash1.bin` 的 64MB 文件,并将它们放在 `flashmem/` 目录中。或者,您也可以将它们压缩在 `tar.bz2` 归档中。然后,您需要在 `mtdparts` 文件中定义要传递给内核的 MTD 分区布局。 6. 将您希望使用 `LD_PRELOAD` 注入的任何共享库放在 `preload/` 目录中。通常,这些共享库包含某些模拟二进制文件正常工作所需的钩子函数。 7. 使用新填充的设备固件内容编辑 `config` 文件。 8. 在 `devices-extra` 文件中创建新的设备记录。请特别注意 QEMU 命令行选项。 模板提供了以下示例内核。 * `zImage-2.6.39.4-vexpress` ARMv7 CPU 在 `vexpress-a9` 板上。 * `zImage-2.6.31.14-realview-rv130-nothumb` ARMv6 CPU 在 `realview-eb` 板上。 * `zImage-2.6.31-versatile-nothumb` ARMv5 CPU 在 `versatilepb` 板上。 * `zImage-2.6.29.6-versatile` ARMv5 CPU 在 `versatilepb` 板上。 * `zImage-2.6.28-versatile-nothumb` ARMv5 CPU 在 `versatilepb` 板上。 * `vmlinux-3.18.109-malta-be` MIPS32 CPU (big endian) 在 `malta` 板上。[新增!] * `vmlinux-3.18.109-malta-le` MIPS32 CPU (little endian) 在 `malta` 板上。[新增!] 但是,鼓励从源代码构建兼容的内核。 ### EMUX 活动日志文件 2021 年 6 月发布的 EMUX 带有启用活动日志的功能。这在向 EMUX 添加新设备时排除错误非常方便。要启用日志记录,请编辑 `/emux/debuglogs` 文件: ``` # 取消 logpath= 的注释以启用 EMUX 和 QEMU 控制台输出日志。 # 应仅取消一个 logpath= 的注释。 # logpath=/home/r0/workspace/logs/ #logpath=/emux/logs/ ``` 建议使用 `/home/r0/workspace/logs`,因为 `workspace` 目录在容器和主机之间共享。 ## 公开场合中的 EMUX (ARMX) #### 2019 年 11 月 7 日在 [Countermeasure 2019][cmeasurecon] 上的演讲。👇
INSIDE EMUX - Countermeasure 2019 from Saumil Shah
#### 2019 年 10 月 16 日在 [HITB+Cyberweek][HITB] 上的发布演讲。👇
Introducing EMUX from Saumil Shah
#### 2021 年 6 月 15 日发布 EMUX Docker。👇
Announcing EMUX Docker - DC11332 from Saumil Shah
### ARM IoT 固件实验室 - 新培训 ### EMUX 文档 - 教程:[Debugging With EMUX][debuggingwithemux] [(Github 文档)][md-debuggingwithemux] - 教程:[Emulating the D-Link DCS-935L WiFi Camera - MIPS][emulatingdcs935] [(Github 文档)][md-emulatingdcs935] - 案例研究:[Emulating the Tenda AC15 Router][emulatingtenda] [(Github 文档)][md-emulatingtenda] - 案例研究:[Extracting the Tenda AC15 Firmware][fw-extraction] [(Github 文档)][md-fw-extraction] ### 结束 EMUX 根据 Mozilla Public License v2.0 (MPLv2) 授权。
标签:Apple Silicon, ARM32, ARM64, ARM架构, ARM模拟, Cutter, Docker容器, Hakrawler, IoT安全, MIPS架构, MIPS模拟, QEMU, 云资产清单, 仿真框架, 内联执行, 固件分析, 固件模拟, 大端序, 小端序, 嵌入式系统, 攻击面发现, 漏洞分析, 灰盒测试, 物联网安全, 系统模拟, 网络仿真, 网络安全, 请求拦截, 路径探测, 身份验证强制, 逆向工程, 隐私保护