PIE 에 대해서 얘기 하기 전에 PIC 에 대한 이해가 선행될 필요가 있다.
What is PIC?
Position Independent Code : PIC
위치 독립 코드
이 자체로는 보호 기술은 아니나 PIE를 이해하기 위해서 필요하다.
PIC는 공유 라이브러리에 적용되는 옵션으로 공유 라이브러리 내 심볼들이 어느 주소에 로드되더라도 동작하는 코드이다.
주 기억 장치의 어딘가에 배치되어 절대 주소와 관계없이 모든 메모리 주소에서 수정없이 실행되는 기계 코드이다.
일반적으로 공유 라이브러리에서 사용되며, 동일한 라이브러리 코드는 각 프로그램의 메모리 영역에 로드 된다.
각 프로세서들은 PIC를 서로 다른 주소에서 실행할 수 있으며, 실행 시 재배치가 필요 없다.
공유 라이브러리를 만들 때 -fPIC 옵션을 이용하여 소스를 컴파일 한다.
Relocatable code
- Relocatable code 는 말 그대로 재배치가 필요한 코드를 의미한다.
- 재배치 과정은 동적 링커에 의해 코드에 생성된 label과 symbol의 주소를 수정하는 것이다.
PIC가 적용된 바이너리에는.rela.plt
섹션이 추가되어 있다.
PIC와 nostartfiles옵션이 적용된 바이너리에는 .rela.dyn
, .init
, .plt.got
, .fini
, .init_array
, .fini_array
, .jcr
, .got
, .data
, .bss
섹션이 없다.
Apply PIC
gcc -mcmodel=large -shared -o libNonPIC.so lazenca.c
gcc -fPIC -shared -o libPIC.so lazenca.c
gcc -fPIC -nostartfiles -shared -o libNoStartPIC.so lazenca.c
What is PIE
Position Independent Executable : PIE
위치 독립 실행가능?
PIE 는 위치 독립 코드로 이루어진 실행 가능한 바이너리이다.
몇몇 시스템들이 오직 PIC 실행 파일만 실행할 수 있다는 것 외에도 이것들이 사용되는 다른 이유들이 존재한다.
PIE 바이너리는 몇몇 보안 중심 리눅스 배포판들에서 Pax sk Exec Shield 가 주소공간 배치 난수화를 사용할 수 있도록 해서, 코드 영역의 실행가능한 코드가 존재하는지 알 수 없게 한다.
Apply PIE
gcc -fPIE -pie // Apply PIE
gcc -no-pie
Diff
test code
#include <stdio.h>
char *buf = "hello";
void func() {
printf("buf: %s\n", buf);
}
int main(){
func();
printf("buf's address: 0x%x\n", buf);
return 0;
}
일반 파일 gcc -no-pie -o noPIE PIE.c
PIE생성 gcc -fPIE -pie -o PIE PIE.c
noPIE
PIE
ASM
noPIE
PIE
PIE의 경우 noPIE와 다르게 매우 작은 주소에 코드들이 위치한다.
PIE가 적용되지 않은 바이너리의 경우 코드 영역의 값이 고정된 주소값이다.
PIE가 적용된 바이너리의 경우 코드 영역의 값이 고정된 주소 값이 아닌 offset 값이다.
해당 offset 값을 이용해 할당된 메모리 영역에 동적으로 위치 할 수 있다.
- 할당받은 메모리 영역 + .text 영역의 main함수 코드의 offset 값 = main 함수의 시작 주소
이 글은 옵시디언을 이용해서 작성되었습니다.
'TOOR' 카테고리의 다른 글
[TOOR] 15.1 Format String Bug (0) | 2023.10.02 |
---|---|
[TOOR] 14. RELRO (0) | 2023.09.29 |
[TOOR] 12.3. SROP (0) | 2023.09.24 |
[TOOR] 12.2 rop_2 write_up (0) | 2023.09.24 |
[TOOR] 12.1. ROP & ropasaurusrex write_up (0) | 2023.09.24 |