技术社区
安全培训
技术社群
积分商城
先知平台
漏洞库
历史记录
清空历史记录
相关的动态
相关的文章
相关的用户
相关的圈子
相关的话题
注册
登录
栈溢出从复现到挖掘-CVE-2018-18708漏洞复现详解
vlan911
发表于 浙江
IoT安全
370浏览 · 2025-05-06 03:07
返回文档
固件和poc可在github下载:
https://github.com/Snowleopard-bin/pwn/tree/master/IOT/Tenda_CVE-2018-16333
首先查看程序开启的保护机制,可以发现没有开启PIE和canary保护
本文介绍如何启动quem用户级调试以及qemu系统级调试
qemu用户级调试
使用binwalk解压固件
Bash
复制代码
后续所有指令均是进入到/_US_AC15V1.0BR_V15.03.05.19_multi_TD01.bin.extracted/squashfs-root文件夹去执行的,该文件夹为固件核心文件夹
查看文件架构,发现是arm小端架构的
需要手动复制一下web目录,否则运行程序会出现访问404的情况
Bash
复制代码
修改网卡,主要是增加网卡,需要先安装网卡管理工具,然后直接运行./net.sh即可
apt-get install bridge-utils
apt-get install uml-utilities
net.sh
直接qemu启动的话,会报错,提示缺少文件夹,同时进程中断或一直等待,忘记保存图片了,大家可以自己试一下看看报错信息是什么样子的
首先手动创建文件夹
然后使用ida打开存放在/_US_AC15V1.0BR_V15.03.05.19_multi_TD01.bin.extracted/squashfs-root/bin/httpd文件,搜索字符串 Welcome ,这一步是为了patch
双击进入到,在aYesWelovelinux函数这里按键盘 x 查看交叉引用
进入后,发现 里面是个条件判断语句
程序运行到第33行时,因为check_network返回的值,程序进入了死循环(这里很奇怪,按理说我已经创建了br0的网卡,不应该死循环才对)。
在图视图中看一下,这里是一条BL指令,然后将函数的返回值从r0中,转移到r3中,为了使我们的程序能绕过此处的死循环,我们可以使用IDA提供的patch bytes功能将MOV R3, R0替换成MOV R3, #1,这样我们的程序就可以按照我们设想的流程进行下去,两处的逻辑相同,可使用同一种方法进行绕过
我们借助rasm2工具翻译汇编指令到机器指令,使用的指令如下。
IDA中
Edit->Patch program->change byte
更改鼠标指针处的字节。
然后,
Edit->Patch program->Apply patches to input file
将我们的更改保存进二进制文件
安装qemu-user-static
安装完成后将qemu-arm-static赋值到文件系统目录squashfs-root下,启动httpd服务
此处使用的是patch后的httpd文件
qemu系统级调试
打包解包后的文件
首先宿主机开启网卡,直接执行./net.sh即可
而后需要下载三个文件
执行下述文件 ./boot.sh
运行后,即可进入到模拟环境
在宿主机打包解包后的squashfs-root文件夹
qemu模拟器开启网卡(默认连接后的qemu里面的网卡是没有网络配置的,需要重新配置一下)
上传压缩包到qemu模拟器
进入到qemu模拟器解压缩
为qemu模拟器添加br0网卡
报错了,提示不能创建core_pattern文件,是因为目录不存在,并且进程断开了
首先手动创建目录
httpd patch过程与上述一致,此处不进行赘述
将patch后的httpd文件上传到qemu模拟器替换
重新运行后,运行成功
但是此时访问是访问不到的东西的,需要结束进程,然后重新执行
如果想通过qemu系统模式进行调试,请看以下内容
首先将gdbserver上传到qemu模拟器上,而后按照如下运行
https://github.com/hugsy/gdb-static
宿主机执行
返回宿主机,执行如下指令,即可远程连接
笔者演示的时候,因为还没有安装pwndbg,所以看上去很奇怪,建议搭建先安装pwndbg再去运行
CVE-2018-18708
参考:
https://blog.xmcve.com/2022/10/08/CVE-2018-18708-%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0/
https://blog.csdn.net/m0_55368674/article/details/128939608
漏洞点位分析
首先看漏洞点位,漏洞接口为setMacFilterCfg,参数为deviceList
打开ida,使用ida打开httpd,搜索strings字符串setMacFilterCfg
在函数aSetmacfiltercf上面点击x查找交叉引用
此时进入到函数体内,按一下tab查看伪代码,此函数实际为tenda接口函数sub_42378()【formDefineTendDa()】
双击formSetMacFilterCfg进入到函数里面,此时可以看到,v18和v17通过sub_2BA8C函数进行传参,该函数实际为websGetVar()函数,该函数通过web进行传参,传入的参数为macFilterType和deviceList
v19 = sub_C10D0(v18); 查看此函数,此函数有数个条件分支
该函数是用来判断传入的macFilterType参数是否符合要求(macFilterType=black或者macFilterType=white),返回0则代表正确,会进入到下述代码的else判断,从而才能进入到v19 = sub_C14DC(v18, v17);
接下来进入到v19 = sub_C14DC(v18, v17); v17是我们主要关注对象(v18实际上是macFilterType,因为上面我们分析过,该参数必须是white和black,写死了,并不能作为溢出点),该参数为deviceList
这一大堆其实我们只需要关注s参数,这个参数对应的传入的deviceList参数
可以看到,主要用到这个参数的函数为sub_C17A0(a1, s, v10);
进入到sub_C17A0(a1, s, v10);函数体
该函数体调用的参数对应的是a2参数,我们发现,对应调用此参数的函数为sub_C24C0(a2, s_2);
首先我们可以看到,这个函数传入两个参数,第一个参数a2就是对应的deviceList,第二个s_2是一个固定的缓冲区,且长度为176(0XB0),这个就是我们后续用到的偏移量,后续会对这个偏移量进行验证
最后,进入到sub_C24C0(a2, s_2);函数体
最后的函数体,传入的deviceList对应参数为s参数;
src = strchr(s, 13); 首先src代表的是,在字符串s中寻找ascii码值为13,也就是“\r”的指针,然后赋值给src,也就是src是写死的;
所以真正的溢出点为strcpy(src_1 + 32, s); 该函数为字符串复制函数;
但是前面有一个判断语句if ( src ),所以在参数里也需要加上"\r";由此分析结束
由此得出结论:
偏移量分析
启动调试,这里需要换成pwndgb,因为pwndgb可以支持更多的指令,特别是计算偏移量。下述指令是在宿主机执行的,测试环境为qemu用户级别启动
此时运行python测试脚本,即可看到pc寄存器的值为taab(因为没有任何断点,所以程序直接停在strcpy函数执行后溢出的位置)
执行即可查看PC寄存器的偏移量为176,pc寄存器的作用是:程序计数器,指向下一条要执行的指令地址。通过控制
pc
,可以劫持程序流 ,这里主要是通过控制pc寄存器实现执行system函数
利用链分析
通过上述指令,我们可以得知,程序开启了NX保护,无法直接执行栈中的shellcode,我们使用ROP技术来绕过NX。
1
NX保护与ROP技术
●
NX保护(No-eXecute)
:
现代操作系统通过NX保护禁止在栈、堆等内存区域执行代码,防止Shellcode直接运行。
●
ROP(Return-Oriented Programming)
:
通过复用程序中已有的代码片段(
Gadget
),将多个Gadget串联成链,实现攻击逻辑。
○
无需注入代码
:利用已有指令(如
pop
,
mov
,
blx
)控制程序流。
○
绕过NX
:所有代码均来自合法内存区域(如libc)。
2
ROP攻击核心思路
2.1
目标
调用
system("/bin/sh")
启动交互式Shell。
需解决两个问题:
1
控制
system
函数地址
:跳转到libc中的
system
函数。
2
传递参数
:将
"/bin/sh"
字符串地址传递给
r0
寄存器(ARM架构下第一个参数通过
r0
传递)。
2.2
步骤
1
泄露libc基址
:通过漏洞泄露libc中某个函数(如
puts
)的运行时地址,计算libc基址。
2
计算
system
地址
:
system地址 = libc基址 + system偏移
。
3
构造ROP链
:通过Gadget控制
r0
和
pc
,触发
system
执行。
3
Gadget作用与寄存器控制
3.1
Gadget解析
跳转到R3的gadget1_addr
●
0x00018298 : pop {r3, pc}
○
功能
:从栈顶弹出两个值,分别存入
r3
和
pc
。( 将
system
地址存入
r3
)
○
用途
:控制
r3
寄存器的值,并直接跳转到
pc
指向的地址。
找到一个可以控制R0的gadget2_addr
●
0x00040cb8 : mov r0, sp ; blx r3
○
功能
:将栈指针
sp
的值赋给
r0
,然后跳转到
r3
寄存器指向的地址执行。
○
用途
:用于将栈顶数据(如命令字符串)传递给
r0
(
system
函数的第一个参数)。
3.2
关键寄存器作用
●
r0
:ARM架构中用于传递函数第一个参数(如
system("/bin/sh")
中的
"/bin/sh"
地址)。
●
r3
:通用寄存器,此处用于暂存
system
函数地址。
●
pc
:程序计数器,指向下一条要执行的指令地址。通过控制
pc
,可以劫持程序流。
3.3
CPSR的T位
●
作用
:CPSR寄存器的T位(Thumb模式标志位)决定CPU执行模式:
○
T=0
:执行ARM指令(4字节对齐)。
○
T=1
:执行Thumb指令(2字节对齐)。
●
影响
:
○
若跳转到Thumb指令(如
system
函数是Thumb模式),地址需为奇数(如
0xdeadbeef | 1
)。
○
例如:
system
地址为
0x5A270
(Thumb模式),则实际跳转地址应为
0x5A271
。
1100 0000 0000 0000 0000 0000 0010 0000
,从右向左第五组0000即为T位,此时是0,所以不需要对system地址增加
3.4
system基址计算
计算system函数偏移量
3.5
lib基质计算
由于qemu-user模拟(使用qemu启动,即为user模拟,除此外还有个qemu系统级模拟)不支持vmmap指令打印内存信息,官方给出了说明:
https://github.com/pwndbg/pwndbg/blob/dev/pwndbg/commands/vmmap.py
。
所以我们获取puts函数泄露libc运行时的地址、libc.so.0中的puts函数的偏移量,从而得到libc基址
libc基址=运行时地址−IDA偏移量
由于QEMU+GDB调试时默认关闭了ASLR(地址空间随机化),所以libc每次加载到内存的基址相同(这也是为什么选择libc.so.0文件的原因)。
对正在运行的httpd文件的puts进行断点,该地址位于进程内存空间中,指向加载到内存中的libc库中的
puts
函数 ,得到运行时地址为0x3fdd1cd4
使用ida打开libc.so.0文件,查看puts函数的IDA偏移量为0x35CD4(
相对偏移量
。该偏移量是静态的,与libc基址无关。)
所以 libc基址=运行时地址−IDA偏移量=0x3fdd1cd4 - 0x35cd4 = 0x3fd9c000
3.6
payload流程如下
最终 payload格式为:[offset, gadget1, system_addr, gadget2, cmd]
3.7
执行流程
1
覆盖返回地址
:
栈溢出后,返回地址被覆盖为
gadget1
地址。
2
执行
gadget1
:
●
执行
gadget2
:
●
执行
system("/bin/sh")
:
启动Shell。
备注:
一、关于CPSR寄存器的T位问题
1
ARM架构的指令模式特性:
●
ARM处理器有两种指令集状态:ARM(32位指令)和Thumb(16/32位混合指令)
●
CPSR寄存器的第5位(T位)控制当前模式:
T=0 → ARM模式(指令地址对齐到4字节)
T=1 → Thumb模式(指令地址对齐到2字节)
1
关键机制:
当通过LDR/STACK POP等操作修改PC寄存器时:
●
PC寄存器写入的地址值最低位(LSB)会被复制到CPSR的T位
●
实际PC值 = 写入值 & 0xFFFFFFFE(ARM模式)或 & 0xFFFFFFFC(Thumb)
1
漏洞利用中的处理:
假设我们想跳转到0x08041234执行Thumb指令:
●
必须构造地址为0x08041234 + 1 = 0x08041235
●
当该值被加载到PC时:
PC = 0x08041234(自动清除LSB)
CPSR.T = 1(进入Thumb模式)
整理后我们的POC为:
0
人收藏
0
人喜欢
转载
分享
0
条评论
某人
表情
可输入
255
字
评论
发布投稿
热门文章
1
契约锁电子签章系统 pdfverifier 远程代码执行漏洞分析(补丁包逆向分析)
2
COFF文件解析 | CoffLdr
3
Java内存马篇——WebSocket内存马及GodZilla二开
4
从零掌握java内存马大全(基于LearnJavaMemshellFromZero复现重组)
5
突破网络限制,Merlin Agent助你轻松搭建跳板网络!
近期热点
一周
月份
季度
1
契约锁电子签章系统 pdfverifier 远程代码执行漏洞分析(补丁包逆向分析)
2
COFF文件解析 | CoffLdr
3
Java内存马篇——WebSocket内存马及GodZilla二开
4
从零掌握java内存马大全(基于LearnJavaMemshellFromZero复现重组)
5
突破网络限制,Merlin Agent助你轻松搭建跳板网络!
暂无相关信息
暂无相关信息
优秀作者
1
T0daySeeker
贡献值:41700
2
一天
贡献值:24800
3
Yale
贡献值:24000
4
1674701160110592
贡献值:21800
5
1174735059082055
贡献值:16000
6
手术刀
贡献值:14000
7
Loora1N
贡献值:13000
8
bkbqwq
贡献值:12800
9
lufei
贡献值:11000
10
xsran
贡献值:10600
目录
qemu用户级调试
qemu系统级调试
CVE-2018-18708
漏洞点位分析
偏移量分析
利用链分析
NX保护与ROP技术
ROP攻击核心思路
目标
步骤
Gadget作用与寄存器控制
Gadget解析
关键寄存器作用
CPSR的T位
system基址计算
lib基质计算
payload流程如下
执行流程
转载
标题
作者:
你好
http://www.a.com/asdsabdas
文章
转载
自
复制到剪贴板