RISC-V 架构逆向(RV32/RV64、RVC、gp 相对寻址)
SkillDev toolsRISC-V 架构逆向:RV32/RV64、压缩指令(RVC)、gp 相对寻址、ABI 与 ecall 系统调用约定、工具链指纹。 触发词:RISC-V、riscv、RV32、RV64、RVC、压缩指令、ecall、ESP32-C3、GD32V。
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the RISC-V 架构逆向(RV32/RV64、RVC、gp 相对寻址) skill
What this skill tells your AI
The instructions your AI receives, as published by dslsdzc/rev-skills in .claude/skills/re-riscv/SKILL.md and read by ahel’s review.
何时使用 / 何时不用
- 用:RV32/RV64 架构二进制——Linux 用户态程序、裸机固件、RISC-V MCU 固件(ESP32-C3 类 RV32IMC)
- 用:压缩指令(RVC)混编代码流、gp 相对寻址恢复、RISC-V ABI 识别、ecall 系统调用/环境调用边界
- 用:工具链与库函数指纹(glibc/musl/newlib 系、指令扩展特征)
- 不用:ARM / x86 / MIPS 等其他架构(走 [[re-binary-core]] 通用底座,本技能只补 RISC-V 特有语义)
- 不用:工具链极端定制且无头绪时,先走 [[re-fw-emulate]] 仿真兜底(能跑就先看行为,再回静态)
- 不用:只需解包固件看内容([[re-fw-extract]])/ 分析文件系统与配置([[re-fw-rootfs]])/ 整体启动固件([[re-fw-emulate]])
工具准备
所有工具先验证再使用。静态分析可免沙箱;qemu 动态执行默认沙箱 + 网络隔离([[re-analyze/platform-tips]] 最高原则)。
反编译器(Ghidra / IDA 任选其一)
- Ghidra(内置 RISC-V 处理器模块,RV32/RV64 + I/M/A/F/D/C 扩展,自动处理 RVC 压缩指令):
- Linux: 官方 release 包(需 JDK);部分发行版仓库有
apt install ghidra/pacman -S ghidra - macOS:
brew install --cask ghidra;Windows: 官方 zip - 验证:
analyzeHeadless -help(headless 模式)或 GUI 导入 RISC-V ELF
- Linux: 官方 release 包(需 JDK);部分发行版仓库有
- IDA:商业版含 RISC-V 模块;Freeware 版架构支持范围以官方页面为准
- 导入时确认 RV32/RV64 与端序——标准 RISC-V 小端、大端变体罕见,选错全部错位
readelf / file —— 架构与字节序确认(binutils)
- Linux: binutils 自带(
apt install binutils等);macOS:brew install binutils或 LLVM 系 readelf;Windows: WSL 内 - 验证:
readelf --version
binutils 交叉工具链 —— RISC-V 反汇编/符号表(objdump)
- Debian/Ubuntu:
apt install binutils-riscv64-linux-gnu(提供riscv64-linux-gnu-objdump;编译链加gcc-riscv64-linux-gnu,gcc 依赖带入 binutils 包) - Fedora:
dnf install binutils-riscv64-linux-gnu gcc-riscv64-linux-gnu(cross-binutils / cross-gcc 源包,提供riscv64-linux-gnu-objdump;官方仓库无 riscv64-unknown-elf 裸机工具链,裸机反汇编用 riscv64-linux-gnu-objdump,RVC 支持一致) - Arch:
pacman -S riscv64-elf-binutils riscv64-elf-gcc(裸机,提供riscv64-unknown-elf-objdump)或pacman -S riscv64-linux-gnu-binutils riscv64-linux-gnu-gcc(用户态) - macOS:
brew install riscv64-elf-binutils riscv64-elf-gcc(homebrew-core,提供riscv64-unknown-elf-objdump);Windows/WSL: WSL 内 Linux 版 - 验证:
riscv64-unknown-elf-objdump --version(Debian/Ubuntu/Arch/brew)、riscv64-linux-gnu-objdump --version(Fedora);objdump 对 RVC 混编流自动识别(2/4 字节)
qemu-riscv64 / qemu-riscv32 —— RISC-V 用户态仿真(动态验证)
- Linux:
apt install qemu-user/dnf install qemu-user/pacman -S qemu-user - macOS:
brew install qemu(含用户态);Windows/WSL: WSL 内 Linux 版 - 64 位为
qemu-riscv64、32 位为qemu-riscv32;-L <rootfs>指定动态库/链接器来源,-strace跟踪系统调用 - 验证:
qemu-riscv64 --version、qemu-riscv32 --version - 裸机 RISC-V(无 OS)qemu-user 不适用——用
qemu-system-riscv64/32(Debian trixie 起 / Ubuntu 25.10 起独立包apt install qemu-system-riscv,Ubuntu 24.04 及更早、Debian bookworm 在qemu-system-misc内;Fedora / Archdnf install qemu-system-riscv/pacman -S qemu-system-riscv)-machine virt或板级模型(-s -S接 gdb),或 [[re-emulation]] 用 Unicorn 逐指令
gdb-multiarch —— 交叉调试
- Linux: Debian/Ubuntu
apt install gdb-multiarch(riscv32/riscv64 目标内置);Fedoradnf install gdb(官方 gdb 支持多目标);Archpacman -S gdb(内置 multiarch) - macOS:
brew install gdb(需 Developer Tools 授权,见 [[re-analyze/platform-tips]] macOS 分支)或 WSL 内 Linux 版;Windows/WSL: WSL 内 Linux 版 - 验证: Debian/Ubuntu
gdb-multiarch --version;Fedora/Archgdb --version;载入固件后set architecture riscv:rv64(或 riscv:rv32)再info registers确认
操作步骤
按顺序执行,每步结果存档;动态执行默认沙箱。
-
架构确认(RV32/RV64 + 字节序):
file target.bin # "RISC-V" + 32-bit/64-bit + little-endian 提示 file target.elf readelf -h target.elf # Machine=RISC-V (243);Data=little-endian;Flags 含 RVC/浮点 ABI 位 readelf -A target.elf | head # Tag_RISCV_arch 属性,如 rv64imafdc- e_flags(readelf -h 的 Flags 字段):
EF_RISCV_RVC(0x1)=含压缩指令;浮点 ABI 位掩码 0x6(0=软浮点、2=单精度 F、4=双精度 D、6=四精度 Q);EF_RISCV_RVE(0x8)=RV32E 精简寄存器 - 标准 RISC-V 为小端;大端变体罕见,以 file/readelf 实际输出为准
- 裸机 .bin(无 ELF 头)由步骤 2 的复位向量上下文与指令形态判定(RV32 定宽 4 字节 vs RVC 混编 2/4 字节)
- e_flags(readelf -h 的 Flags 字段):
-
入口定位(reset / 启动代码):
- Linux 用户态:入口即 ELF e_entry(
readelf -h的 Entry point)=_start;动态链接程序先经 ld.so(PT_INTERP),断点/分析从 _start 起 - 裸机:RISC-V 无固定向量表(对比 ARM Cortex-M),入口 = SoC datasheet 的 reset 向量;QEMU virt 机器 reset 向量在 MROM
0x1000(reset stub 再跳 start_addr,默认 DRAM0x80000000,pflash 固件场景为0x20000000)——别把 DRAM 基址当 reset 入口;部分 MCU flash 基址形如 0x08000000;异常/中断向量基址在 mtvec(M 态)/ stvec(S 态)CSR,trap 处理代码按 CSR 值定位 - 启动流程一般为:设栈(
la sp, ...)→ 拷贝 .data / 清零 .bss → 跳 main(裸机)或 __libc_start_main(Linux) - 定位入口后在反编译器中标注,沿调用链展开主逻辑
- Linux 用户态:入口即 ELF e_entry(
-
RVC 压缩指令识别(2/4 字节混合,勿固定宽度切割):
- RVC 让代码 2 字节对齐(半字),地址全为偶数;32 位指令可落在 2 mod 4 的奇半字位置——不能按固定 4 字节步长切割
- 起点错 → 整条指令流错位成乱码;正确做法:用支持 RVC 的反汇编器(Ghidra / riscv64-*-objdump 自动识别),从入口/跳转目标对齐,出现合法压缩指令(c.addi/c.li/c.j/c.lw 等)即对齐正确
- 识别信号:e_flags RVC 位(0x1)、objdump 输出含 2 字节指令、-Os 编译的裸机固件
- 同一函数内 16/32 位指令交错是常态,无固定步长
-
gp 相对寻址恢复(lui+addi 对、.sdata/.sbss):
- gp(x3)=
__global_pointer$,一般落在 .sdata 段内,12 位有符号偏移(±2048)覆盖 .sdata/.sbss 小数据区 - 访问形态:启动时
lui gp, %hi(...)+addi gp, gp, %lo(...)一次设置 → 后续lw/ld aN, off(gp)小偏移数据访问(-msmall-data-limit 默认 8 字节以内的全局变量走 gp) - 符号剥离后:从 _start/crt0 序言的 lui+addi 序列计算 gp 实际值 → 反编译器中标注 → 数据引用恢复;有 ELF 时
readelf -s查__global_pointer$符号值 - gp 缺失时这些访问解析为「未知全局」、数据流散乱——先定 gp 再分析(见坑 2)
- gp(x3)=
-
ABI 识别(整数/浮点 ABI、a0-a7 约定):
- 整数约定:参数 a0-a7(x10-x17,第 9 个起栈传)、返回值 a0、被调用者保存 s0-s11(x8-x9、x18-x27);ra=x1、sp=x2、gp=x3、tp=x4、fp=s0(x8);调用边界 sp 16 字节对齐
- ABI 名:RV32 为 ilp32/ilp32f/ilp32d,RV64 为 lp64/lp64f/lp64d——f/d 后缀表示浮点参数走浮点寄存器(F/D 扩展)
- 浮点约定:参数 fa0-fa7(f10-f17)、返回值 fa0、被调用者保存 fs0-fs11(f8-f9、f18-f27);硬浮点 ABI 浮点参数进 fa0-fa7,软浮点进 a0-a7
- 判定:
readelf -hFlags 浮点 ABI 位 + 反汇编浮点指令密度(flw/fadd/fmv 等)佐证;混编软/硬浮点编译单元时按单元确认(同 ARM 场景)
-
系统调用边界(ecall + a7 号):
- Linux 用户态:
ecall触发系统调用,号在 a7(x17)、参数 a0-a5、返回 a0;RISC-V 用 asm-generic 编号(read=63、write=64、openat=56、exit=93、mmap=222)——与 x86/ARM 编号不同,别拿其他架构的号套 - 定位:objdump 搜
ecall(0x73),往回找li a7, imm立即数;Ghidra 反编译中识别系统调用点 - 裸机(无 OS):ecall 是自定义语义——M 态固件/SBI 调用(a7=扩展号、a6=功能号)或厂商 monitor,不能按 Linux 号解读;按运行环境查 SBI/厂商 SDK 文档对照
- 行为验证:
qemu-riscv64 -strace直接打印系统调用序列(联动 [[re-tracing]])
- Linux 用户态:
-
生态指纹(工具链/库函数特征):
- 用户态:glibc(动态、PT_INTERP、__libc_start_main)/ musl(静态常见、入口小)/ 目标板发行版特征(busybox 等)
- 裸机:newlib/picolibc(crt0:_start → __libc_init_array → main);厂商 SDK 启动链(ROM → bootloader → app)与分区表结构
- 指令扩展:向量指令(RVV,v0-v31 寄存器组)提示较新工具链;压缩指令密度高多为 -Os 编译
- 特征串定位库函数版本(思路同 [[re-imports]]),交叉库指纹辅助还原
跨域联合
- [[re-binary-core]]:RISC-V ELF 通用初勘/反编译/调试底座([[re-ghidra]]、[[re-ida]]、[[re-gdb]]、[[re-radare2]] 照常使用)
- [[re-firmware]]:固件类样本网关路径(re-firmware → re-fw-extract → re-fw-rootfs → 本技能)
- [[re-fw-extract]] / [[re-fw-rootfs]]:固件解包与文件系统/配置分析前置
- [[re-fw-emulate]]:整体启动固件或用户态运行 RISC-V 程序(qemu 系列)
- [[re-emulation]]:无 qemu 场景用 Unicorn/Qiling 模拟执行(裸机逐指令验证)
- [[re-rtos]]:MCU 固件内 RTOS 任务表/TCB 定位后按任务拆解反编译
- [[re-hardware-io]]:JTAG/SWD 真机调试与 flash 读取(OpenOCD + gdb)
- [[re-cpp-abi]]:RISC-V 上 C++ 产物 RTTI/异常/虚表恢复
- [[re-variant]]:固件多版本对比与补丁 diff
- [[re-tracing]]:qemu -strace / strace 系统调用跟踪验证 ecall 边界
- [[re-sandbox]]:一切动态执行强制前置([[re-analyze/platform-tips]] 默认沙箱原则)
- 配套:[[re-patching]](RVC 感知的字节补丁)、[[re-triage]](初勘/架构识别前置)
常见坑与陷阱
- 压缩指令流按 4 字节切割全错:现象——按固定 4 字节步长反汇编,指令全乱、引用全错位;原因——RVC 混编流 2/4 字节混合、2 字节对齐,固定宽度切割会从指令中间起拆;对策——用支持 RVC 的反汇编器(Ghidra/objdump 自动识别),从入口/跳转目标对齐起点,出现合法压缩指令(c.addi/c.j/c.lw)即对齐正确;补丁时指令长度可能 2↔4 字节变化
- gp 全局指针缺失致数据访问散乱:现象——大量
lw/ld off(gp)数据访问解不出地址,全局变量互不关联、逻辑碎片化;原因——符号剥离后__global_pointer$丢失,或反编译器未推导 gp;对策——从 _start/crt0 的lui gp+addi gp序列计算实际 gp 值并在反编译器中标注;有 ELF 时readelf -s查__global_pointer$ - la/li 伪指令展开形态多变:现象——同一逻辑不同函数里指令序列不同(单条 addi / lui+addi / auipc+addi),被误判为不同逻辑;原因——汇编器按立即数大小与重定位类型选展开形态,链接器 relax 后还可能缩短成单条;对策——以机器码语义为准(目标地址一致即同一引用),跨工具对照,关键逻辑回指令级核实
- ecall 系统调用号绑定运行环境、无 OS 时为自定义语义:现象——裸机固件里 ecall 被当 Linux 系统调用解读,语义全错;原因——ecall 只是「环境调用」指令,号语义由运行环境定义(Linux:a7=系统调用号;裸机:SBI 扩展/厂商 monitor);对策——先确认运行环境(有无 OS、动态库、_start 形态),无 OS 时查 SBI 扩展号或厂商 SDK 文档对照 a7/a6
- 链接器 relax(R_RISCV_RELAX)影响反汇编边界:现象——反汇编 .o 中间产物与最终二进制指令流对不上,或按未 relax 的布局找地址错位;原因——链接器 relax 把 auipc+addi 收缩为 addi、jal 缩短为 c.j 等,R_RISCV_RELAX 标记的序列尺寸在链接后变小;对策——分析最终链接产物(不是 .o),地址引用以最终二进制为准;改动字节前先确认是否受 relax 影响(重新链接或比对反汇编)
Signals
- GitHub stars
- 57
- Forks
- 8
- Last commit
- Sep 2026
ahel review
K1binfo
installs-packages
Automated review, not a security audit. Ruleset v1+k2.
Advanced
- Catalog kind
- skill
- Gateway key
re-riscv- Source
- github.com/dslsdzc/rev-skills