欢迎来到 无奈人生 安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

从solc编译过程来理解solidity合约结构

来源:未知 作者:wnhack 时间:2019-01-08 14:27 点击: 我要投稿
广告位API接口通信错误,查看德得广告获取帮助
现在以一个最简单的代码来开始我们的逆向旅程,为了方便学习,所有的代码编译和分析都在http://remix.ethereum.org/# 上进行.默认IDE 选项是关闭代码优化(Enable Optimization)和使用0.4.25 版本的solidity 编译器编译.
    pragma solidity ^0.4.24;
    contract test {
        function a() {
            uint a = 123;
        }
    }
在Remix 上输入上述代码,点击Start to Compile 对代码进行编译,可以在Details 按钮里面获取编译出来的结果.结果包含如下:
    METADATA  编译器元数据,包含:编译器版本,编译器设置,源码信息等
    BYTECODE  合约编译完整的字节码结果
    ABI  应用程序接口,用于标识合约提供了哪些函数给外部调用
    WEB3DEPLOY  Web3js版合约部署代码
    METADATAHASH  元数据哈希
    GASESTIMATES  编译器计算函数调用需要消耗的Gas表
    RUNTIME BYTECODE  合约运行时字节码
    ASSEMBLY  字节码反汇编
读者们会注意到,编译结果里面有ByteCode 和Runtime Bytecode ,分别表示什么意思呢,在此先略过这个疑问,我们关注Runtime Bytecode 中返回的字节码.对代码结构分析和字节码分析的标注后所有代码如下:
    000 PUSH1 80
    002 PUSH1 40
    004 MSTORE             ;  把0x80 写到[0x40 ,0x40 + 0x20] 这块内存里面,因为内存是空的,这会创建新的内存
    005 PUSH1 04
    007 CALLDATASIZE       ;  获取CALLDATA 的长度
    008 LT                 ;  LT 和PUSH1 0x4 对应,判断CALLDATA 的长度是否小于0x4
    009 PUSH1 3f
    011 JUMPI              ;  如果小于0x4 就往下跳转到0x3F
    012 PUSH1 00
    014 CALLDATALOAD       ;  CALLDATALOAD 0x0 ,PUSH1 0x0 是给CALLDATALOAD 的参数,意思要获取CALLDATA 数据的偏移位置
    015 PUSH29 0100000000000000000000000000000000000000000000000000000000
    045 SWAP1
    046 DIV                ;  DIV 和PUSH29 对应,意思是把上面的数据向左移28 字节,剩下4 字节是调用合约函数名的哈希
    047 PUSH4 ffffffff
    052 AND                ;  AND 和PUSH4 0xFFFFFFFF 对应,保留低位4 字节数据,高位去处
    053 DUP1
    054 PUSH4 0dbe671f     ;  这个是合约有的函数名,经过sha3() 精简过的
    059 EQ                 ;  判断传递过来的函数调用名是否相等
    060 PUSH1 44
    062 JUMPI              ;  如果两值相等就往下跳转到0x44
    063 JUMPDEST           ;  空指令
    064 PUSH1 00
    066 DUP1
    067 REVERT             ;  没有匹配到相应的函数就撤销所有操作,Revert(0,0)
    068 JUMPDEST
    069 CALLVALUE          ;  获取用户转帐数额
    070 DUP1
    071 ISZERO             ;  如果用户转帐数额为0
    072 PUSH1 4f
    074 JUMPI              ;  转帐数额不为0 则跳到0x4F,否则就退出
    075 PUSH1 00
    077 DUP1
    078 REVERT             ;  因为调用函数a() 是不需要附加转帐金额的,所以检测到带有附加金额的函数调用就退出,参考payable 关键字
    079 JUMPDEST
    080 POP
    081 PUSH1 56
    083 PUSH1 58
    085 JUMP               ;  跳转到地址88
    086 JUMPDEST
    087 STOP               ;  停止执行
    088 JUMPDEST 现在以一个最简单的代码来开始我们的逆向旅程,为了方便学习,所有的代码编译和分析都在http://remix.ethereum.org/# 上进行.默认IDE 选项是关闭代码优化(Enable Optimization)和使用0.4.25 版本的solidity 编译器编译.
    pragma solidity ^0.4.24;
    contract test {
        function a() { www.wnhack.com
            uint a = 123;
        }
    }
在Remix 上输入上述代码,点击Start to Compile 对代码进行编译,可以在Details 按钮里面获取编译出来的结果.结果包含如下:

www.wnhack.com


    METADATA  编译器元数据,包含:编译器版本,编译器设置,源码信息等
    BYTECODE  合约编译完整的字节码结果
    ABI  应用程序接口,用于标识合约提供了哪些函数给外部调用
    WEB3DEPLOY  Web3js版合约部署代码
本文来自无奈人生安全网

    METADATAHASH  元数据哈希
    GASESTIMATES  编译器计算函数调用需要消耗的Gas表
    RUNTIME BYTECODE  合约运行时字节码
    ASSEMBLY  字节码反汇编
读者们会注意到,编译结果里面有ByteCode 和Runtime Bytecode ,分别表示什么意思呢,在此先略过这个疑问,我们关注Runtime Bytecode 中返回的字节码.对代码结构分析和字节码分析的标注后所有代码如下: copyright 无奈人生
    000 PUSH1 80
    002 PUSH1 40
    004 MSTORE             ;  把0x80 写到[0x40 ,0x40 + 0x20] 这块内存里面,因为内存是空的,这会创建新的内存
    005 PUSH1 04 本文来自无奈人生安全网
    007 CALLDATASIZE       ;  获取CALLDATA 的长度
    008 LT                 ;  LT 和PUSH1 0x4 对应,判断CALLDATA 的长度是否小于0x4
    009 PUSH1 3f
    011 JUMPI              ;  如果小于0x4 就往下跳转到0x3F copyright 无奈人生
    012 PUSH1 00
    014 CALLDATALOAD       ;  CALLDATALOAD 0x0 ,PUSH1 0x0 是给CALLDATALOAD 的参数,意思要获取CALLDATA 数据的偏移位置
    015 PUSH29 0100000000000000000000000000000000000000000000000000000000
    045 SWAP1

无奈人生安全网


    046 DIV                ;  DIV 和PUSH29 对应,意思是把上面的数据向左移28 字节,剩下4 字节是调用合约函数名的哈希
    047 PUSH4 ffffffff
    052 AND                ;  AND 和PUSH4 0xFFFFFFFF 对应,保留低位4 字节数据,高位去处
    053 DUP1

内容来自无奈安全网


    054 PUSH4 0dbe671f     ;  这个是合约有的函数名,经过sha3() 精简过的
    059 EQ                 ;  判断传递过来的函数调用名是否相等
    060 PUSH1 44
    062 JUMPI              ;  如果两值相等就往下跳转到0x44 本文来自无奈人生安全网
    063 JUMPDEST           ;  空指令
    064 PUSH1 00
    066 DUP1
    067 REVERT             ;  没有匹配到相应的函数就撤销所有操作,Revert(0,0)

内容来自无奈安全网


    068 JUMPDEST
    069 CALLVALUE          ;  获取用户转帐数额
    070 DUP1
    071 ISZERO             ;  如果用户转帐数额为0
copyright 无奈人生

    072 PUSH1 4f
    074 JUMPI              ;  转帐数额不为0 则跳到0x4F,否则就退出
    075 PUSH1 00
    077 DUP1 本文来自无奈人生安全网
    078 REVERT             ;  因为调用函数a() 是不需要附加转帐金额的,所以检测到带有附加金额的函数调用就退出,参考payable 关键字
    079 JUMPDEST
    080 POP
    081 PUSH1 56 copyright 无奈人生
    083 PUSH1 58
    085 JUMP               ;  跳转到地址88
    086 JUMPDEST
    087 STOP               ;  停止执行 www.wnhack.com
    088 JUMPDEST。 (责任编辑:wnhack)
【声明】:无奈人生安全网(http://www.wnhack.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱472701013@qq.com,我们会在最短的时间内进行处理。