《IOT废物学习之路》(5)–修复固件运行环境

虽然可以利用firmadyne模拟运行固件,但是并不是所有的固件都能模拟运行成功,有的固件需要依赖于硬件,qemu无法完全模拟。所以需要修复固件的运行环境,从而模拟固件运行。

固件下载地址

https://support.dlink.com/resource/products/dir-605l/REVA/

image-20231013080601658

利用firmadyne模拟运行一下试试

1
sudo docker run  --network host --privileged -it --rm -e USER=root -v $(pwd):$(pwd) asdqwe876/iot_analyze

启动容器并挂载当前盘符。

将固件复制到firmadyne

1
cp /home/zhuyuan/IOT/05/dir605L_FW_113.bin ./

image-20231013083248582

设置id

1
project_id=1

解压固件

1
python3 ./sources/extractor/extractor.py -b Netgear -sql 127.0.0.1 -np -nk "firmware.bin" images

识别cpu

1
./scripts/getArch.sh ./images/$project_id.tar.gz

存储数据库

1
./scripts/tar2db.py -i $project_id -f ./images/$project_id.tar.gz

创建qemu镜像

1
./scripts/makeImage.sh $project_id

设置网络接口

1
./scripts/inferNetwork.sh $project_id

image-20231013084615433

这一步骤上Interfaces为空代表模拟失败。这就说明firmadyne并不能模拟运行所有的固件,尤其是那些需要和硬件进行交互的固件。

从另一个方面想,模拟固件运行的实质就是把固件的web程序运行起来,模拟失败的原因就是web程序没有被正确运行起来。所以需要针对web程序报错的原因以及如何修复运行环境。

首先利用binwalk提取固件的文件系统。

1
2
3
4
sudo docker run -it --rm \
-v $(pwd):$(pwd) \
asdqwe876/iot_analyze \
binwalk --run-as=root -C $(pwd) -Mer $(pwd)/dir605L_FW_113.bin

image-20231013085338801

image-20231013085423159

使用命令:

1
find ./ -name boa

定位该固件的web程序。Boa程序是轻量级的web服务器程序,常见于嵌入式系统中。常见路径为bin/boa

同时在etc/boa下发现boa的密码配置文件,可以直接获取到boa加密后的密码。

image-20231013090317208

直接使用命令模拟运行程序。

image-20231013090851564

使用idaboa程序进行逆向分析。

image-20231013093854272发现会根据apmib_init函数返回的值来判断是否跳转,如果相等则跳转,不相等则继续执行,输出报错。

apmib_init函数是从flash中读取mib值到RAM中,模拟环境中没有flash硬件,所以会读取失败。

可以通过修改把bnezbeqz,这样即使读取失败,也能正确执行读取成功之后的内容。

13

但是这个程序利用ida自带的patch不会成功。就用编辑器修改字节码也可以。

bnez(0x14)命令改成beqz(0x10)

image-20231013094634924

修改之后运行

image-20231013094951608

经过调试,发现是apmib_get函数导致的错误。

image-20231013101710873

两个Create chklist file error!不影响。

重新伪造apmib_initapmib_get劫持代码。返回正确值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include<stdio.h>
#include<stdlib.h>

#define MIB_IP_ADDR 170
#define MIB_HW_VER 0x250
#define MIB_CAPTCHA 0x2C1

int apmib_init(void)
{
return 1;
}

int fork(void)
{
return 0;
}

void apmib_get(int code,int* value)
{
switch(code)
{
case MIB_HW_VER:
*value = 0xF1;
break;
case MIB_IP_ADDR:
*value = 0x7F000001;
break;
case MIB_CAPTCHA:
*value = 1;
break;
}
return 1;
}

编译为so文件。

1
mips-linux-gnu-gcc -Wall fPIC -shared apmib.c -o apmib-ld.so

利用LD_PRELOAD参数指定劫持so,这样当boa执行到apmib_initapmib_get时,就调用到apmib-ld.so里的函数,从而顺利运行。

image-20231013103733133

但是访问时,程序又崩溃了,自动跳转到/Basic/Wizard_Easy_LangSelect.asp

image-20231013104259561

查看该文件ASP代码,通过文件名猜出是选择页面语言,尝试从硬件设备读取语言。

1
cat Basic/Wizard_Easy_LangSelect.asp

image-20231013104509607

修该first.asp,不判断系统语言,直接进入。

image-20231013104625834

修改后

image-20231013104707489

成功进入web页面

image-20231013105007017