Just saw @0xkaden publish an interesting onchain CTF. The money was gone, but I wanted to walk through it so my followers and students can see how to approach these challenges.
The challenge: a contract with 0.1 ETH, no source code, just raw bytecode. Your mission: drain it.
First observation: the bytecode is tiny. This is perfect for brain symbolic execution 🤣
Let me show you the complete symbolic analysis...
INITIAL STATE
- Calldata: with the first 32 bytes denoted as CD
- Stack: []
ENTRY POINT (0x00-0x07)
This branches into code paths based on the value of CD

BRANCH A: CD == 0 (Delegatecall Path)
Standard proxy: forwards all calls to whatever address is stored in slot 0.

BRANCH B: CD != 0 (Upgrade Logic)
This is where it gets wild. Let me trace every single stack operation:

First check - selector validation:

Now the crazy bit manipulation to extract an address:

Now watch the stack ballet for the bit shifting:
The formula is: A = ((CD >> 8) << ((S+12)*8)) >> ((S+12)*8)
This keeps only the lower (256 - SHIFT) bits, effectively extracting an address from the calldata.

Now the second constraint - the code size check:

If both checks pass, update storage:

Now the task becomes clear. To drain the contract, we need an implementation contract satisfying these constraints:
Two Requirements:
1. S / 3 >= 1 → selector must be ≥ 3
2. EXTCODESIZE(A) == S / 3 → code size must equal S/3
How to construct such a contract?
Let's examine the winning solution. There are three transactions:
tx1 - deployment
tx2 - upgrade
tx3 - drain
The exploit contract at 0x000000000000AbCcd31Cd7F023902B3FA91e9b15 has only two opcodes:
0x33 = CALLER // Push msg.sender
0xff = SELFDESTRUCT // Send all ETH to caller
Code size = 2 bytes. When delegatecalled, it selfdestructs the proxy and sends all ETH to the caller.
Calldata of upgrade tx: 0x0000000000000000000000000000000000abccd31cd7f023902b3fa91e9b1506
Breaking it down:
Last byte: 0x06 (selector S)
Remaining bytes: encoded address data
S = 6 → S/3 = 2 ✅ matches the 2-byte contract size
SHIFT = (6+12)*8 = 144 bits preserves addresses with leading zeros perfectly
After bit manipulation: extracts 0x000000000000AbCcd31Cd7F023902B3FA91e9b15
Result: storage[0] now points to the exploit contract
8,16 tys.
61
Treści na tej stronie są dostarczane przez strony trzecie. O ile nie zaznaczono inaczej, OKX nie jest autorem cytowanych artykułów i nie rości sobie żadnych praw autorskich do tych materiałów. Treść jest dostarczana wyłącznie w celach informacyjnych i nie reprezentuje poglądów OKX. Nie mają one na celu jakiejkolwiek rekomendacji i nie powinny być traktowane jako porada inwestycyjna lub zachęta do zakupu lub sprzedaży aktywów cyfrowych. Treści, w zakresie w jakim jest wykorzystywana generatywna sztuczna inteligencja do dostarczania podsumowań lub innych informacji, mogą być niedokładne lub niespójne. Przeczytaj podlinkowany artykuł, aby uzyskać więcej szczegółów i informacji. OKX nie ponosi odpowiedzialności za treści hostowane na stronach osób trzecich. Posiadanie aktywów cyfrowych, w tym stablecoinów i NFT, wiąże się z wysokim stopniem ryzyka i może podlegać znacznym wahaniom. Musisz dokładnie rozważyć, czy handel lub posiadanie aktywów cyfrowych jest dla Ciebie odpowiednie w świetle Twojej sytuacji finansowej.


