본문 바로가기

Dreamhack/Lecture & Practice

[Lecture] PIE (Position-Independent Executable)

1. PIC (Position-Independent Code) 정의

  • 리눅스에서 ELF에는 실행파일(Executable)과 공유 오브젝트(Shared Object, SO)가 존재하며, 공유 오브젝트는 libc.so와 같은 라이브러리 파일이 해당된다.
  • 공유 오브젝트는 기본적으로 재배치가 가능하도록 설계되어 있는데, 이러한 성질을 만족하는 코드를 PIC라고 한다.
  • gcc는 PIC 컴파일을 지원한다.
   
    [참고]

    '재배치가 가능하다는 것'은 메모리의 어느 주소에 적재되어도, 코드의 의미가 훼손되지 않음을 의미한다.

2. PIC 실습

2-1. 실습 코드

 

  • PIC 적용된 바이너리와 적용되지 않은 바이너리 비교를 위해, 두 가지 방식으로 컴파일해준다.
// Name: pic.c
// Compile: gcc -o pic pic.c
// 	      : gcc -o no_pic pic.c -fno-pic -no-pie

#include <stdio.h>
char *data = "Hello World!";

int main() {
  printf("%s", data);
  return 0;
}

 

2-2. PIC 실습 결과

 

  • 두 파일에서 main함수를 비교해보면, [main + 14]에서 "%p"문자열을 printf에 전달하는 방식이 다른 것을 볼 수 있다.
    • pic가 적용되지 않은 파일의 경우, 0x4005a1라는 절대 주소로 문자열을 참조하고 있다.
    • pic가 적용된 파일은 문자열 주소를 [rip + 0xa2]로 참조하고 있다.
  • 이를 통해 알 수 있는 점은 아래와 같다.
    • pic가 적용되지 않은 파일 경우, 바이너리가 매핑되는 주소가 바뀌면 0x4005a1에 있던 데이터도 함께 이동하므로 코드를 제대로 실행하지 못한다.
    • pic가 적용된 파일은 rip을 기준으로 데이터를 상대 참조하기 때문에, 바이너리가 무작위 주소에 매핑되어도 제대로 실행된다.

3. PIE (Position-Idependent Executable)

  • ASLR이 코드 영역에도 적용되게 해주는 기술로, 무작위 주소에 매핑해도 실행 가능한 실행파일이다.
  • ASLR이 생기기 전, 기존 실행파일은 재배치를 고려하지 않고 설계되었기 때문에, 개발자들은 원래 재배치가 가능했던 공유 오브젝트를 실행 파일로 사용하기로 한다.
  • 현대의 gcc는 PIE를 기본적으로 적용하므로, 모든 옵션을 제거하면 PIE가 적용된 바이너리로 컴파일된다.
  • PIE가 적용되면, main함수의 주소도 매 실행마다 바뀌게 된다.

4. PIE 우회

  • 코드 베이스 구하기
    • ASLR환경에서 PIE가 적용된 바이너리는 실행될 때마다 다른 주소에 적재하므로, 코드 영역의 가젯을 사용하거나 데이터 영역에 접근하려면 바이너리가 적재된 주소를 알아야 한다.
      해당 주소를 "PIE 베이스" or " 코드 베이스"라고 한다.
    • 코드 베이스를 구하려면, 코드 영역의 임의 주소를 읽고 그 주소의 오프셋을 빼야 한다.

  • Partial Overwrite
    • 코드 베이스가 구하기 어렵다면, 반환 주소의 일부 바이트만 덮는 공격을 고려해볼 수 있는데 
      이를 Partial Overwrite라고 한다. 
    • Off by One이라는 취약점으로 인해, Partial Overwrite가 발생한다.
    • 일반적으로 함수의 반환 주소는 호출 함수(Caller)의 내부를 가리키기 때문에,
      특정 함수의 호출 관계는 정적&동적 분석으로 쉽게 확인할 수 있으므로 공격자는 반환 주소를 예측할 수 있다.
    • ASLR의 특성상, 코드 영역의 주소도 하위 12bit 값은 항상 같다. 
      따라서, 사용하려는 코드 가젯의 주소가 반환 주소와 하위 한 바이트만 다르면, 이 값만 덮어서 원하는 코드를 실행시킬 수 있다.
      (단, 2byte이상 다른 주소로 실행 흐름을 옮기려면 ASLR로 섞이는 주소를 맞춰야 하므로 브로트 포싱을 해야함.)

5. 키워드 정리

  상대참조   어떤 값을 기준으로 다른 주소를 지정하는 방식이다.
  PIC   어떤 주소에 매핑되어도 실행 가능한 코드로, 절대 주소를 사용하지 않으며 일반적으로 rip을 기준으로
  한 상대 주소를 사용한다.
  PIE   어떤 주소에 매핑되어도 실행 가능한 실행 파일로, PIE의 코드는 모두 PIC이다.
  Partical Overwrite   어떤 값을 일부분만 덮는 공격 방법으로, PIE를 우회하기 위해 사용된다.

 

'Dreamhack > Lecture & Practice' 카테고리의 다른 글

[Lecture] OOB (Out of bounds)  (0) 2022.08.09
[Practice] Hook Overwrite  (0) 2022.07.14
[Lecture] RELRO (RELocation Read-Only)  (0) 2022.07.11
[Practice] ROP - GOT Overwrite  (0) 2022.07.02
[Practice] Return to Library  (0) 2022.07.01