혜랑's STORY

Linux Exploitation & Mitigation Part 2 (1) 본문

무지성 공부방/Dreamhack SystemHacking

Linux Exploitation & Mitigation Part 2 (1)

hyerang0125 2021. 2. 21. 20:02
본 포스팅은 DreamHack 사이트의 Linux Exploitation & Mitigation Part 1 강의 내용을 요약한 것이다. 강의의 주소는 다음과 같다.
 

해커들의 놀이터, Dreamhack

해킹과 보안에 대한 공부를 하고 싶은 학생, 안전한 코드를 작성하고 싶은 개발자, 보안 지식과 실력을 업그레이드 시키고 싶은 보안 전문가까지 함께 공부하고 연습하며 지식을 나누고 실력 향

dreamhack.io

1. ASLR(Address Space Layout Randomization)

 라이브러리, 힙, 스택 영역 등의 주소를 바이너리가 실행될때마다 랜덤하게 바꿔 RTL과 같이 정해진 주소를 이용한 공격을 막기 위한 보호 기법이다. NX bit와 달리 서버의 설정 파일에 의해 보호기법의 적용이 결정된다.

우분투에서 /proc/sys/kernel/randomize_va_space 파일의 값을 확인하면 서버의 ASLR 설정 여부를 알 수 있다. 설정 파일의 값으로는 0, 1, 2가 있다.

  • 0 : ASLR을 적용하지 않음
  • 1 : 스택, 힙 메모리를 랜덤화
  • 2 : 스택, 힙 라이브러리 메모리를 랜덤화

만약 해당 파일의 값이 2가 아니라면, 루트 권한으로 다음 명령어를 실행하여 ASLR 보호 기법을 적용할 수 있다.

echo 2 > /proc/sys/kernel/randomize_va_space

>> example3.c

//example3.c
//gcc -o example3 example3.c -m32

#include <stdio.h>
#include <stdlib.h>

int main(void){
  char * buf = (char *)calloc(1, 4096);
  FILE * fp = 0;
  size_t sz = 0;
  
  fp = fopen("/proc/self/maps", "r");
  sz = fread(buf, 1, 4096, fp);
  
  fwrite(buf, 1, sz, stdout);
}

example3.c 실행 결과

서버에 ASLR이 켜져있을 때, 라이브러리, 힙, 스택 영역의 주소가 랜덤하게 바뀌는 것을 확인할 수 있다.

라이브러리 주소가 계속 바뀌기 때문에, 스택 버퍼 오버플로우 취약점을 공격할 때 정적 주소를 이용한 공격을 사용할 수 없다. 하지만 example3의 실행 결과를 보면 알 수 있듯이, 바이너리 코드 영역의 주소는 변하지 않는다. 

이를 이용해 ASLR 보호 기법을 우회하여 익스플로잇할 수 있다.

 

2. PLT, GOT Section

Procedure Linkage Table(PLT)는 외부 라이브러리 함수를 사용할 수 있도록 주소를 연결해주는 역할을 하는 테이블이다. Global Offset Table(GOT)는 PLT에서 호출하는 resolve 함수를 통해 구한 라이브러리 함수의 절대 주소가 저장되어있는 테이블이다.

ASLR이 적용되어 있는 환경에서, 동적으로 라이브러리 링크하여 실행되는 바이너리는 바이너리가 실행될 때마다 라이브러리가 매핑되는 메모리의 주소가 변한다.

라이브러리가 메모리에 매핑된 후 라이브러리 함수가 호출되면, 정적 주소를 통해 해당 함수의 PLT와 GOT 영역에 접근함으로써 함수의 주소를 찾는다.

디버깅을 통해 puts 함수를 호출했을 떄 PLT에서 어떤 일을 하는지 확인해 보자. (직접 실행해보려했으나 강의처럼 되지 않아 일단 강의에 있는 내용을 사용합니다!)

(gdb) b*0x8048485
Breakpoint 1 at 0x8048485
(gdb) r
Starting program: ~/example4 
Breakpoint 1, 0x08048485 in main ()
(gdb) x/i $eip
=> 0x8048485 <main+42>:	call   0x8048320 <puts@plt>
(gdb) si
0x08048320 in puts@plt ()
(gdb) x/4i $eip
=> 0x8048320 <puts@plt>:	jmp    DWORD PTR ds:0x804a00c
   0x8048326 <puts@plt+6>:	push   0x0
   0x804832b <puts@plt+11>:	jmp    0x8048310
   0x8048330 <__libc_start_main@plt>:	jmp    DWORD PTR ds:0x804a010
(gdb) x/wx 0x804a00c
0x804a00c:	0x08048326
(gdb) x/2i 0x8048310
   0x8048310:	push   DWORD PTR ds:0x804a004
   0x8048316:	jmp    DWORD PTR ds:0x804a008
(gdb) x/wx 0x804a008
0x804a008:	0xf7fee000

 

puts@plt+0에서는 0x804a00c 메모리를 참조하여 저장되어있는 값으로 점프한다. 해당 메모리에는 puts@plt+6의 주소가 저장되어 있다. puts@plt+6에서는 스택에 -을 push한 후 0x8048310 함수로 점프한다. 이후에는 ox804a008 주소에 저장되어 있는 0xf7fee00 함수로 점프한다.

브레이크포인트를 설정해 스택 메모리를 확인해 보았다. puts 함수로 점프하는 것으로 보아, 0xf7fee00  함수는 호출된 라이브러리 함수의 주소를 알아내는 함수라는 것을 알 수 있다.

(gdb) x/11i 0xf7fee000
   0xf7fee000:	push   eax
   0xf7fee001:	push   ecx
   0xf7fee002:	push   edx
   0xf7fee003:	mov    edx,DWORD PTR [esp+0x10]
   0xf7fee007:	mov    eax,DWORD PTR [esp+0xc]
   0xf7fee00b:	call   0xf7fe77e0
   0xf7fee010:	pop    edx
   0xf7fee011:	mov    ecx,DWORD PTR [esp]
   0xf7fee014:	mov    DWORD PTR [esp],eax
   0xf7fee017:	mov    eax,DWORD PTR [esp+0x4]
   0xf7fee01b:	ret    0xc
(gdb) b*0xf7fee01b
Breakpoint 2 at 0xf7fee01b
(gdb) c
Continuing.
Breakpoint 2, 0xf7fee01b in ?? () from /lib/ld-linux.so.2
(gdb) x/wx $esp
0xffffd520:	0xf7e62ca0
(gdb) x/i 0xf7e62ca0
   0xf7e62ca0 <puts>:	push   %ebp
(gdb) 

 

- Abusing PLT, GOT

특정 함수의 PLT를 호출하면 함수의 실제 주소를 호출하는 것과 같은 효과를 나타내고, PLT의 주소는 고정되어 있기 때문에 서버에 ASLR 보호 기법이 적용되어 있어도 PLT로 점프하면 RTL과 비슷한 공격을 할 수 있다. 그러나 최종 목표인 쉘을 획득하는데 필요한 함수들을 사용하지 않기 때문에 ASLR 환경에서 직접적으로 해당 함수들을 호출할 수 없다.