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,17 тыс.
61
Содержание этой страницы предоставляется третьими сторонами. OKX не является автором цитируемых статей и не имеет на них авторских прав, если не указано иное. Материалы предоставляются исключительно в информационных целях и не отражают мнения OKX. Материалы не являются инвестиционным советом и призывом к покупке или продаже цифровых активов. Раздел использует ИИ для создания обзоров и кратких содержаний предоставленных материалов. Обратите внимание, что информация, сгенерированная ИИ, может быть неточной и непоследовательной. Для получения полной информации изучите соответствующую оригинальную статью. OKX не несет ответственности за материалы, содержащиеся на сторонних сайтах. Цифровые активы, в том числе стейблкоины и NFT, подвержены высокому риску, а их стоимость может сильно колебаться. Перед торговлей и покупкой цифровых активов оцените ваше финансовое состояние и принимайте только взвешенные решения.


