Linux 메모리 보호기법 정리(bpsecblog)
1) ASLR(Address Space Layout Randomization)
=스택, 힙, 라이브러리 등의 주소를 랜덤으로
/proc/self/maps로 확인
해제:
echo 0 > /proc/sys/kernel/randomize_va_space
randomize_va_space=0 : ASLR 해제
randomize_va_space=1 : 스택 & 라이브러리
randomize_va_space=2 : 스택 & 라이브러리 & 힙
특정 바이너리에서만 비활성화
setarch `uname -m` -R ./yourProgram
ldd로도 확인가능, 라이브러리 기본주소 임의로 지정
-->System 함수노출을 위한 libc.so.6 기본주소 + offset 연산,
libc.so.6을 얻기위한 __libc_start_main 주소 노출
_start함수에서 __libc_start_main을 호출하기에 got에 함수 주소가 올라감을 이용
2) DEP(Data Execution Prevention), NX(W^X)
=데이터 영역의 실행 방지
DEP 제거 = 스택, 힙 실행 허용 = -z execstack 옵션으로 gcc 컴파일 (gcc -z execstack ~~.c -o ~~)
-->RTL, ROP
3) ASCII-Armor
=공유라이브러리 영역의 상위 주소에 0x00을 포함시킴
RTL(Return to library)방어
libc의 특정 함수로 뛰는 것 방어
-->
4) Stack Canary
=로컬 변수와 SFP(Saved Frame Pointer)사이에 특정한 값을 추가 후 확인
프롤로그 이후(프롤로그에서 SFP저장), gs: Thread Control Block (which stores Thread Local Storage, aka TLS)영역에서 값을 가져와서 저장후 마지막에 확인, 확인시 다시 gs와 비교후 다르면 __stack_chk_fail@plt로 점프
1. Terminator canaries
2. Random canary
3. Null canary
-->fork 이용한 4바이트 한자리씩 예측
5) RELRO
GOT Overwrite 공격
=다른 함수의 주소로 덮어씌워서 임의의 함수 실행
Lazy Binding: Dynamic Linking 방식으로 컴파일 시에 공유 라이브러리 내의 함수 주소를 GOT(Global Offset Table)을 통해 동적으로 알아온다.
Dynamic link: 공유 라이브러리를 하나의 메모리 공간에 매핑하고 여러 프로그램이 사용
그래서 실제 코드가 없고 PLT, GOT를 사용 https://looka149.tistory.com/entry/PLTGOT
함수실행 -> PLT -> GOT값으로 jmp (처음실행시에는 PLT+6으로 이동해서 실제 주소를 가져옴 // 두번째부터는 실제 주소)
이때 GOT의 값을 임의의 함수의 주소로 덮어씌우면 끝
PLT (Procedure Linkage Table)
GOT (Global Offset Table)
이를 막기위한 것으로
출처: https://bpsecblog.wordpress.com/2016/05/18/memory_protect_linux_2/
읽기 전용 섹션으로 만들어서 수정을 방지
섹션들의 정보는 objdump -h 바이너리명으로 확인가능
Dafult : .ctors, .dtors, .jcr, .dynamic, .got -> 수정가능
Partial : .ctors, .dtors, .jcr, .dynamic -> 읽기전용 .got -> 수정가능
Full : .ctors, .dtors, .jcr, .dynamic, .got -> 읽기전용
그러나 속도때문에 Partial을 많이 쓴다.
6) PIC(Position Independent Code)
정적 라이브러리(Static Library)는 오브젝트 파일(.o)을 모아서 ar rv로 묶은 라이브러리 파일(.a)
gcc -c def.c
ar rv lib_static_def.a def.o
def.c에서 정의한 함수를 call.c에서 호출 후
gcc call.c -o call lib_static_def.a 하면 정적으로 포함하여 컴파일
공유 라이브러리는 실행시에 공유 라이브러리를 참조하도록 함
gcc -c -fPIC def.c
gcc -shared -o lib_dynamic_def.so def.o
= gcc -shared -fPIC -o lib_dynamic_def.so def.c
$ vi /etc/ld.so.conf 을 보면
include /etc/ld.so.conf.d/*.conf 라고 적혀있다. == /etc/ld.so.conf.d/ 디렉토리 안에 [아무말].conf로 파일을 만들고 안에 lib_dynamic_def.so의 폴더경로를 적음
후에 ldconfig 명령어 입력
이렇게 되면 다른 모든 실행파일 내에서 사용 가능
def.c에서 정의한 함수를 사용하는 call.c라는 파일을 만든 후
gcc call.c -o call -lmy -L. 을 이용하여 공유라이브러리 링킹
(-l 옵션은 앞의 lib과 뒤의 a이나 so를 떼고 진행 libaaa.a -> -laaa, libmy.so -> -lmy)
(-L 옵션은 라이브러리의 위치를 지정해줌)
(리눅스에선 기본적으로 /lib, /usr/lib, /usr/local/lib 만 검색)
ldd(List Dynamic Dependencies)을 이용하여 확인 가능
gcc -shared -o A.so A.c
gcc -shared -fPIC -o B.so B.c
두개가 있을 경우 PIC 유무의 차이인데 이는 재배치의 차이로 이어진다.
readelf -d 옵션을 통해 TEXTREL과 RELCOUNT를 살펴보면 둘 다 기본적으로 gcc가 기본적으로 사용하는 시작 파일의 코드로인해 RELCOUNT가 3이고(-nostartfiles로 없앨 수 있음) 재배치 횟수만큼 A.so와 B.so가 차이가 난다. noPIC이 그만큼 더 많다.
noPIC의 경우 내부의 printf 함수를 .text섹션에서 호출
PIC의 경우 plt을 거쳐서 printf를 호출한다.
Relocatable code는 재배치가 필요함. 따라서 .text영역에 이를 표시해 두고 로더가 이후에 이 영역의 값을 변경함
이는 곧 다른 위치로 로드된 동일한 코드는 이를 사용할 수 없다는 것이므로 공유 라이브러리의 개념과 맞지 않아서
PC-relative 방식의 link time에 계산된 오프셋만을 이용하는 PIC를 사용함.
7) PIE(Position Independent Executable)
6은 라이브러리를 위한 것
PIE는 전체가 위치 독립 코드로 이루어진 실행 가능한 바이너리
6처럼 so를 만들고 연결해주고
so안의 함수를 call하는 test.c라는 파일을 만들고, 전역 *buf = "hello"의 위치를 호출하는 코드 address.c를 만들고.
gcc -o test_no_PIE test.c
gcc -fPIE -pie test_yes_PIE test.c
gcc -o address_no_PIE address.c
gcc -fPIE -pie address_yes_PIE address.c 를 통해 두가지 버전을 만들면
PIE버전의 주소는 계속 변한다. --> PIE는 위치 독립 실행파일로, 실행할 때마다 매핑되는 주소가 어디든지에 상관없이 실행가능 -> 매번다름
또한 file 명령어를 통해 안을 보면
no_PIE는 executable로
PIE는 shared object로 나온다.
일반 실행 파일은 puts를 plt를 이용하여 호출한다. 이때 주소는 고정되어있다. 뿐만 아니라 사용자 함수도 고정되어 있다.
PIE 파일은 puts@plt를 call 하는 것은 같지만 주소가 매우 다르다.
뿐만아니라 __x86.get_pc_thunk.bx와 같은 함수를 볼 수 있다. 이는 다음 실행할 EIP를 EBX로 옮기는 명령어다.
이를 통해 상대적으로 주소를 계산한다. 어떻게? ebx에 X를 더하는 명령어를 실행함으로써 .got.plt 섹션의 주소를 가르키도록 만든다.
X = “got영역의 주소(오프셋)” – “add 인스트럭션의 주소(오프셋)” 이다. 다 상대주소(오프셋)기때문에 가능하다!
더 자세한설명은 블로그에 있다.
또한 -fPIC -pie 의 의미는 각각 컴파일러, 링커를 위한 옵션이다.
출처:
https://hackability.kr/entry/%EC%8B%9C%EC%8A%A4%ED%85%9C-%ED%95%B4%ED%82%B9-101?category=577654
https://bpsecblog.wordpress.com/memory_protect_linux/