ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Linux Exploitation & Mitigation]-ASLR / PLT,GOT
    System Security/dreamhack 2021. 3. 16. 00:24

     

    * 드림핵 <system exploitation fundamental> 공부한 후 정리한 내용이다.

     

    1. ASLR

     

    Address Space Layout Randomization은 바이너리가 실행될 때마다 라이브러리, 힙, 스택 영역 등의 주소가 랜덤하게 바뀌도록 해 RTL처럼 고정된 주소값을 이용하는 공격을 막기 위한 메모리 보호 기법이다.

    aslr은 서버의 설정 파일에 의해 보호 기법 적용이 결정된다.

    더보기

    /proc/sys/kernel/randomize_va_space 를 확인해 적용 여부를 확인할 수 있다.

    0 : 적용 x

    1: 스택, 힙 메모리 랜덤화

    2: 스택, 힙, 라이브러리 메모리 랜덤화

     

    aslr을 적용시켜 스택, 힙 , 라이브러리 메모리 주소는 랜덤화 시킬 수 있지만 코드 영역의 주소는 변하지 않는다. 이를 이용해 aslr 보호 기법을 우회해 익스플로잇을 할 수 있다.

     

     

    example4.c는 scanf로 buf 값을 받아오는데, 포맷 스트링이 %s로, 입력 길이의 제한이 없어 스택 버퍼 오버플로우 취약점을 갖고 있다. 해당 파일을 익스플로잇해 /bin/sh 바이너리를 실행해보는 실습을 진행해보자.

     

     

    example4.c

    먼저 스택에 NX bit가 설정되어 있나 확인해본다.

    nx bit 설정 여부 확인

    rw인것으로 보아 스택에 실행권한이 없다. 따라서 nx bit가 설정되어 있음을 알 수 있다.

     

    이제 return addr을 덮어 볼건데,

    먼저 컴파일 후 gdb 디버깅을 진행한다.

     

    example4.c 컴파일

    main을 disas 해본 결과 strcpy 의 두번째 인자인 buf의 크기가 0x24, 즉 36byte인 것을 확인할 수 있다.

     

    return addr을 덮으려면 40byte가 필요하다.

    40byte의 A와 BBBB를 입력해 return addr을 덮어보자.

     

     

    main 이 ret후, eip의 레지스터 값이 bbbb로 채워진 것을 확인할 수 있다.

     

    example4는 nx bit가 걸려있기 때문에 프로그램이 비정상 종료되지 않으려면  실행 권한이 있는 코드 영역으로 덮어야 한다.

    참고로 aslr이 적용되어 있더라도 바이너리 코드 영역의 주소는 랜덤하게 바뀌지 않는다는 것을 확인했다.

     

     

     

    2. PLT, GOT

    plt : procedure linkage table, 외부 라이브러리 함수를 사용할 수 있도록 주소를 연결해주는 역할을 하는 테이블

    got : global offset table, plt에서 호출하는 reslove 함수를 통해 구한 라이브러리 함수의 절대주소 저장되어 있는 테이블

     

     

    plt 와 got 개념을 직접 확인해보자.

     

    example4.c

    example4.c 파일을 다음과 같이 컴파일 한 후 (pie를 해제해야 한다.)

    PLT와 GOT에 대해 알아보기 위해 0x080491c3 에 bp를 걸어 확인해보자.

     

    si 결과

    출력 결과를 보니 puts가 호출되면 0x804c00c에 저장되어 있는 값으로 jmp를 한 뒤 0x8049020으로 jmp 하는 것을 확인할 수 있다.

    각각의 메모리 주소를 확인해보자.

    0x804c00c 메모리를 확인해보니 0x08049036이 저장되어 있다. 즉 0x08049036으로 jump 한 것이다. 이는 puts@plt+6의 주소이다.

    puts@plt+6에서는 0을 push 한뒤 0x8049020로 jump한다. 해당 주소의 명령어를 보니 0x804c008에 저장되어 있는 값으로 jmp를 한다. 저장되어 있는 값은 바로 0xb7feb730으로, 이 값으로 jump를 하는 것이다.

    그럼 해당 주소가 무엇을 하는 지 알아보자. 

     

    ret에 bp를 걸고 esp값을 확인해보자.

    확인해본 결과 ret하는 시점에 puts 함수로 이동하는 것을 확인할 수 있다.

    즉, 0xb7feb730은 호출된 라이브러리 함수의 실제 주소를 GOT에 저장한 후 해당 주소로 jump하는 함수였던 것이다.

     

    --> 특정 함수의 PLT를 호출한다는 것은 실제 주소를 호출하는 것과 같은 효과이다.

     

     

    동작 원리를 간단히 설명하면 다음과 같다.

    plt에서 got로 넘어가 여러 과정을 거쳐 실제 함수 주소가 구해지면, 그 주소가 got에 들어간다는 것이다.

    plt의 주소는 고정되어 있기 때문에 PLT에 존재하는 함수들( 프로그램에서 한 번 이상은 호출하는 라이브러리 함수들)은 고정된 주소를 통해 호출할 수 있다.

     

    ASLR이 적용되어 있는 경우에는 동적 라이브러리를 링크하여 실행하는 바이너리가 실행될 때마다 라이브러리가 메모리에 매핑되는 주소가 달라진다. 따라서 바이너리가 실행되기 전까지는 라이브러리 함수의 주소를 알 수 없다. 하지만 plt의 주소는 고정되어 있어서 aslr이 적용되어 있어도 plt로 jump하여 RTL과같은 공격이 가능해진다. 따라서 라이브러리 함수를 호출할 때 GOT에 저장된 주로 JUMP하는데, 이때 GOT에 저장된 값을 바꿔 원하는 주소로 이동하게 할 수 있다.

     

     

    example4 의 main에 bp를 걸고 실행시킨 후 puts 함수의 GOT 인 0x804c00c의 값을 0xdeadbeef로 변경해보자.

    puts를 호출하면 puts의 GOT 에 저장된 값으로 이동해서 실제 주소를 호출하는게 가능해지지만

    GOT에 저장된 값을 0xdeadbeef로 변경했더니, 그 값으로 jump하게 되어 eip 레지스터 값이 0xdeadbeef으로 바뀐 것을 확인할 수 있다.

    즉 GOT 에 저장된 값을 변경해서, 라이브러리 함수가 호출될 때 공격자가 원하는 주소로 이동할 수 있도록 조작하는 것이 가능하다.

    하지만 example4 예제는 쉘을 획득하는 데 필요한 system이나 execve를 사용하지 않아 aslr 환경에서는 직접 저런 함수들을 호출할 수 없게 된다. 

     

    이렇게 PLT에는 프로그램 내에서 호출하는 함수들만 존재하기 때문에 100%에 가까운 확률로 익스플로잇을 할 수 있는 공격기법이 바로 ROP이다. ROP에 대해서는 다음 포스팅에 정리하겠다.

     

     

     

    'System Security > dreamhack' 카테고리의 다른 글

    [Linux Exploitation & Mitigation] NX bit / RTL  (0) 2021.03.15
    시스템 해킹 기초  (0) 2021.03.09

    댓글

Designed by Tistory.