一、异架构Pwn概述
什么是异架构Pwn
异架构Pwn,说白了就是你在x86的电脑上,去攻击一个ARM、MIPS或者RISC-V架构的设备。你写的shellcode不能在本地跑,得交叉编译成目标架构的机器码。
我刚开始接触这个方向时,也觉得挺别扭。明明本地调试环境是x86_64,目标设备却是ARMv7的小端序。你想想看,连寄存器名字都不一样,更别提指令编码了。
但现实就是这样。IoT设备、路由器、交换机、智能汽车……这些玩意儿的CPU架构五花八门。你不可能在每个架构上都搭一套调试环境。所以,异架构Pwn的核心能力就是:在一种架构上编写、调试、攻击另一种架构的漏洞。
核心定义:异架构Pwn = 攻击者平台架构 ≠ 目标平台架构 的漏洞利用技术。
为什么需要异架构Shellcode
你可能会问:我直接拿现成的shellcode改改不行吗?
嗯,这里要注意。x86的shellcode和ARM的shellcode,完全是两码事。我举个例子:
- 指令长度不同:x86指令是变长的(1-15字节),ARM指令固定4字节(Thumb模式2字节)。
- 寄存器模型不同:x86有8个通用寄存器(64位下16个),ARM有16个(R0-R15),MIPS有32个。
- 系统调用约定不同:x86用int 0x80/syscall,ARM用swi/svc,MIPS用syscall指令。
- 字节序问题:ARM和MIPS都支持大小端切换,你得确认目标设备用的是哪种。
我在项目中遇到过最坑的一次:目标设备是MIPS大端序,我拿小端序的shellcode直接怼上去,结果设备直接重启。后来才发现,MIPS的字节序和x86完全相反,连立即数编码都得反过来。
避坑指南:我曾经因为没确认目标设备的字节序,浪费了整整两天。记住,拿到目标固件后第一件事就是查它的字节序和指令集模式。
常见异架构平台介绍
目前主流的异架构平台有三个:ARM、MIPS、RISC-V。我按自己的经验给你排个序:ARM最常见,MIPS正在减少,RISC-V是未来趋势。
| 架构 | 常见设备 | 指令长度 | 寄存器数量 | 系统调用方式 | 字节序 |
|---|---|---|---|---|---|
| ARM | 手机、路由器、智能摄像头 | 4字节(ARM)/ 2字节(Thumb) | 16个(R0-R15) | SVC #0 | 小端为主,支持大端 |
| MIPS | 路由器、交换机、机顶盒 | 4字节(固定) | 32个(R0-R31) | syscall | 大小端都有 |
| RISC-V | 嵌入式设备、AI芯片 | 4字节(基础)/ 2字节(压缩) | 32个(x0-x31) | ecall | 小端为主 |
ARM架构要点
ARM是我接触最多的异架构。它的特点很明显:
- 两种指令集模式:ARM模式(4字节)和Thumb模式(2字节)。Thumb模式代码密度高,shellcode常用。
- PC寄存器可读:R15就是PC,你可以直接读它来获取当前地址,这对写位置无关shellcode很有用。
- 条件执行:大部分指令可以带条件码,比如EQ、NE、GT等。这既是优势也是坑——写shellcode时要注意条件码是否被意外触发。
个人习惯:我写ARM shellcode时,优先用Thumb模式。指令短,空字节少,而且很多IoT设备默认跑Thumb代码。
MIPS架构要点
MIPS现在主要存在于老款路由器和交换机里。它的设计哲学和ARM很不一样:
- 延迟槽:分支指令后面的那条指令,无论分支是否跳转,都会被执行。这是MIPS最大的坑。
- 寄存器约定:R0永远为0,R29是栈指针,R31是返回地址寄存器。
- 缓存一致性:MIPS的指令缓存和数据缓存是分开的。你写shellcode时,如果代码段被修改,得手动刷缓存。
我记得有一次调试MIPS shellcode,明明代码写对了,但跑起来就是崩溃。后来发现是延迟槽的问题——我在分支指令后面放了一条不该执行的指令,结果它每次都执行,把寄存器搞乱了。
注意:MIPS的延迟槽是新手最容易踩的坑。写shellcode时,分支指令后面一定要放一条有效指令(通常是nop)。
RISC-V架构要点
RISC-V是后起之秀,设计上吸取了ARM和MIPS的教训。它的特点:
- 模块化设计:基础指令集(RV32I/RV64I)很小,扩展指令集按需添加。
- 没有延迟槽:这点比MIPS友好多了。
- 压缩指令集:RVC(压缩指令)可以混搭基础指令,代码密度和Thumb差不多。
我个人觉得,RISC-V会是未来异架构Pwn的主流方向。现在已经有越来越多的IoT芯片用RISC-V了,比如一些AI加速器和低功耗传感器。
知识体系总览
下面这张图,是我梳理的异架构Pwn知识体系。你可以把它当作学习路线图:
学习路径建议
我个人建议的学习顺序是这样的:
- 先选一个架构深入:ARM是最佳起点,资料多,设备多。
- 掌握交叉编译工具链:学会用arm-linux-gnueabi-gcc这类工具。
- 写简单的shellcode:从execve("/bin/sh")开始,逐步增加功能。
- 理解系统调用:每个架构的系统调用号、参数传递方式都不一样。
- 实战漏洞利用:找一些CTF题目或者真实设备的漏洞练手。
我的经验:别一开始就想着写复杂的shellcode。先学会在目标架构上执行一个简单的系统调用,比如exit(0)。能跑通这个,后面就好办了。
好了,这一章就到这里。异架构Pwn的核心概念你已经清楚了。接下来,我们会一步步深入每个架构的细节,从寄存器模型到系统调用,再到实际的shellcode编写。准备好了吗?