ctfwriteup.com
Search…
⌃K

Puzzle 4

ADDRESS, BALANCE

Puzzle

############
# Puzzle 4 #
############
00 30 ADDRESS
01 31 BALANCE
02 36 CALLDATASIZE
03 6000 PUSH1 00
05 6000 PUSH1 00
07 37 CALLDATACOPY
08 36 CALLDATASIZE
09 6000 PUSH1 00
0B 30 ADDRESS
0C 31 BALANCE
0D F0 CREATE
0E 31 BALANCE
0F 90 SWAP1
10 04 DIV
11 6002 PUSH1 02
13 14 EQ
14 6018 PUSH1 18
16 57 JUMPI
17 FD REVERT
18 5B JUMPDEST
19 00 STOP
? Enter the value to send: (0)

Solution

This combo:
ADDRESS
BALANCE
is equivalent to:
address(this).balance
Pseudocode:
// Copy calldata to memory offset 0
calldatacopy(0, 0, calldata_size);
// Create a new contract and give it all the balance of the current contract
create(address(this).balance, 0x00, calldata_size);
if (old_contract_balance / new_contract_balance == 2) {
jump(0x18);
}
The new contract must burn half of the balance it receives. For example, if the challenge contract has 8 wei, then 4 wei is sent to the new contract when create() is called. Once received, the new contract must burn 4 wei so that 8 wei / 4 wei == 2.
Burning half of the balance is equivalent to sending them to the zero address. Suppose we are sending 8 wei as msg.value, then we need to burn 4 wei in the new contract. This can be done with CALL:
PUSH1 0x00 // retSize
DUP1 // retOffset
DUP1 // argsSize
DUP1 // argsOffset
PUSH1 0x04 // value
DUP2 // address
GAS // gas
CALL
PUSH1 0x00
DUP1
RETURN
We are not returning anything because nothing needs to be returned, but the RETURN part of the code is needed to terminate the contract.
Compile:
60008080806004815af1600080f3
Last modified 1d ago