-
-
[原创]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)});
然后去刚才交易的详情去看一下
拿到新的合约地址之后 await contract.setSolver("合约地址"),然后就通关了
目标:拿到合约所有权
由于 EVM 存储优化的关系,在 slot [0] 中同时存储了 contact 和 owner,所以我们要做的就是将 owner 变量覆盖为自己账户地址
所有函数都有 contacted 限制,所以必须要先通过 make_contact 把 contact 改成 true
make_contact() 函数只验证传入数组的长度。OPCODE 中数组长度是存储在某个 slot 上的,并且没有对数组长度和数组内的数据做校验。所以可以构造一个存储位上长度很大,但实际上并没有数据的数组,打包成 data 发送
之后通过调用 retract(),使得 codex 数组长度下溢。
web3.eth.getStorageAt(contract.address, 1, function(x, y) {alert(y)});
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
- 对某款智能手表的分析与攻击 6564
- [原创][车联网安全]使用STM32开发板实战汽车UDS诊断 15017
- [分享]binwalk路径穿越导致RCE(CVE-2022-4510) 9984
- [原创]Hack-A-Sat 2020预选赛 beckley 13588
- [原创]一个BLE智能手环的分析 31562