diff --git a/src/Curta/20_Lana/Exploit.s.sol b/src/Curta/20_Lana/Exploit.s.sol new file mode 100644 index 0000000..95763cc --- /dev/null +++ b/src/Curta/20_Lana/Exploit.s.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.13; + +import {Script, console2} from "forge-std/Script.sol"; +import {ICurta} from "../general/ICurta.sol"; +import {Lana} from "./challenge/Challenge.sol"; + +// forge script src/Curta/20/Exploit.s.sol:ExploitScript --private-key $PRIVATE_KEY -vvvvv +// forge script src/Curta/20/Exploit.s.sol:ExploitScript --private-key $PRIVATE_KEY -vvvvv --broadcast + +contract ExploitScript is Script { + function run() public { + vm.startBroadcast(); + + address curtaAddr = 0x0000000006bC8D9e5e9d436217B88De704a9F307; + address challengeAddr = 0xaffb3F98c2BABe229aE8586E1c2c1B4af6BB26F5; + vm.deal(msg.sender, 1 ether); + uint32 puzzleId = 20; + + ICurta curta = ICurta(curtaAddr); + Lana puzzle = Lana(challengeAddr); + + bytes memory val = + hex"4444434343424343434342424142414269414141414141414141414141414141414141414141414141414141414141414141414141414141414143434343434343434343434343434343434343434343434343434343434343434343434343437E"; + puzzle.solve(val, msg.sender); + curta.solve(puzzleId, uint256(keccak256(val))); + + vm.stopBroadcast(); + } +} diff --git a/src/Curta/20_Lana/Exploit.t.sol b/src/Curta/20_Lana/Exploit.t.sol new file mode 100644 index 0000000..1f3921a --- /dev/null +++ b/src/Curta/20_Lana/Exploit.t.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.13; + +import {Test, console2} from "forge-std/Test.sol"; +import {Curta} from "../general/CurtaLocal.sol"; +import {Lana} from "./challenge/Challenge.sol"; +import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; +import {ICurta} from "../general/ICurta.sol"; + +contract ExploitTest is Test { + address playerAddr = 0x1317B995c20000C085Af006Ba2f311c107cAc7aD; + Curta curta; + Lana puzzle; + uint32 puzzleId = 20; + + function setUp() public { + curta = new Curta(); + curta.setPuzzleId(puzzleId - 1); + puzzle = new Lana(); + curta.addPuzzle(puzzle, 0); + vm.deal(playerAddr, 1 ether); + } + + function test() public { + vm.startPrank(playerAddr, playerAddr); + + bytes memory val = + hex"4444434343424343434342424142414269414141414141414141414141414141414141414141414141414141414141414141414141414141414143434343434343434343434343434343434343434343434343434343434343434343434343437E"; + puzzle.solve(val, playerAddr); + curta.solve(puzzleId, uint256(keccak256(val))); + + vm.stopPrank(); + } +} diff --git a/src/Curta/20_Lana/challenge/Challenge.sol b/src/Curta/20_Lana/challenge/Challenge.sol new file mode 100644 index 0000000..387c7f0 --- /dev/null +++ b/src/Curta/20_Lana/challenge/Challenge.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import {IPuzzle} from "../../general/IPuzzle.sol"; + +contract Lana is IPuzzle { + mapping(uint256 => uint256) solvers; + + function name() external pure returns (string memory) { + return "Lana"; + } + + function generate(address _seed) external pure returns (uint256) { + return uint256(uint160(_seed)); + } + + function verify(uint256 start, uint256 _solution) external view returns (bool) { + assert(solvers[start] != 0); + return _solution == solvers[start]; + } + + function solve(bytes calldata val, address start) external { + bytes memory data = + hex"61094c8061000e6000396000f3fe600080620100206080815261010082608037660fffffffffffff6106075262010140926105e784525b8015610938578060011461091057806002146108fb57806003146108e657806004146108c857806005146104b557806006146108b0578060071461089e578060091461087e5780600a146108675780600b146108565780600c146108465780600d146108385780600e146108205780600f146107f257806010146107e057806012146107c857806013146107a95780601414610791578060151461077957806016146107645780601714610750578060181461073c57806019146106f35780601a146107235780601b1461069d5780601c1461070f5780601d146106fb5780601e146106f35780601f146106db57806020146106bd578060211461069d57806022146106a5578060231461069d578060241461068657806025146106725780602614610653578060271461063b5780602814610623578060291461060b5780602a146105f15780602b146105d95780602c146105bb5780602d1461059f5780602e146105835780602f14610563578060301461054a578060311461052a5780603214610513578060331461050157806035146104e757806036146104cc57806037146104b557806038146104a657806039146104975780603a146104895780603b146104815780603c146104725780603d146104575780603e146104445780603f146104365780604014610422578060411461040a57806042146103ee57806043146103d657806044146103bf57806045146103a5578060461461039d5780604714610386578060481461036a57806049146103475780604a146103335780604b1461031b5780604c146102fc5780604d146102e45780604e146102cb5780604f146102b35760501461029d57602062010000f35b8251610200602082018086525191018452610028565b5062010000600160401b602082510890526050610028565b508051600160401b62010000918251089052604f610028565b506001600160401b03815160081b168152604e610028565b506001600160401b03815160c090811b901d60381d168152604d610028565b506001600160401b03815160381b168152604c610028565b508051601c19015160ff168152604b610028565b50620100006001600160401b03815160c090811b901d60381d169052604a610028565b50620100006001600160401b03815160381b1690526049610028565b508051601b19015160ff1662010000526048610028565b506050610028565b50604662010060516201008051036100285750603c610028565b506201006060ff6061825101511690526045610028565b50620100808051601e19015160ff1690526044610028565b506201006051600160401b620100809182510890526043610028565b506001600160401b0381511662010080526042610028565b506041620100805161002857506047610028565b508162010040526040610028565b506201008060018151169052603f610028565b506001600160401b036201004051166201008052603e610028565b5060066201006052603d610028565b506041610028565b50816201000052603b610028565b5060016201004052603a610028565b50600562010060526039610028565b508251610200602082018086525191018452610028565b506001600160401b0362010100511662010000526037610028565b5060366104f48251151590565b156100285750600e610028565b5063fffffffe62010100526035610028565b506201004051601e19015160ff1681526033610028565b50620100c05160171901516001600160401b031662010040526032610028565b5062010120600160401b60001982510890526031610028565b5060306105766201000051610423141590565b1561002857506036610028565b50620100006001600160401b03815160201c169052602f610028565b50620100006001600160401b03815160201b169052602e610028565b5082516101df1901808452602d90528251601f190183526038610028565b506001600160401b03620100e051168152602c610028565b50602b6105fe8251151590565b1561002857506030610028565b506001600160401b03815160201c168152602a610028565b506001600160401b03815160201b1681526029610028565b506001600160401b0362010120511681526028610028565b50601e19620100e0510160ff1981511660ff8351161790526027610028565b50600160401b600182510881526026610028565b50620100e051601e19015160ff1681526025610028565b506027610028565b50620100e0600160401b600182510890526023610028565b5082516101df1901808452602190528251601f190183526006610028565b506001600160401b03620100c0511681526020610028565b506036610028565b50601e60448251036100285750601f610028565b50601d604382510361002857506024610028565b50620100e0600160401b6000198251089052601b610028565b50601960428251036100285750601a610028565b506018604182510361002857506022610028565b5060176042825113156100285750601c610028565b506001600160401b03815160201c1681526016610028565b506001600160401b03815160201b1681526015610028565b506001600160401b03815160c090811b901d60381d1681526014610028565b506001600160401b03815160381b1681526013610028565b5063ffffffff62010100526012610028565b50601719620100c051016001600160401b03198151166001600160401b036201004051161790526010610028565b5062010040600160401b60018251089052600f610028565b50600e806201012052610028565b50610200620100e052600d610028565b50600c815161002857506036610028565b506201004051601e19015160ff168152600b610028565b50620100c05160171901516001600160401b03166201004052600a610028565b5063fffffffe62010100526009610028565b506001600160401b03815116620100c0526007610028565b5082516101df1901808452600590528251601f190183526006610028565b50600160401b60071982510881526004610028565b506001600160401b0383511681526003610028565b50601f198351016001600160401b03198151166001600160401b038351161790526002610028565b50600160401b60208251088152600161002856"; + + assembly { + let addr := create(0, add(data, 32), mload(data)) + let sz := extcodesize(addr) + if iszero(sz) { revert(0, 0) } + + let code := mload(0x40) + + mstore(add(code, 0x14), start) + calldatacopy(add(code, 0x40), val.offset, val.length) + + let success := call(gas(), addr, 0, add(code, 0x20), 0x100, code, 0x20) + if or(iszero(eq(returndatasize(), 0x20)), iszero(success)) { revert(0, 0) } + + let secret := mload(code) + if iszero(eq(secret, 0x1337)) { revert(0, 0) } + } + + solvers[uint256(uint160(start))] = uint256(keccak256(val)); + } +} diff --git a/src/Curta/20_Lana/generate_payload.py b/src/Curta/20_Lana/generate_payload.py new file mode 100644 index 0000000..e2e7a72 --- /dev/null +++ b/src/Curta/20_Lana/generate_payload.py @@ -0,0 +1,8 @@ +print((""" +export CALLDATA=0x +1317376e0b00007e4b9dbbb794e583387437214a000000000000000000000000 +4444 +4343434243434343424241424142 +69""" + ("41" * 0x29) + ("43" * (0x47 - 0x21)) + """ +7E +""").replace("\n", "")) diff --git a/src/Curta/general/CurtaLocal.sol b/src/Curta/general/CurtaLocal.sol index 674560f..eb84f74 100644 --- a/src/Curta/general/CurtaLocal.sol +++ b/src/Curta/general/CurtaLocal.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT // from: https://github.com/waterfall-mkt/curta/blob/main/src/Curta.sol -pragma solidity ^0.8.17; +pragma solidity ^0.8.13; import {ICurta} from "./ICurta.sol"; import {IPuzzle} from "./IPuzzle.sol"; diff --git a/src/Curta/general/ICurta.sol b/src/Curta/general/ICurta.sol index 468547f..cf19ff3 100644 --- a/src/Curta/general/ICurta.sol +++ b/src/Curta/general/ICurta.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT // from: https://github.com/waterfall-mkt/curta/blob/main/src/interfaces/ICurta.sol -pragma solidity ^0.8.17; +pragma solidity ^0.8.13; import {IPuzzle} from "./IPuzzle.sol"; diff --git a/src/Curta/general/IPuzzle.sol b/src/Curta/general/IPuzzle.sol index f40c444..0cecf9e 100644 --- a/src/Curta/general/IPuzzle.sol +++ b/src/Curta/general/IPuzzle.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT // from https://github.com/waterfall-mkt/curta/blob/main/src/interfaces/IPuzzle.sol -pragma solidity ^0.8.17; +pragma solidity ^0.8.13; interface IPuzzle { function name() external pure returns (string memory);