ctfwriteup.com
Search…
⌃K

Puzzle 10

Puzzle

#############
# Puzzle 10 #
#############
00 6020 PUSH1 20
02 6000 PUSH1 00
04 6000 PUSH1 00
06 37 CALLDATACOPY
07 6000 PUSH1 00
09 51 MLOAD
0A 7FF0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 PUSH32 F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0
2B 16 AND
2C 6020 PUSH1 20
2E 6020 PUSH1 20
30 6000 PUSH1 00
32 37 CALLDATACOPY
33 6000 PUSH1 00
35 51 MLOAD
36 17 OR
37 7FABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB PUSH32 ABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB
58 14 EQ
59 605D PUSH1 5D
5B 57 JUMPI
5C FD REVERT
5D 5B JUMPDEST
5E 00 STOP
? Enter the calldata:

Solution

Pseudocode:
calldatacopy(0, 0, 0x20); // store 1st 32 bytes of calldata in memory
calldata_first_half = mload(0x00); // load 1st 32 bytes of calldata onto the stack
calldatacopy(0, 0x20, 0x20); // store 2nd 32 bytes of calldata in memory
calldata_second_half = mload(0x00) // load 2nd 32 bytes of calldata onto the stack
first_computation = calldata_first_half & 0xF0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0;
second_computation = first_computation | calldata_second_half;
if (second_computation == 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB) {
jump(0x5D);
}
first_computation can be zeroed out if calldata_first_half contains only 0x00, so we only have to worry about the second half of calldata.
Recall that 0 | 1 == 1, a generalization of that is 0x0000... | x == x. In order to get first_computation | calldata_second_half == 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB, we can simply let `calldata_second_half = 0xABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB.
The final calldata payload is:
0x0000000000000000000000000000000000000000000000000000000000000000ABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB