Skip to main content

re-blockchain

EVM 智能合约逆向:字节码反编译、漏洞分析。 触发词:智能合约、EVM、Solidity、字节码、合约漏洞、ABI、Solana、Move、BPF

Informações da origem

Repositório
dslsdzc/rev-skills
Última atividade na origem
22 de setembro de 2026 às 20:34
Idioma detectado do SKILL.md
chinês
Estrelas
77
Forks
11

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
re-blockchain
description
EVM 智能合约逆向:字节码反编译、漏洞分析。 触发词:智能合约、EVM、Solidity、字节码、合约漏洞、ABI、Solana、Move、BPF
capabilities
["blockchain-analysis"]
# EVM 智能合约逆向(cast / panoramix / web3.py) ## 何时使用 / 何时不用 - 用:拿到合约字节码(链上地址或 .bin/.hex 文件)要还原逻辑——ABI 恢复、反编译、存储布局重建 - 用:合约漏洞分析(重入/整数溢出/权限)或漏洞利用前的审计定位 - 用:恶意合约/代币诈骗合约取证(链上数据获取、只读拉取) - 不用:Solidity 源码可得且未混淆——直接读源码更准(审计思路同 [[re-vuln]]),本技能面向无源码/仅字节码 - 不用:本节未覆盖的非 EVM 链(如 WASM 系链,指令集不同);WASM 走 [[re-wasm]] - 注意:链上交互以只读为主(`cast call`/`cast code`/`cast storage`);任何写链/部署/动态验证默认本地 anvil 或隔离网络([[re-analyze/platform-tips]] 沙箱最高原则);合约分析基本静态,按「静态优先」执行 ## 工具准备 ### python3 —— 脚本化分析基础 - Linux: `apt install python3` / `dnf install python3` / `pacman -S python` - macOS: `brew install python3`;Windows: `choco install python` - 验证: `python3 --version`(本技能脚本均为 Python 3) ### cast(foundry)—— 链上交互/字节码/存储主力 - 官方安装器(全平台,装到 `~/.foundry/bin`,含 forge/cast/anvil/chisel): `curl -L https://foundry.paradigm.xyz | bash && foundryup` - macOS: `brew install foundry`(官方 Homebrew formula,含四件套) - Arch: 官方仓库**无** foundry——用 AUR `foundry-bin`(`yay -S foundry-bin` 等);**注意 `pacman -S foundry` 是无关的 GNOME Builder 工具包,别装错**;Debian/Ubuntu/Fedora 无官方包——用官方安装器 - 验证: `cast --version && anvil --version` ### web3.py(pip,Python >=3.10)—— 脚本化链上分析 - `pip install web3`(官方 PyPI;当前 8.x 要求 **Python >=3.10**,PyPI `requires-python` 为 `<4,>=3.10`——7.x 才支持 3.8。Python 3.8/3.9 环境需 pin 7.x) - 验证: `python3 -c "import web3; print(web3.__version__)"` ### panoramix(pip,Python 3.9–3.11)—— EVM 反编译器(disasm→流程) - `pip install panoramix-decompiler`(官方 PyPI 0.6.x,要求 Python 3.9–3.11);维护更活跃的 fork 为 `panoramix-decompiler-abi`,两者都提供 `panoramix` 命令 - 验证: `panoramix --help`(或 `python3 -m panoramix --help`) - 用法: 直接传原始字节码 `panoramix <hex> --abi` 反编译;传合约地址则需 `WEB3_PROVIDER_URI` 环境变量(从链上拉字节码);输出伪码 `.pan`/反汇编 `.asm` 写到 cache 目录 ### pyevmasm(pip,Python 3)—— EVM 反汇编 - `pip install pyevmasm`(官方 PyPI);验证: `pyevmasm -d 0x6001600101` 输出指令行 - 备选: `cast disassemble <hex>`(foundry 自带,同一用途) ### hevm / echidna(可选,形式化/模糊验证) - echidna: GitHub releases 预编译二进制(crytic/echidna)或 `cargo install --locked echidna`(官方仓库无发行版包;Arch 有 AUR 包);验证: `echidna --version` - hevm: GitHub releases(ethereum/hevm)或 cargo 构建;验证: `hevm --version` - 均为可选——先跑完步骤 1-5 的静态分析,需要行为验证再上 ### solc / solc-select(可选)—— 存储布局对照 - `pip install solc-select`(Python 3)+ `solc-select install 0.8.28`(官方 PyPI/编译产物下载);或 solc-bin 官方二进制(Linux x86 静态包) - 验证: `solc --version` - 无源码合约不需要;用于"拿到同源码编译产物"时对照权威 storage layout(坑 2) ## 操作步骤 按顺序执行,每步产物(字节码/选择器表/伪码/asm)存档 sha256 + 路径([[re-ioc]] 证据链)。 1. **合约字节码获取(链上/文件)**: ```sh # 链上(RPC 节点;公开 RPC 或自有节点) cast code 0xDEAD... --rpc-url https://eth.llamarpc.com > code.hex # 文件(.bin/.hex 文本或二进制) xxd -r -p code.hex > code.bin && file code.bin && xxd code.bin | head -2 sha256sum code.bin > code.sha256 ``` - 区分 **creation code**(含 initcode + runtime,前面是部署逻辑)与 **runtime code**(纯业务逻辑,首指令常 `0x6080...` PUSH1 0x80 分配内存)——Etherscan 的 Bytecode 页是 creation、Deployed Bytecode 页是 runtime;分析业务逻辑用 runtime - 链上数据获取纪律:`cast call`/`cast code`/`cast storage` 只读安全;写链/交易类操作默认本地 `anvil` 起测试链 2. **ABI 恢复(函数选择器/签名)**: ```sh # 从字节码提取 PUSH4 选择器常量(4 字节 = keccak256(signature)[:4]) cast disassemble "$(cat code.hex)" | grep -E 'PUSH4' | awk '{print $NF}' | sort -u > selectors.txt # 对照签名库(4byte.directory / etherface 在线服务) while read s; do echo -n "$s "; cast 4byte "$s"; done < selectors.txt # 已知签名本地计算(签名必须规范化,见坑 1) cast sig "transfer(address,uint256)" cast sig "balanceOf(address)" ``` - 事件 topic 同理:日志 topic0(前 32 字节)= keccak256(事件签名),对 etherface/4byte 查询 - 候选签名多时用参数长度(CALLDATASIZE 比较)、回退逻辑、存储访问模式消歧(坑 1) 3. **反编译(panoramix 思路:disasm→流程)**: ```sh panoramix "$(cat code.hex)" --abi > contract.pan # 伪码(可读性优先) cast disassemble "$(cat code.hex)" > contract.asm # 精确指令流(交叉验证真值) # 按地址反编译(需节点): WEB3_PROVIDER_URI=<rpc> panoramix 0xDEAD... ``` - 工作流:disasm(指令级真值)→ 函数边界定位(分派表:`PUSH4 sel EQ PUSH2 off JUMPI` 模式,位于字节码开头 ~0x00-0x1f 区域)→ 伪码粗读 → 关键函数回 asm 精读 - 输出粗糙是常态(坑 4),一切反编译结论以 asm 交叉验证 4. **逻辑还原(存储布局/状态变量)**: ```sh # 链上存储读取(状态变量从 slot 0 起、每槽 32 字节) cast storage 0xDEAD... 0 --rpc-url <rpc> cast storage 0xDEAD... 1 --rpc-url <rpc> # 动态数组/映射槽位 = keccak256 派生(见坑 2 公式) cast call 0xDEAD... "owner()(address)" --rpc-url <rpc> # 公开变量 getter # 无源码:从反编译的 SSTORE/SLOAD 常量与 getter 推断语义 grep -E 'SSTORE|SLOAD' contract.asm | head ``` - 布局规则:继承按 C3 线性化合并不变式、每变量 32 字节(`bool/uint8/address` 等可同槽打包)、动态数组 `slot = keccak256(slot_index)`、mapping `slot = keccak256(key ++ slot_index)`;有源码时 `solc --storage-layout` 出权威 JSON 对照 - 与 ABI getter 交叉验证:公开状态变量自动生成 getter,`cast call` 结果反推变量类型与槽位 5. **漏洞分析(重入/整数溢出/权限)**: ```sh grep -cE 'CALL|DELEGATECALL|CALLCODE' contract.asm # 外部调用面(重入/交互边界) grep -E 'ADD|MUL|SUB' contract.asm | head # 算术运算(<0.8 无内置溢出检查) grep -E 'CALLER' contract.asm | head # 调用者检查(onlyOwner 权限) ``` - 重入:外部调用(CALL 到用户可控地址)之后才改状态(SSTORE 顺序在 CALL 之后)——检查 effects 是否在 interactions 之前 - 溢出:Solidity <0.8 无内置检查——看 ADD/MUL 后是否有溢出分支;0.8+ 找 `unchecked` 块 - 权限:CALLER 与 owner 槽比较模式;owner 槽可写/无检查即任意调用(只有构造函数初始化 owner 是常见权缺失) - 可选行为验证:echidna 属性测试(不变量/重入/溢出模式)、hevm 符号执行、`anvil` 本地复现攻击序列 - 结论纪律:漏洞判定需"路径可达"证据(调用链 + 状态条件),仅指令模式是弱信号(坑 4) ## 非 EVM 链(Solana / Move) 流程与 EVM 同构(字节码反编译 → 漏洞分析),指令集与资源模型不同——先识别运行时,再按对应路径走。 - **Solana(BPF 字节码)**:识别特征——ELF 文件 + .text 段为 BPF 指令(eBPF 类指令集);反编译路径——`llvm-objdump -d`(BPF 反汇编)或专用反编译器;分析重点——程序账户与指令调度(CPI 跨程序调用链)、账户数据布局(结构体偏移) - **Sui / Aptos(Move 字节码)**:识别特征——模块/资源/函数表结构;反编译——move disassembler(`move disassemble`);分析重点——资源模型(对象/能力)对漏洞面的影响(转账/所有权逻辑)、模块依赖图 - **DeFi/NFT 场景**:池子合约(AMM 常量积公式)、代币标准变体(SPL 等)、授权与提现逻辑定位 - 漏洞分析承接:逻辑漏洞(重入/权限)沿用 EVM 思路,资源/账户模型差异处单独判断 ## 跨域联合 - [[re-managed]]:本网关「识别运行时」识别到 EVM 字节码(.bin/hex)后固定调用本技能(合约字节码是"托管字节码"分支) - [[re-vuln]]:合约漏洞与漏洞挖掘网关衔接——echidna 的覆盖引导/语料思路同 [[re-fuzzing]],断言崩溃分析思路同 [[re-crash-triage]];漏洞报告结构一致(入口/条件/影响/修复) - 链上数据获取:cast/web3.py 经 RPC 只读(公开 RPC、自有节点、Etherscan API);写链与动态验证默认本地 anvil(隔离网络) - [[re-wasm]]:非 EVM 的 Wasm 合约/链上 Wasm 模块(同域不同指令集) - 引用 [[re-analyze/platform-tips]] 静态优先(大型样本)与沙箱隔离分支(写链/动态验证隔离) ## 常见坑与陷阱 - **选择器碰撞**:现象——`cast 4byte` 返回多个候选签名,或按猜的签名 `cast call` 解析失败/结果错位;原因——选择器是 keccak256(signature) 前 4 字节,碰撞存在(恶意变体/已知碰撞案例),且大量签名未入库;对策——`cast sig` 只对规范化签名成立(参数间无空格、`uint256` 不写 `uint`、地址小写完整),候选签名用 CALLDATASIZE 比较(参数长度分派)、回退逻辑(fallback 处理)、存储访问模式消歧;最终以完整签名 keccak256 比对确认 - **存储布局 vs 源码映射难**:现象——无源码合约按"声明顺序=槽位顺序"推断出错,读出的值类型对不上/混槽;原因——布局受编译器版本、优化开关、继承顺序(C3)、结构体/数组打包规则影响,无源码时没有权威映射;对策——有源码: `solc --storage-layout` 出 JSON 对照(编译器版本要一致);无源码: 从反编译的 SSTORE 常量 + getter 行为 + 值大小推断类型,标注置信度不硬猜;动态数组/mapping 槽位按 keccak256 公式算(步骤 4),别线性加一 - **代理合约(delegatecall 逻辑在别处)**:现象——主合约反编译只有 fallback + delegatecall 转发,找不到任何业务逻辑;原因——升级代理模式(EIP-1967 等)把逻辑放实现合约:主合约只存实现地址并 delegatecall,状态变量布局在主合约、代码在实现合约(布局冲突本身是经典漏洞);对策——先查 EIP-1967 实现槽: `cast storage <addr> 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc --rpc-url <rpc>`(管理员槽 `0xb53127684a568b3173ae13bae8d486943e0793e1d5dccd29778a66c42e1c39d`),非标准代理从反编译定位 SLOAD 常量槽位读实现地址;再 `cast code <实现地址>` 分析实现;实现地址可变=可升级,结论标注读取时点 - **反编译工具输出粗糙需手工**:现象——panoramix 伪码缺变量名/类型/存储语义,函数边界错位,误以为合约逻辑混乱或遗漏关键分支;原因——EVM 无类型无符号表,符号执行/启发式反编译丢信息,现代 Solidity 优化产物(ABIEncoderV2、优化器)结构复杂;对策——伪码只当"粗读地图",关键函数回 `cast disassemble` 指令级精读(分派表定位 → 逐指令语义 → 存储/调用模式);多工具交叉(panoramix + cast disasm + echidna 行为验证);结论标注置信度与验证方式
Ver no GitHub