Skip to content
Back to skills

Re Address Space

ASecurity

地址空间换算统一处理:PIE/ASLR 基址确定、RVA/VA 转换、loader offset(固件加载地址 vs 链接地址)、 跨工具地址对齐(Ghidra/angr/frida/gdb)。 触发词:PIE、ASLR、基址、RVA、VA、loader offset、地址换算、重定位地址、gdb算地址、angr地址。

  • 112 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 19, 2026
developmentpythonbackend

Security analysis

A100/100

Scanned September 19, 2026

npx -y skills add dslsdzc/rev-skills --skill re-address-space --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Re Address Space?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Re Address Space
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/dslsdzc-re-address-space/badge)](https://www.skillsdirectory.com/skills/dslsdzc-re-address-space)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: re-address-space
type: atomic
description: >
  地址空间换算统一处理:PIE/ASLR 基址确定、RVA/VA 转换、loader offset(固件加载地址 vs 链接地址)、
  跨工具地址对齐(Ghidra/angr/frida/gdb)。
  触发词:PIE、ASLR、基址、RVA、VA、loader offset、地址换算、重定位地址、gdb算地址、angr地址。
capabilities: [address-translation, elf-parser]
---

# 地址空间换算(PIE / ASLR / 基址 / RVA-VA)

## 入口判定(Decision Gate)

```
地址相关问题
├── 静态文件(无运行态): VA/RVA/文件偏移换算 ──→ 本技能(步骤 1-2)
├── 运行态(进程/内存): 基址确定(PIE/ASLR)──→ 本技能(步骤 3)+ /proc/pid/maps
├── 跨工具对齐(Ghidra 显示 vs 运行时 vs angr)──→ 本技能(步骤 4)
└── 固件加载地址 vs 链接地址差 ──→ 本技能(步骤 5)
```

## 何时使用 / 何时不用

- 用:任何「这个地址对不上」问题——反编译器显示地址 ≠ 运行时地址 ≠ find 到的地址
- 用:PIE/ASLR 二进制需要换算运行时基址(frida `Process.getModuleByName(...).base` / gdb `info proc mappings` / maps 文件)
- 用:RVA/VA 互转、文件偏移与虚拟地址互转、固件加载地址与链接地址差
- 不用:只是读 ELF 头/节表(走 [[re-format-elf]])
- 不用:运行时内存布局细查(走 [[re-memdump]] / [[re-gdb]])

## 工具准备

所有工具先验证再使用。全部为静态/轻量命令,可免沙箱。

### readelf / objdump(binutils)—— 文件侧基址与段信息

- Linux: `apt install binutils` / `dnf install binutils` / `pacman -S binutils`(多数预装)
- 验证: `readelf --version`;`objdump --version`

### gdb —— 运行态基址(跨 OS,见 [[re-gdb]])

- 安装与验证见 [[re-gdb]] 工具准备

### python3 —— 换算脚本

- 安装与验证见 [[re-python]] 工具准备

## 操作步骤

1. **确定文件侧基址(静态)**:
   ```sh
   readelf -l target | grep LOAD        # 首个 LOAD 段 p_vaddr 即链接基址(ET_EXEC 固定;ET_DYN/PIE 为 0 起相对)
   readelf -h target | grep Type        # EXEC(固定基址)/ DYN(PIE,运行时才定基址)
   ```
   - 链接基址(link-time base):取**最低 PT_LOAD 的 p_vaddr**(页对齐)——不要假设 PIE/ET_DYN 的 p_vaddr 必为 0,格式没这条要求;PIE 下常见 0,但也可能非 0(如 0x1000 起的布局)。load_bias = 运行时映射起点 − 最低 p_vaddr(见步骤 3)
   - 文件偏移 ↔ VA:`VA = p_vaddr + (file_offset - p_offset)`(按段匹配,别用全文件线性换算)

2. **RVA / VA 换算**:
   ```
   RVA = VA - ImageBase(PE 语境)
   VA  = RVA + ImageBase
   ```
   - ELF 无统一 ImageBase 概念——用「链接基址 + 段偏移」;PE 用节表(RVA → 文件偏移按节)
   - 32/64 位宽度影响地址表示,不影响换算逻辑

3. **运行态基址(PIE / ASLR)**:
   ```sh
   cat /proc/<pid>/maps | head -5        # 加载基址 = 首个映射(r--p,file offset 0x0)起点(Linux)
   gdb -p <pid> -ex 'info proc mappings' -ex detach   # 或 gdb 侧(跨平台)
   ```
   - **布局差异(separate-code)**:gcc 默认 PIE 下首个 LOAD 是 R-- 段(p_vaddr=0),代码段在其后(p_vaddr=0x1000 起);老式布局(无 separate-code)首个 LOAD 即 R E(p_vaddr=0)——取加载基址用**首个映射(r--p)起点**;若用首个 r-xp 起点须减去该段自身 p_vaddr,两种布局结果才一致
   - frida:`Process.getModuleByName("libtarget.so").base`(Frida 17+:静态 `Module.findBaseAddress` / `Module.getBaseAddress` 已移除,旧版本文法见 [[re-frida-script-author]])
   - **运行时地址 = 链接地址 + load bias**——bias = 运行时基址 - 链接基址;PIE 每次运行 bias 不同(ASLR),脚本必须动态取
   - 换算:`runtime_addr = link_addr + bias`(如链接 0x1000 的符号在运行时 `0x1000 + 0x7f0000000000`)

4. **跨工具对齐**:
   - Ghidra:默认按链接基址导入(PIE 程序 Image Base 常为 0);与运行时地址差 = load bias——`Ghidra 地址 + bias = 运行时地址`
   - angr:`proj.loader.main_object.mapped_base`(rebase 后基址);重定基址用后端对象的 `obj.rebase(new_base)`(如 `proj.loader.main_object.rebase(...)`,cle Backend.rebase)
   - gdb/frida:以运行时基址为准(步骤 3),反编译器地址需加 bias 才能对齐
   - 断点对齐:`gdb b *<链接地址> + <bias>` 或 frida `Process.getModuleByName("libfoo.so").findExportByName("func")` 加偏移

5. **固件 loader offset**:
   - 固件镜像链接地址 vs 实际加载地址(flash 映射/解压后)差 = loader offset——先读固件头部/启动代码确认加载地址([[re-fw-extract]] / [[re-arm]] 联动)
   - 换算:`实际地址 = 链接地址 + loader_offset`;不确定时用启动代码里对自身地址的引用反推

## 跨域联合

- [[re-binary-core]]:本技能是其子技能——二进制分析通用底座(地址换算被全域消费)
- [[re-format-elf]] / [[re-format-pe]]:段/节表来源(步骤 1-2 输入)
- [[re-frida]] / [[re-gdb]] / [[re-memdump]]:运行态基址来源(步骤 3)
- [[re-ghidra]] / [[re-angr]]:跨工具地址对齐(步骤 4)
- [[re-fw-extract]] / [[re-arm]]:固件加载地址(步骤 5)
- [[re-analyze/analysis-contract]]:地址换算结论进数据契约的**文件域字段** base_addr(见 [[re-analyze/analysis-contract]] §3.2)

## 常见坑与陷阱

- **PIE 静态基址误用**:现象——把 PIE 的链接基址(0 或 ELF 头值)当运行时地址,断点/查找全落空;原因——ET_DYN 运行时基址由 ASLR 决定;对策——步骤 3 动态取 bias,不静态猜
- **文件偏移当虚拟地址**:现象——`find 0x1234`(文件偏移)后在 Ghidra/运行时找不到对应;原因——混淆偏移与 VA 两套坐标系;对策——按步骤 1 段映射换算,先确认读的是哪套
- **固件链接地址 ≠ 加载地址**:现象——固件里 `file` 报的入口与实际运行入口差一个常数;原因——链接器按 flash/ROM 地址链,运行时解压/重映射到 RAM;对策——步骤 5 反推 loader offset,别硬凑
- **跨工具地址各说各话**:现象——Ghidra 说 0x401000、angr 说 0x400000、frida 说 0x7f...——同一符号三套数;原因——各工具默认基址不同(链接/映射/rebase);对策——步骤 4 统一到同一坐标系(运行时基址为锚)再比对

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…