首页
社区
课程
招聘
[原创]Ethernaut智能合约代码审计题目writeup(19-21)
发表于: 2020-5-25 21:23 27181

[原创]Ethernaut智能合约代码审计题目writeup(19-21)

2020-5-25 21:23
27181


目标:使用 10 个操作码输出 42

原理:https://hitcxy.com/2019/ethernaut/  太强了!

在合约创建的时候,用户或合约将交易发送到以太坊网络,没有参数 to,表示这是个合约创建而不是一个交易

EVM 把 solidity 代码编译为 字节码,字节码直接转换成 opcodes 运行


字节码包含两部分:initialization code 和 runtime code ,一开始合约创建的时候 EVM 只执行 initialization code,遇到第一个 stop 或者 return 的时候合约的构造函数就运行了,此时合约便有了地址


想要做这道题要构造这两段代码 initialization code 和 runtime code,initialization code 是由 EVM 创建并且存储需要用的 runtime code 的,所以首先来看 runtime code,想要返回 42,需要用 return(p,s) 但是在返回值前先要把值存储到内存中 mstore(p, v)


首先,用 mstore(p,v) 把 42 存储到内存中,v 是 42 的十六进制值 0x2a,p 是内存中的位置(不知道为啥)

然后,用 return(p,s) 返回 42,p 是存储的位置,s 是存储所占的大小不明白为啥是 0x20

所以整个 runtime code 是 0x602a60805260206080f3


再来看 initialization code,首先 initialization code 要把 runtime code 拷贝到内训,然后再返回给 EVM

将代码从一个地方复制到一个地方的方法是 codecopy(t, f, s)。t 是目标位置,f 是当前位置,s 是代码大小(单位:字节),之前我们的代码大小为 10 字节

然后,将内存中的 runtime codes 返回到 EVM

initialization codes 总共占了 0x0c 字节,这表示 runtime codes 从索引 0x0c 开始,所以 ?? 的地方是 0x0c

所以,initialization codes 最后的顺序是 600a600c600039600a6000f3

两个拼起来,得到字节码是:0x600a600c600039600a6000f3602a60805260206080f3


var bytecode = "0x600a600c600039600a6000f3602a60805260206080f3";

web3.eth.sendTransaction({from:player,data:bytecode},function(err,res){console.log(res)});

然后去刚才交易的详情去看一下


image.png


image.png


拿到新的合约地址之后 await contract.setSolver("合约地址"),然后就通关了


image.png



目标:拿到合约所有权

由于 EVM 存储优化的关系,在 slot [0] 中同时存储了 contact 和 owner,所以我们要做的就是将 owner 变量覆盖为自己账户地址

所有函数都有 contacted 限制,所以必须要先通过 make_contact 把 contact 改成 true


make_contact() 函数只验证传入数组的长度。OPCODE 中数组长度是存储在某个 slot 上的,并且没有对数组长度和数组内的数据做校验。所以可以构造一个存储位上长度很大,但实际上并没有数据的数组,打包成 data 发送

image.png


之后通过调用 retract(),使得 codex 数组长度下溢。

web3.eth.getStorageAt(contract.address, 1, function(x, y) {alert(y)});



[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//