D-link M30固件模拟

m30固件模拟
2026-01-11 13:15
31155

最近在学习IOT的固件,所以找了dlink的M30固件来进行模拟,首先从官网上下载1.10版本,因为固件是加密过的,需要解密,然后再进行模拟。

固件解密

github上已经有了解密dlink固件的程序[GitHub - devttys0/delink](https://github.com/devttys0/delink.git),下载下来,使用rust进行编译最后生成delink,然后解密。

./delink M30A1_FW110B02.bin m30_110_dec.bin

解密完成后,使用binwalk来提取固件。

binwalk -Me m30_110_dec.bin

提取成功之后,可以得到squashfs文件系统。

image.png

固件模拟

固件分析

在模拟之前,需要先大概过一下这个固件的关键信息,如web服务,启动脚本等。

为了方便,我使用firmwalkersquashfs-root文件夹进行扫描。

./firmwalker.sh ./squashfs-root

完成之后查看扫描结果,看能否发现一些关键服务以及脚本。

image.png

发现了一个关键的web服务程序httpd。同时需要留意一下以下几个目录:bin, sbinusr/binusr/sbin,提取出来的可执行程序可能会指向不正确的链接,如/dev/null,需要修复一下,让它们指向busybox。脚本如下:

#!/bin/sh
# 批量修改 ./bin/、./sbin/、./usr/bin/、./usr/sbin/ 下指向 /dev/null 的软链接
# 定义需要处理的目录和对应的busybox路径
TARGETS="
./bin ../bin/busybox
./sbin ../bin/busybox
./usr/bin ../../bin/busybox
./usr/sbin ../../bin/busybox
"

# 遍历每一行配置
echo "$TARGETS" | while read dir busybox_link; do
    # 跳过空行
    [ -z "$dir" ] && continue

    # 检查目录是否存在
    if [ ! -d "$dir" ]; then
        echo "警告:目录 $dir 不存在,跳过该目录"
        continue
    fi

    echo "========================================"
    echo "开始处理目录:$dir(链接指向:$busybox_link)"
    # 遍历目录下所有文件
    for file in "$dir"/*; do
        # 跳过子目录
        [ -d "$file" ] && continue

        # 检查是否是指向 /dev/null 的软链接
        if [ -L "$file" ] && [ "$(readlink "$file")" = "/dev/null" ]; then
            # 删除旧链接
            rm -rf "$file"
            # 创建新链接
            ln -s "$busybox_link" "$file"
            echo "  已修改:$file -> $busybox_link"
        fi
    done
done

echo -e "\n所有目录处理完成!"

启动web服务

httpdaarch64小端,所以我用qemu-system-aarch64来模拟,模拟之前先配置主机网络。

sudo tunctl -t tap0  
sudo ifconfig tap0 192.168.0.4/24 up 

然后启动qemu虚拟机

qemu-system-aarch64 \                                                                     
    -M virt -m 4G -cpu cortex-a72 -smp 2 \
    -bios QEMU_EFI.fd \
    -drive id=hd0,media=disk,if=none,file=debian-10-generic-arm64-20201207-477.qcow2 \
    -device virtio-scsi-pci \
    -device scsi-hd,drive=hd0 \
    -net nic -net tap,ifname=tap0,script=no,downscript=no -nographic

启动之后为虚拟机添加网卡并配置ip。

brctl addbr br0
brctl addif br0 enp0s1
ip link set enp0s1 up
ip link set br0 up
ifconfig br0 192.168.0.3/24

我们将squashfs-root文件夹打包传到虚拟机中,并启动httpd

image.png
这里报错了,我们找一下init_csman_ipc_client函数,发现在libcsman.so中。

image.png
libcsman.so拖到ida中,查找字符串。

image.png
定位到函数位置。

image.png
可以看到这里调用了一个shmget,返回值小于0,通过查询,我们得到如下信息:

  • shmget 是 Linux 系统中 System V 共享内存 的核心函数,作用是创建 / 获取一个共享内存段的标识符,进程间可通过这个标识符访问同一块内存,实现高效数据通信。

  • 参数1为共享内存的唯一标识(键值),参数2为共享内存段的大小(字节),参数3为

    标志位,组合使用:

     IPC_CREAT:创建新的共享内存(不存在则创建,存在则获取);

     IPC_EXCL:配合 IPC_CREAT 使用,若内存已存在则报错(确保创建新内存);

    权限位:如 0666(可读可写,和文件权限一致)。

这里可以看到标志位为428,八进制为0666,说明常见的标志位(如 IPC_CREATIPC_EXCL)未被包含,说明这段代码仅尝试获取已存在的共享内存(key=5678),若不存在则返回错误。

既然这里仅仅是尝试获取,那应该有其他地方负责创建这个共享内存,但是libcsman.so中只有这里一处调用了shmget,我们去其他地方查找。

image.png
发现这个 csmanuds程序比较可疑,我们把它拖到ida中分析。仅仅找到一处对于shmget函数的引用。

image.png
这里我们看到第三个参数是950,等价于八进制 1666,由 IPC_CREAT(512) + 0666(438) 组成,用来创建key=5678、大小 8 字节、权限 0666 的共享内存段。

分析到这里,发现csmanuds程序应该在httpd之前执行,但是这个程序可能会需要参数。我们去firmwalker的结果中查找蛛丝马迹,并没有查到,可能是在某个启动脚本中。

image.png
找到csman_server.sh这个脚本,查看具体内容。

image.png
我们将这个脚本执行一下。

image.png
我们暂时不管这些错误,启动httpd。

image.png
我们查看目录usr/www.d是否存在,

image.png
发现目录并不存在,我们去查找是否在哪个脚本中使用了usr/www.d

image.png
可以看到uitar.sh是负责解压web主目录的,手动创建/usr/www.d目录,并将/boot/www.tgz解压到www.d目录下,

在之前执行csman_server.sh时显示csmanuds会访问/tmp/csman,所以我们也将/usr/www.d/*dat拷贝至./tmp/csman/下,

既然涉及到csman,那么我们重新执行csman_server.sh,之后执行httpd

image.png

image.png
查看端口,80端口已经启动。

image.png
访问web管理页面。

image.png
空密码登录之后重新设置密码再次登录。

image.png
最后感谢SeBao老师的指导和支持,感谢IOTsec-Zone社区。

参考

[GitHub - devttys0/delink

分享到

参与评论

0 / 200

全部评论 1

阿萨姆369的头像
good,nice,it helps me
2026-02-04 23:31
阿萨姆369的头像
a lot
2026-02-05 00:14
投稿
签到
联系我们
关于我们