修复路由器程序运行环境+远程调试

前言

当搭建好了QEMU环境后,就会想到运行路由器中的程序(如路由器中的web服务器),但可能会遇到路由器相关硬件模块缺失导致应用程序启动失败的情况

本文将以D-Link DIR-605L(FW_113)路由器中的web应用程序boa为例子。

修复路由器程序的执行流程大致如下。

  • 运行程序,定位导致程序异常的函数
  • 分析导致异常的函数,编写一个具有相同功能的函数,在函数中伪造执行流程和数据,并将编写的函数封装成一个新的动态库
  • 使用LD_PRELOAD 环境变量加载新的动态库来劫持目标程序中的异常函数,使目标程序执行动态库中的函数

固件分析

首先下载固件

使用binwalk提取固件中的文件系统,然后提取/bin/boa文件到桌面

1
2
3
4
iot@research:~/Desktop/DIR/DIR605/DIR-605L_FIRMWARE_1.13$ binwalk -Me dir605L_FW_113.bin 
iot@research:~/Desktop/DIR/DIR605/DIR-605L_FIRMWARE_1.13$ ls
dir605L_FW_113.bin _dir605L_FW_113.bin.extracted
iot@research:~/Desktop/DIR/DIR605/DIR-605L_FIRMWARE_1.13$ cp _dir605L_FW_113.bin.extracted/squashfs-root-0/bin/boa ~/Desktop/

编写劫持函数动态库

获取错误信息,定位异常函数。初次运行boa的错误提升信息如下

1
2
3
4
iot@research:~/Desktop/DIR/DIR605/DIR-605L_FIRMWARE_1.13/fmk/rootfs$ qemu-mips -L . ./bin/boa 
./bin/boa: cache '/etc/ld.so.cache' is corrupt
Initialize AP MIB failed!
Could not chdir to "/etc/boa": aborting

使用IDA pro对boa进行分析,搜索错误提升字符串"Initialize AP MIB failed!",在执行puts函数前下断点,发现在调用apmib_init函数的时候,如果返回值为0,就会报错

1
2
if ( !apmib_init() )
return puts("Initialize AP MIB failed!");

分析发现函数apmib_init来自于动态链接库apmib.so。

1
2
3
4
5
6
iot@research:~/Desktop/DIR/DIR605/DIR-605L_FIRMWARE_1.13/fmk/rootfs$ grep -r  apmib_init
Binary file apmib-ld.so matches
Binary file bin/boa matches
Binary file bin/flash matches
Binary file bin/setfirewall matches
Binary file lib/apmib.so matches

然后ida打开apmib.so,分析apmib_init函数,通过静态反编译和动态调试对函数代码进行分析,apmib_init函数内的代码处理流程对模糊测试没有影响,因此,可以伪造apmib_init函数直接返回值1,让程序正常执行下去

根据对异常函数apmib_init的分析,编写新的apmib_init函数,代码如下:

1
2
3
4
5
6
7
8
#define MIB_IP_ADDR 170
#define MIB_HW_VER 0x250
#define MIB_CAPTCHA 0x2c1
#include<stdio.h>
#include<stdlib.h>
int apmib_init(void){
return 1;
}

使用如下命令编译生成动态库apmib-ld.so

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

运行测试

将编译好的apmib-ld.so动态链接库复制到路由器的根目录文件系统下

使用LD_PRELOAD环境变量加载apmib-ld.so,劫持apmib.so 中的apmib_init函数,命令如下

1
2
3
4
5
iot@research:~/Desktop/DIR/DIR605/DIR-605L_FIRMWARE_1.13/fmk/rootfs$ sudo chroot .   ./qemu-mips-static -E LD_PRELOAD="/apmib-ld.so"  ./bin/boa
Create chklist file error!
Create chklist file error!
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
Segmentation fault

报错Create chklist file error!

可以看到尽管我们修复了"Initialize AP MIB failed!",但程序还是崩溃。在apmib_init函数那里下断点,用IDA远程调试或者GDB调试,发现在程序执行到apmib_get()函数的时候程序崩溃

image-20240815160944390

因此我们还需要劫持apmib_get函数,查看apmib.so中的apmib_get 函数的汇编代码,通过分析代码,将要劫持的函数整理如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#define MIB_IP_ADDR 170
#define MIB_HW_VER 0x250
#define MIB_CAPTCHA 0x2c1
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;
}

为了方便调试,我们吧boa中的fork函数一起劫持掉,形成最终的劫持代码如下

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
#define MIB_IP_ADDR 170
#define MIB_HW_VER 0x250
#define MIB_CAPTCHA 0x2c1
#include<stdio.h>
#include<stdlib.h>
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;
}

使用命令编译最终的apmib.c生成apmib-ld.so

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

将生成的apmib-ld.so复制到根目录下,然后使用下面命令运行

1
sudo chroot .   ./qemu-mips-static -E LD_PRELOAD="/apmib-ld.so"  ./bin/boa

然后可以看到boa已经开始运行了,并且打开了一个80端口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Create chklist file error!
Create chklist file error!
hard ver is
Create f/w version file error!
Create chklist file error!
boa: server version Boa/0.94.14rc21
boa: server built May 25 2012 at 13:03:21.
boa: starting server pid=44549, port 80
Unsupported ioctl: cmd=0x89f0
device ioctl:: Function not implemented
Unsupported ioctl: cmd=0x89f0
device ioctl:: Function not implemented
smart 404 ----------------------------------
Unsupported ioctl: cmd=0x89f0
device ioctl:: Function not implemented
Unsupported ioctl: cmd=0x89f0
device ioctl:: Function not implemented
Unsupported ioctl: cmd=0x89f0
device ioctl:: Function not implemented
Unsupported ioctl: cmd=0x89f0
1
2
3
4
5
6
7
8
9
10
11
12
iot@research:~/Desktop/DIR/DIR605/DIR-605L_FIRMWARE_1.13/fmk/rootfs$ netstat -ano | grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN off (0.00/0/0)
unix 2 [ ACC ] STREAM LISTENING 55827 /var/run/docker/libnetwork/680160b12e88.sock
unix 2 [ ACC ] STREAM LISTENING 56099 /run/containerd/s/9e47177e2200ecf7b6b185485055824fbcfc68077754130259948bfa27002005
unix 3 [ ] STREAM CONNECTED 75809
unix 3 [ ] STREAM CONNECTED 74801 /run/user/1000/bus
unix 3 [ ] STREAM CONNECTED 49380
unix 3 [ ] STREAM CONNECTED 112808
unix 3 [ ] STREAM CONNECTED 76480
unix 3 [ ] STREAM CONNECTED 75380
unix 3 [ ] STREAM CONNECTED 45807
unix 3 [ ] STREAM CONNECTED 75780

IDA+qemu远程调试

在虚拟机运行下面代码即可打开一个可以供ida链接的远程端口

1
sudo chroot .   ./qemu-mips-static -E LD_PRELOAD="/apmib1-ld.so"  -g 12345 ./bin/boa 

然后IDA在对应的地址下断点

image-20240815161210558

然后调试器选择

image-20240815161254780

在Debug->process option选择对应虚拟机的IP和端口还有程序

image-20240815161356312

然后F9运行,F4运行到断点,就能成功下断点了

image-20240815161529952