[Dreamhack] Background: RELRO

#코딩노예#·2022년 7월 18일
0

Dreamhack - System Hacking

목록 보기
22/49

RELocation Read-Only(RELRO)

쓰기 권한이 불필요한 데이터 세그먼트에서 쓰기 권한을 제거합니다.

RELRO는 범위에 따라 부분적으로 적용하는 Partial RELRO와 가장 넓은 영역에 적용하는 Full RELRO가 있습니다.


실습 코드

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

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
  FILE *fp;
  char ch;
  fp = fopen("/proc/self/maps", "r");
  while (1) {
    ch = fgetc(fp);
    if (ch == EOF) break;
    putchar(ch);
  }
  return 0;
}

Partial RELRO

 kali@kali  ~/dreamhack/Bypass_PIE_RELRO/RELRO  gcc -o prelro relro.c -no-pie -fno-PIE
 kali@kali  ~/dreamhack/Bypass_PIE_RELRO/RELRO  checksec prelro 
[*] '/home/kali/dreamhack/Bypass_PIE_RELRO/RELRO/prelro'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

 kali@kali  ~/dreamhack/Bypass_PIE_RELRO/RELRO  ./prelro
00400000-00401000 r--p 00000000 08:01 2633797                            /home/kali/dreamhack/Bypass_PIE_RELRO/RELRO/prelro
00401000-00402000 r-xp 00001000 08:01 2633797                            /home/kali/dreamhack/Bypass_PIE_RELRO/RELRO/prelro
00402000-00403000 r--p 00002000 08:01 2633797                            /home/kali/dreamhack/Bypass_PIE_RELRO/RELRO/prelro
00403000-00404000 r--p 00002000 08:01 2633797                            /home/kali/dreamhack/Bypass_PIE_RELRO/RELRO/prelro
00404000-00405000 rw-p 00003000 08:01 2633797                            /home/kali/dreamhack/Bypass_PIE_RELRO/RELRO/prelro
01e6f000-01e90000 rw-p 00000000 00:00 0                                  [heap]
7f7f8ed69000-7f7f8ed6b000 rw-p 00000000 00:00 0 
7f7f8ed6b000-7f7f8ed91000 r--p 00000000 08:01 1835719                    /usr/lib/x86_64-linux-gnu/libc-2.33.so
7f7f8ed91000-7f7f8eee9000 r-xp 00026000 08:01 1835719                    /usr/lib/x86_64-linux-gnu/libc-2.33.so
7f7f8eee9000-7f7f8ef35000 r--p 0017e000 08:01 1835719                    /usr/lib/x86_64-linux-gnu/libc-2.33.so
7f7f8ef35000-7f7f8ef36000 ---p 001ca000 08:01 1835719                    /usr/lib/x86_64-linux-gnu/libc-2.33.so
7f7f8ef36000-7f7f8ef39000 r--p 001ca000 08:01 1835719                    /usr/lib/x86_64-linux-gnu/libc-2.33.so
7f7f8ef39000-7f7f8ef3c000 rw-p 001cd000 08:01 1835719                    /usr/lib/x86_64-linux-gnu/libc-2.33.so
7f7f8ef3c000-7f7f8ef47000 rw-p 00000000 00:00 0 
7f7f8ef5c000-7f7f8ef5d000 r--p 00000000 08:01 1835021                    /usr/lib/x86_64-linux-gnu/ld-2.33.so
7f7f8ef5d000-7f7f8ef81000 r-xp 00001000 08:01 1835021                    /usr/lib/x86_64-linux-gnu/ld-2.33.so
7f7f8ef81000-7f7f8ef8b000 r--p 00025000 08:01 1835021                    /usr/lib/x86_64-linux-gnu/ld-2.33.so
7f7f8ef8b000-7f7f8ef8d000 r--p 0002e000 08:01 1835021                    /usr/lib/x86_64-linux-gnu/ld-2.33.so
7f7f8ef8d000-7f7f8ef8f000 rw-p 00030000 08:01 1835021                    /usr/lib/x86_64-linux-gnu/ld-2.33.so
7ffc85840000-7ffc85861000 rw-p 00000000 00:00 0                          [stack]
7ffc859d9000-7ffc859dd000 r--p 00000000 00:00 0                          [vvar]
7ffc859dd000-7ffc859df000 r-xp 00000000 00:00 0                          [vdso]

쓰기 권한이 할당되어 있는 주소를 찾아보면 0x404000-0x405000에 쓰기 권한이 할당되어 있습니다.


 kali@kali  ~/dreamhack/Bypass_PIE_RELRO/RELRO  objdump -h ./prelro

./prelro:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn

 22 .got.plt      00000030  0000000000404000  0000000000404000  00003000  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 23 .data         00000010  0000000000404030  0000000000404030  00003030  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 24 .bss          00000008  0000000000404040  0000000000404040  00003040  2**0
                  ALLOC

이 주소에 해당하는 영역을 봐보면 .got.plt와 .data와 .bss 영역이 있습니다.

여기서 .got.plt 영역과 .got 영역의 차이점을 봐보면

.got 영역의 경우 프로그램이 실행되는 시점에 바인딩되는 변수가 위치합니다. 그래서 바이너리가 실행 중일 때는 더 이상 바인딩을 하지 않기 때문에 쓰기 권한을 부여하지 않습니다.

하지만 .got.plt 영역은 실행 중에 바인딩되는 변수가 위치합니다. 그래서 쓰기 권한이 남아 있습니다.

Partial RELRO가 적용된 바이너리에서 대부분의 함수들의 GOT 엔트리는 .got.plt에 저장됩니다.


Full RELRO

 kali@kali  ~/dreamhack/Bypass_PIE_RELRO/RELRO  gcc -o frelro relro.c -z now          
 kali@kali  ~/dreamhack/Bypass_PIE_RELRO/RELRO  checksec frelro  
[*] '/home/kali/dreamhack/Bypass_PIE_RELRO/RELRO/frelro'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled

Full RELRO가 적용되면 모든 라이브러리 함수들의 주소가 바이너리 로딩 시점에 바인딩됩니다. 그래서 GOT에는 쓰기 권한이 없고 data와 bss에만 쓰기 권한이 있습니다.


RELRO 우회

Parital RELRO의 경우 .got.plt 영역에 대한 쓰기 권한이 존재해서 GOT Overwrite를 할 수 있습니다.

Full RELRO의 경우 .got 영역에 대한 쓰기 권한이 없어서 GOT Overwrite를 할 수 없습니다.

하지만 hook 함수의 경우 Full RELRO 방어기법이 걸려 있어도 주소를 덮어쓸 수 있습니다.

대표적인 hook 함수인 malloc hook이나 free hook을 이용해서 Hook Overwrite를 하면 Full RELRO 상황에서도 프로그램의 실행 흐름을 조작할 수 있습니다.



Background: RELRO

0개의 댓글