IOT固件调试环境搭建

本文将简单介绍一下如何开始搭建一个固件调试环境并且使用gdb来调试

系统

文中所用的系统是AttifyOS4,下载后用7zip解压并安装到虚拟机中

Release AttifyOS 4.0 OVA · AttifyOS/AttifyOS · GitHub

工具

binwalk

下载并导入AttifyOS4系统后我们需要下载binwalk

AttifyOS 4.0 里预装的是 binwalk 2.3.3,是snap 包的形式,我选择删除然后下载源码来安装,也可选择使用自带的

删除snap形式的binwalk

sudo snap remove binwalk

hash -r

which -a binwalk

安装系统依赖

sudo apt update

sudo apt install -y git build-essential locales \

mtd-utils gzip bzip2 tar lhasa p7zip p7zip-full cabextract \

cramfsswap squashfs-tools zlib1g-dev liblzma-dev liblzo2-dev \

sleuthkit default-jdk lzop srecord cpio unyaffs

下载binwalk

此处我给出指令的路径是按照我自己存放的路径来给的

mkdir -p /home/attify/Desktop/iot/binwalk

cd /home/attify/Desktop/iot/binwalk

wget https://github.com/ReFirmLabs/binwalk/archive/refs/tags/v2.3.4.tar.gz

tar xzf v2.3.4.tar.gz

cd /home/attify/Desktop/iot/binwalk/binwalk-2.3.4

sudo python3 setup.py install

如果缺少sasquatch

cd /tmp

git clone --quiet --depth 1 --branch master https://github.com/devttys0/sasquatch

cd sasquatch

wget https://github.com/devttys0/sasquatch/pull/51.patch && patch -p1 < 51.patch

sudo ./build.sh

qemu

安装qemu

mkdir -p /home/attify/Desktop/iot/qemu

cd /home/attify/Desktop/iot/qemu

wget https://download.qemu.org/qemu-6.0.0.tar.xz

tar xvJf qemu-6.0.0.tar.xz

sudo apt-get install -y htop gcc g++ libglib2.0-dev libpixman-1-dev make libgtk-3-dev ninja-build

cd /home/attify/Desktop/iot/qemu/qemu-6.0.0

mkdir build

cd build

../configure --gdb=/usr/bin/gdb --enable-debug --prefix=/usr/local

make -j4

sudo make install

qemu-system

我们要使用qemu-systm来仿真,使用qemu-user的话环境不完整

下载图中三个

Index of /~aurel32/qemu/armhf

我存放的路径是

备份

mkdir -p /home/attify/Desktop/iot/backups

chmod 700 /home/attify/Desktop/iot/backups

cp -v debian_wheezy_armhf_standard.qcow2 /home/attify/Desktop/iot/backups/

cp -v vmlinuz-3.2.0-4-vexpress initrd.img-3.2.0-4-vexpress \

/home/attify/Desktop/iot/backups/

chmod 444 /home/attify/Desktop/iot/backups/*.qcow2

ls -l /home/attify/Desktop/iot/backups/

仿真指令,如何使用我给的脚本则不需要这段指令启动

qemu-system-arm \

-M vexpress-a9 \

-kernel vmlinuz-3.2.0-4-vexpress \

-initrd initrd.img-3.2.0-4-vexpress \

-drive if=sd,file=debian_wheezy_armhf_standard.qcow2 \

-append "root=/dev/mmcblk0p2 console=ttyAMA0" \

-net nic \

-net tap,ifname=tap0,script=no,downscript=no \

-nographic

下文我会给出脚本来一键启动和关闭

gdbserver

为了方便调试我们需要安装对应指令集下静态编译的gdbserver,此处我们需要的是

gdbserver-7.7.1-armhf-eabi5-v1-sysv

HatLab Tools Library: 海特实验室IoT安全工具/环境整合 - Gitee.com

我存放的路径如图所示

mygdbinit

建在 gdb 的当前工作目录

cd ~/Desktop/iot/Firmware/SR20/_tpra_sr20v1_us-up-ver1-2-1-P522_20180518-rel77140_2018-05-21_08.42.04.bin.extracted

cat > mygdbinit <<'EOF'

---- 架构与字节序 ----

set architecture arm

set endian little

---- 让 gdb 去宿主机上的解包目录找固件的库符号 ----

set sysroot ./squashfs-root

set solib-search-path ./squashfs-root/lib:./squashfs-root/usr/lib

---- 允许对尚未加载的库/函数下断点 ----

set breakpoint pending on

---- daemon 常 fork,跟住子进程 ----

set follow-fork-mode child

set detach-on-fork off

---- 连接 QEMU guest 里运行的 gdbserver ----

target remote 10.10.10.2:12345

EOF

cat mygdbinit

固件

本文使用到的固件是SR20(US)_V1_180518

Download for SR20 | TP-Link

使用binwalk对文件系统进行提取

binwalk -Me tpra_sr20v1_us-up-ver1-2-1-P522_20180518-rel77140_2018-05-21_08.42.04.bin

进入提取出来的文件系统中查看是什么类型,随便file一个就行

cd /home/attify/Desktop/iot/Firmware/SR20/_tpra_sr20v1_us-up-ver1-2-1-P522_20180518-rel77140_2018-05-21_08.42.04.bin.extracted/squashfs-root

file ./usr/bin/tddp

我们可以发现是一个 ARM 32 位小端,动态链接 uClibc,符号表已剥离的ELF可执行文件

调试

启动脚本

复制代码
sudo tee /usr/local/bin/iot-arm >/dev/null <<'EOF'
#!/bin/bash
set -e
DIR="$HOME/Desktop/iot/qemu/qemu-system/armhf"
BASE="$HOME/Desktop/iot/backups/debian_wheezy_armhf_standard.qcow2"
TAP_IP="10.10.10.1/24"
cd "$DIR"

[ -f "$BASE" ] || { echo "base 镜像缺失: $BASE"; exit 1; }
[ -f work.qcow2 ] || qemu-img create -f qcow2 -b "$BASE" -F qcow2 work.qcow2

if ! ip link show tap0 &>/dev/null; then
sudo ip tuntap add dev tap0 mode tap user "$USER"
sudo ip link set tap0 up
fi
# 幂等:缺地址才加,已有同网段则跳过
ip -4 addr show tap0 | grep -q "10.10.10.1/24" || sudo ip addr add "$TAP_IP" dev tap0

exec qemu-system-arm \
-M vexpress-a9 \
-kernel vmlinuz-3.2.0-4-vexpress \
-initrd initrd.img-3.2.0-4-vexpress \
-drive if=sd,file=work.qcow2 \
-append "root=/dev/mmcblk0p2 console=ttyAMA0" \
-net nic -net tap,ifname=tap0,script=no,downscript=no \
-nographic
EOF
sudo chmod +x /usr/local/bin/iot-arm

指令

iot-arm # 启动qume-system-arm

关闭脚本

复制代码
sudo tee /usr/local/bin/iot-arm-stop >/dev/null <<'EOF'
#!/bin/bash
# 关闭 Attify 宿主机上运行的 qemu-system-arm
set -u

PATTERN="${PATTERN:-qemu-system-arm}"
GUEST_IP="${GUEST_IP:-10.10.10.2}"
GUEST_USER="${GUEST_USER:-root}"
TAP_IF="${TAP_IF:-tap0}"

GRACE="${GRACE:-5}" # 发完 poweroff 后等 guest 收尾的秒数
WAIT_SOFT="${WAIT_SOFT:-20}" # 等 QEMU 自然退出的上限
WAIT_TERM="${WAIT_TERM:-10}" # 等 SIGTERM 生效的上限

FORCE=0
DOWN_TAP=0

SSH_OPTS=(-o StrictHostKeyChecking=no
-o UserKnownHostsFile=/dev/null
-o ConnectTimeout=5
-o NumberOfPasswordPrompts=1
-o LogLevel=ERROR
-o HostKeyAlgorithms=+ssh-rsa
-o PubkeyAcceptedKeyTypes=+ssh-rsa)

usage() {
cat <<'EOT'
用法: iot-arm-stop [选项]
-f, --force 跳过 guest 正常关机,直接终止 QEMU
--down-tap 同时删除 tap0(默认保留,下次启动更快)
-h, --help 显示帮助

环境变量: PATTERN / GUEST_IP / GUEST_USER / TAP_IF / GRACE
EOT
}

qemu_pids() {
pgrep -f "$PATTERN" 2>/dev/null | grep -vx -e "$$" -e "${PPID:-0}" || true
}

alive() { [ -n "$(qemu_pids)" ]; }

down_tap() {
ip link show "$TAP_IF" &>/dev/null || return 0
echo "→ 删除 $TAP_IF"
sudo ip link set "$TAP_IF" down 2>/dev/null || true
sudo ip tuntap del dev "$TAP_IF" mode tap 2>/dev/null \
|| echo " (删除失败,忽略)"
}

while [ $# -gt 0 ]; do
case "$1" in
-f|--force) FORCE=1 ;;
--down-tap) DOWN_TAP=1 ;;
-h|--help) usage; exit 0 ;;
*) echo "未知参数: $1" >&2; usage; exit 2 ;;
esac
shift
done

if ! alive; then
echo "没有运行中的 $PATTERN"
[ "$DOWN_TAP" = 1 ] && down_tap
exit 0
fi

echo "发现 QEMU 进程: $(qemu_pids | tr '\n' ' ')"

# ---- 1) 尽力让 guest 自己干净关机 ----
if [ "$FORCE" = 0 ]; then
if ssh "${SSH_OPTS[@]}" "$GUEST_USER@$GUEST_IP" 'sync' 2>/dev/null; then
echo "→ guest 磁盘已同步,发送 poweroff"
ssh "${SSH_OPTS[@]}" "$GUEST_USER@$GUEST_IP" 'poweroff' &>/dev/null &
sleep "$GRACE"
else
echo "→ 连不上 guest(sshd 未起 / 网络不通 / 取消输密码),跳过正常关机"
fi
fi

# ---- 2) 等 QEMU 自己退出(部分内核 poweroff 会让 QEMU 退出)----
for _ in $(seq "$WAIT_SOFT"); do
alive || break
sleep 1
done

# ---- 3) SIGTERM(QEMU 会正常关闭块设备、刷缓存)----
if alive; then
echo "→ QEMU 仍在运行,发送 SIGTERM"
kill -TERM $(qemu_pids) 2>/dev/null
for _ in $(seq "$WAIT_TERM"); do
alive || break
sleep 1
done
fi

# ---- 4) 最后的 SIGKILL ----
if alive; then
echo "→ SIGTERM 无效,强制 SIGKILL"
kill -KILL $(qemu_pids) 2>/dev/null
sleep 1
fi

if alive; then
echo "✗ 无法终止,请手动检查: $(qemu_pids | tr '\n' ' ')" >&2
exit 1
fi

echo "✓ QEMU 已关闭"
[ "$DOWN_TAP" = 1 ] && down_tap
exit 0
EOF

sudo chmod +x /usr/local/bin/iot-arm-stop

指令

iot-arm-stop # 正常关:通知 guest 落盘 → 终止 QEMU

iot-arm-stop --down-tap # 顺便删掉 tap0(宿主机要断网/重配时用)

iot-arm-stop --force # guest 完全卡死、ssh 不通时直接终止

初次启动

启动qemu-system

在终端中输入下列指令

iot-arm

用户名和密码是root

将gdbserver放入文件系统,打包送入qemu

scp ~/Desktop/iot/arm/gdbserver-7.7.1-armhf-eabi5-v1-sysv \

root@10.10.10.2:/root/squashfs-root/tmp/

guest 内赋权

ls -l /root/squashfs-root/tmp/

chmod +x /root/squashfs-root/tmp/gdbserver-7.7.1-armhf-eabi5-v1-sysv

ls -l /root/squashfs-root/tmp/

使用chroot将根目录变为固件文件系统

cd /root

mkdir -p ./squashfs-root/proc ./squashfs-root/sys ./squashfs-root/dev

mount -t proc proc ./squashfs-root/proc

mount -t sysfs sysfs ./squashfs-root/sys

mount --rbind /dev ./squashfs-root/dev

chroot ./squashfs-root /bin/sh

进 chroot 运行

chroot /root/squashfs-root /bin/sh

/tmp/gdbserver-7.7.1-armhf-eabi5-v1-sysv :12345 /usr/bin/tddp

AttifyOS连 gdb

cd ~/Desktop/iot/Firmware/SR20/*.extracted

gdb-multiarch -q ./squashfs-root/usr/bin/tddp -x mygdbinit

关闭qemu-system

AttifyOS中使用下列指令即可

iot-arm-stop

日常使用

启动qemu

iot-arm

进 chroot 运行

chroot /root/squashfs-root /bin/sh

/tmp/gdbserver-7.7.1-armhf-eabi5-v1-sysv :12345 /usr/bin/tddp

AttifyOS连 gdb

cd ~/Desktop/iot/Firmware/SR20/*.extracted

gdb-multiarch -q ./squashfs-root/usr/bin/tddp -x mygdbinit

关闭qemu-system

AttifyOS中使用下列指令

iot-arm-stop

相关推荐
Alinket18 小时前
当 AI 走进传感器:嵌入式人工智能如何重构设备智能
人工智能·物联网·重构·健康医疗·无线通信·智能硬件·iot
TDengine (老段)7 天前
TDgpt 概览 — AI 增强的时序数据库
大数据·数据库·人工智能·物联网·时序数据库·iot·tdengine
sibo_yzm7 天前
谁动了底层的工艺参数?Kepware+OPM-820 双剑合璧实现数据权限管控
mqtt·iot·modbus tcp·opc·kepware·上海泗博
DreamLife☼8 天前
Agent的典型应用场景深度解析
自动驾驶·agent·iot·工业·智慧交通·医疗健康
会周易的程序员8 天前
aiDgeController软PLC控制通讯协议文档
c++·物联网·网关·iot·ipc·进程间通讯
jianqiang.xue9 天前
ESP-IDF保姆级入门23|MQTT物联网通信全解:发布订阅模式/QoS等级/遗嘱消息/主题设计/断线重连,掌握工业级标准消息通信
stm32·单片机·mcu·物联网·51单片机·iot
jianqiang.xue9 天前
ESP-IDF保姆级入门29|FreeRTOS任务管理与调度全解:任务创建/状态切换/优先级调度/双核负载均衡/实时性优化,掌握嵌入式多任务编程核心
stm32·单片机·mcu·物联网·51单片机·iot
jianqiang.xue9 天前
ESP-IDF保姆级入门22|WiFi联网与网络编程全解:STA/AP双模式/TCP-UDP Socket/HTTP服务端/自动重连,掌握工业级可靠网络通信
人工智能·stm32·单片机·mcu·物联网·51单片机·iot
pnoker10 天前
IoT DC3 概念解读:把设备抽象成一套语义模板——位号、指令、事件与面向智能体的设备建模
java·人工智能·物联网·iot·dc3