radare2 和 EVM
1. 引言
radare2为开源的逆向工程框架,具体代码见:
- https://github.com/radareorg/radare2
其包含多个组件,如:
- radare2:为主要工具,其核心为hexadecimal editor and debugger。
- rabin2:从二进制可执行文件中提取信息。支持的二进制格式有ELF, PE, Java CLASS, Mach-O 以及其他支持r2 plugins的格式。
- rasm2:为汇编和反汇编工具,支持多种架构,如Intel x86, x86-64, MIPS, ARM, PowerPC, Java等。
- rahash2:为block-based hash tool,支持大小文件,支持MD4, MD5, CRC16, CRC32, SHA1, SHA256等算法。可用于验证大文件的完整性,或跟踪大文件的修改,memory dumps or disks。
- radiff2:为二进制比对工具,支持byte-level 或 delta diff。
- rafind2:用于查找文件中的特定字符。
- ragg2:将高级语言编写程序编译为tiny binaries for x86, x86-64 and ARM。
- rarun2:支持在不同环境,以不同参数,不同权限等启动程序运行。
- rax2:为支持各种进制数字、ASCII、String转换的工具。
此外,还有额外的插件:radare2-extras。
2. 将radare2用于EVM反向分析
2.1 EVM: stack-based machine
EVM为图灵完备的,基于stack的虚拟机。与经典的图灵完备VM不同,在EVM中执行的每条指令都需要以gas征税。
EVM中的指令集可分为2部分:
- 通用的指令(如push, pop, jump等等)。
- 以太坊特有的指令(如call to external contracts, read the address of the caller等等)。
举例,将两个数相加的指令为:
PUSH1 32 | Stack: [ 32 ]
PUSH1 42 | Stack: [ 42, 32 ]
ADD | Stack: [ 74 ]
2.2 EVM中的Flow-control
每一步所要执行的指令由PC register控制。JUMP指令将take the destination addr from the top of the stack,并会修改PC register。EVM中,仅当dst address包含了JUMPDEST指令,JUMP指令才会生效,这是一种控制流保护。
PUSH1 01 | Stack: [ 1 ], PC: 0
JUMPDEST | Stack: [ 1 ], PC: 2
PUSH1 02 | Stack: [ 1, 2 ], PC: 3
ADD | Stack: [ 3 ], PC: 5
PUSH1 0x2 | Stack: [ 3, 2 ], PC: 6
JUMP | Stack: [ 3 ], PC: 7
PUSH1 02 | Stack: [ 3, 2 ], PC: 3
ADD | Stack: [ 5 ], PC: 5
.....
此处,有一个无限循环,在每次迭代中向stack顶部的值加2。
2.3 EVM特有的command
EVM中有一些特有的command,详细可参加以太坊黄皮书 ETHEREUM: A SECURE DECENTRALISED GENERALISED TRANSACTION LEDGER ISTANBUL VERSION 80085f7 – 2021-07-11。
主要有:
- 1)Memory:EVM为非冯诺依曼架构,其memory和storage是分离的。不同的指令将向memory读写数据。memory only lives during a single execution of the contract。
- 2)Storage:storage在合约的整个生命周期都是persistent的。storage中存储的是合约的state。local variables也存储在storage中。
2.4 借助radare2实现EVM disassembler and debuger
安装完radare2之后,需安装evm插件:【在此之前需安装 libjansson-dev和curl4-openssl-dev 】
r2pm update
r2pm install evm
安装evm插件过程中如报一下错误,将相应的lseek修改为seek即可安装成功:
io_evm.c:765:3: error: field designator 'lseek' does not refer to any field intype 'RIOPlugin' (aka 'struct r_io_plugin_t'); did you mean 'seek'?.lseek = __lseek,^~~~~seek
简单举例为:
$ cat ./example1.sol
pragma solidity ^0.4.0;contract Example1 {uint a = 0;function setA(uint b) {a = b + 0x42;}
}$ solc ./example1.sol --bin-runtime -o ./out/
$ ls ./out/
Example1.bin-runtime
--bin-runtime
flag创建的binary code与合约加载进链上是一致的:
$ cat out/Example1.bin-runtime
608060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063ee919d50146044575b600080fd5b348015604f57600080fd5b50d38015605b57600080fd5b50d28015606757600080fd5b506084600480360381019080803590602001909291905050506086565b005b60428101600081905550505600a165627a7a7230582091f0675ac5f9ce9b61e7b21b35d15da09c6c12c54b19ef72ecfb72a50d9f59810029
以上为十六进制,可使用rax2转换为二进制并使用r2工具来解析:
$ rax2 -s < ./out/Example1.bin-runtime > ./out/Example1.bin-runtime.bin
$ r2 -a evm out/Example1.bin-runtime.bin
WARNING: No calling convention defined for this file, analysis may be inaccurate.-- What about taking a break? Here, have this nice 0xCC.
[0x00000000]> aa
[Warning: set your favourite calling convention in `e anal.cc=?`
[x] Analyze all flags starting with sym. and entry0 (aa)
[0x00000000]> pd 30
┌ 145: fcn.00000000 ();
│ 0x00000000 6080 push1 0x80
│ 0x00000002 6040 push1 0x40
│ 0x00000004 52 mstore
│ 0x00000005 6004 push1 0x04
│ 0x00000007 36 calldatasize
│ 0x00000008 10 lt
│ 0x00000009 603f push1 0x3f
│ ┌─< 0x0000000b 57 jumpi
│ │ 0x0000000c 6000 push1 0x00
│ │ 0x0000000e 35 calldataload
│ │ 0x0000000f 7c0100000000. push29 0x0100000000000000000000
│ │ 0x0000002d 90 swap1
│ │ 0x0000002e 04 div
│ │ 0x0000002f 63ffffffff push4 0xffffffff
│ │ 0x00000034 16 and
│ │ 0x00000035 80 dup1
│ │ 0x00000036 63ee919d50 push4 0xee919d50
│ │ 0x0000003b 14 eq
│ │ 0x0000003c 6044 push1 0x44
│ ┌──< 0x0000003e 57 jumpi
│ │└─> 0x0000003f 5b jumpdest
│ │ 0x00000040 6000 push1 0x00
│ │ 0x00000042 80 dup1
│ │ 0x00000043 fd revert
│ └──> 0x00000044 5b jumpdest
参考资料
[1] Reversing EVM bytecode with radare2
[2] Radare2 book
[3] Radare2 and EVM Bytecode
radare2 和 EVM相关推荐
- Ti公司DSP的DSK、EVM、DDK的区别
1. DSK TI的DSP Starter kit,初学者开发套件,它是一个DSP的最简单系统,最小开发功能板,是在最小系统上的略微扩充,使初学者了解DSP系统结构的板卡.DSK是TI或TI的第三方生 ...
- 误差向量幅度(EVM)介绍
误差向量幅度[EVM]:Error Vector Magnitude,误差向量(包括幅度和相位的矢量)是在一个给定时刻理想无误差基准信号与实际发射信号的向量差,能全面衡量调制信号的幅度误差和相位误差. ...
- linux 逆向工具 radare2入门
注:radare2系列实验共有3个.这是第一个,第二个实验是进阶用法通过它写exp,第三个实验是通过它分析rom.参考链接已经在文末给出. 1 预备知识 1.关于Radare2: radare2 ...
- 基于DM8168 EVM的智能视频跟踪系统
基于DM8168智能视频跟踪系统以TMS320DM8168处理器为核心,各种外设接口组成的智能视频分析跟踪系统.本评估板(DM8168 EVM)硬件模块高度集成了DM8168,以及其它外设如NAND. ...
- 【译】The Faults and Shortcomings of the EVM
所以,先介绍一下. 我共同创立了Qtum ,这是一个基本上采用了以太坊虚拟机(EVM)的项目,并把它放到了不是以太坊的区块链(以及其他一些东西)上. 在我这样做的过程中,我被迫反对自己的意愿去学习比我 ...
- 以太坊源码学习 -- EVM
以太坊源码学习 – EVM 学习文档链接:here 一.虚拟机外 主要功能: 执行前将Transaction类型转化成Message,创建虚拟机(EVM)对象,计算一些Gas消耗,以及执行交易完毕后创 ...
- 以太坊虚拟机EVM的缺陷与不足
首先对作者做个简单的自我介绍,Jordan Earls是Qtum量子链的联合创始人之一,目前担任Qtum量子链全球首席工程师.Qtum目前采用了以太坊虚拟机(Ethereum Virtual Mach ...
- radare2 常用操作总结
radare2 简介 radare2是一个用C语言编写的跨平台的二进制分析工具,支持ARM.MIPS.X86等平台,支持分析多种格式的二进制文件如ELF.Mach-O.Fatmach-O, PE.PE ...
- 对于以太坊虚拟机 (EVM)及其相关知识的讲解
以太坊虚拟机(EVM) EVM是智能合约的运行环境 作为区块验证协议的一部分,参与网络的每个节点都会运行EVM,审查节点会检查验证正在验证的区块中列出的交易,并运行EVM中交易触发的代码 EVM是沙盒 ...
最新文章
- Solaris 默认Shell 修改
- java switch语句练习 从键盘输入2个数和一个运算符(+,-,*,/),输出运算结果
- struc,union,class的内存对齐方式
- keepalived高可用集群配置
- 曹大带我学 Go(1)——调度的本质
- rabbitmq如何保证消息不被重复消费_RabbitMQ保证消息可靠投递与消费的正确使用姿势...
- 今日头条大佬十年面试了 2000 人,总结了这 5 点
- dynamodb容器使用_使用DynamoDBMapper插入DynamoDB项目
- 英特尔固态硬盘540s开卡_英特尔Z490主板绝配?技嘉PCIe 3.0 x8固态硬盘测试:6.5GB/s读速...
- rust睡觉按键没反应_Rust 有问有答之 use 关键字
- 为什么大部分的C/C++码农都成不了高级工程师?真实原因是缺少核心能力!
- 营销任何产品都只解决2个功能
- 数据可视化——利用pandas和seaborn绘图基础
- Python中的signal模块和Ctrl+C操作
- python千行代码项目_p2:千行代码入门python
- 动态修改App.Config 和web.Config
- php解析视频_原创更新:快手短视频无水印直连解析下载PHP前端版
- StringUtil工具类 之 字符串长度截取函数
- python库之pyserial用法,pyserial和serial的区别
- 2022-04-08美团笔试练题