Chain Heist Writeup – Peter Kacherginsky
It was possible to track current participants and points scored on the Bounty Hunter page. Here you can see the tight race between myself and maurelian toward the end of the contest:
Account Unlock (easy)
Challenge: Help me find the password stored at the contract address 0x8e852b8ce63a2d1b4d4E7d3404c05363a32F0AB0
pragma solidity ^0.5.0;contract AccountUnlock
}
Based on the source above, the contract is unlocked with a value stored in the first storage slot “password”. We are going to use the excellent mythril utility to read what is stored there:
$ myth read-storage — rpc infura-ropsten 0 0x8e852b8ce63a2d1b4d4E7d3404c05363a32F0AB0
0: 0x5374726f6e6750617373776f7264313233000000000000000000000000000022
Converting the above hex values to ASCII gives used the password: StrongPassword123
Bank Locker (medium)
Challenge: Getting more than what you deposit is always fun. Drain the target contract of all its Ether.
pragma solidity ^0.5.0;import "../zeppelin/SafeMath.sol";contract Locker modifier alreadyExists() function createAcc() public alreadyExists() function deposit() internal checkPoint() function checkBalanceUser() public view checkPoint() returns(uint256) function withDraw(uint256 _amount) public checkPoint() function closeAccount() public checkPoint() function checkBalance() view public returns(uint256) function() payable external
}
The above code is vulnerable to the reentrancy vulnerability when calling the closeAccount() function. We can exploit it with the following contract which will continuously call the vulnerable function every time it receives funds:
contract Reenter function attack() public
function() external payable
}
}
Challenge: Ethereum is an open platform with lots of visibility. But if the source code isn’t provided you’ll have to figure out on your own what a contract can do. Deploy this contract and then change the value of ‘solved’ to boolean true.
pragma solidity ^0.5.0;contract ReverseEng
}
The contract source code is mostly missing so we need to decompile the bytecode first:
bool solved;function 799320bb() public view function () public payable
The contract defines a single fallback payable function which flips the solved variable. It requires exactly 42 Wei in order to run.
Challenge: Can you please register a vehicle with Serial Number “12345” and OwnerName “RandomUser”
pragma solidity ^0.4.24;contract VehicleRegister struct UniqueTag mapping(uint256 => bytes32) private registrationTagRecord;
mapping(bytes32 => bool) private registrationTagRecordExists;
mapping(bytes32 => UniqueTag) private uniqueIDRecord; function registerVehicle(uint256 _serialNumber, string _Ownername) public function getRegistrationTag(uint256 _serialNumber) public view returns (bytes32) function getUniqueID(bytes32 _registrationTag, string _licenseNumber)public returns (bytes32)
bytes32 _uniqueID = keccak256(abi.encode(_registrationTag,_licenseNumber));
uniqueIDRecord[_uniqueID]=instance;
return _uniqueID;
} function registrationTagVerify(bytes32 _registrationTag) public view returns (bool)
}
In order to register a new vehicle we must call registerVehicle() function. Unfortunately, the boolean variable registrationAllowed is set to False with no apparent way of resetting it.
Notice two structs in the source code above: Record and UniqueTag. An important feature of structs is that unless you specify the “memory” keyword when accessing them inside a function they will default to global storage. This could have undesirable effect of overwriting whatever is stored there. The getUniqueID is missing the “memory” keyword so it would in fact overwrite anything in storage:
function getUniqueID(bytes32 _registrationTag,string _licenseNumber)public returns (bytes32){
UniqueTag instance; // Missing “memory” keyword
instance.registrationTag = _registrationTag; // storage 0
instance.licenseNumber =_licenseNumber; // storage 1
The first storage slot is in fact boolean registrationAllowed which is preventing us from registering a new vehicle. It is currently set to false:
$ myth read-storage --rpc infura-ropsten 0 0x7c9Fab75f24850b3C7f54233B8d269766D6d297f
0: 0x0000000000000000000000000000000000000000000000000000000000000000
Let’s overwrite it by exploiting the above vulnerability using Remix:
Checking the storage slot again confirms that it was reset to true:
$ myth read-storage --rpc infura-ropsten 0 0x7c9Fab75f24850b3C7f54233B8d269766D6d297f
0: 0x0000000000000000000000000000000000000000000000000000000000000001
At this point we can submit a new transaction to register a vehicle and complete the challenge.
Published at Thu, 19 Sep 2019 00:36:08 +0000
Bitcoin Pic Of The Moment
✅ This image from Marco Verch (trendingtopics) is available under Creative Commons 2.0. Please link to the original photo and the license. 📝 License for use outside of the Creative Commons is available by request.
By trendingtopics on 2019-04-01 05:01:31
