본문 바로가기

Pwnable/개념

[Pwnable] Dreamhack STAGE 8

https://dreamhack.io/lecture/roadmaps/2

 

System Hacking

시스템 해킹을 공부하기 위한 로드맵입니다.

dreamhack.io


[ RELocation Read-Only(RELRO) ]

: 프로세스의 데이터 세그먼트를 보호

: 쓰기 권한이 불필요한 데이터 세그먼트에 쓰기 권한을 제거

  1. Partial RELRO: RELRO를 부분적으로 적용

 → 2. Full RELRO: RELRO를 가장 넓은 영역에 적용

 

 

[ Partial RELRO ]

 gcc는 Full RELRO를 기본 적용하며, PIE를 해제하면 Partial RELRO를 적용함

Ex) gcc -o prelro relro.c -no-pie fno-PIE

 

* “.got”와 “.got.plt”

: partial relro가 적용된 바이너리는 got와 관련된 섹션이 두 개가 존재하는데

 전역 변수 중에서 실행되는 시점에 바인딩(now binding)되는 변수는 .got에 위치함.

      바이너리가 실행될 때는 이미 바인딩이 완료되어있으므로 이 영역에 쓰기 권한을 부여하지는 않음

 반면 실행 중에 바인딩(lazy binding)되는 변수는 .got.plt에 위치함. 이 영역은 실행 중에 값이 쓰여져야 하므로

      쓰기 권한이 부여되며, partial relro가 적용된 바이너리에서 대부분 함수들의 got 엔트리는 .got.plt에 저장됨

 

 

[ Full RELRO ]

 : got에 쓰기 권한 제거, 따라서 data와 bss에만 쓰기 권한이 있음

 : full relro가 적용되면 라이브러리 함수들의 주소가 바이너리의 로딩 시점에 모두 바인딩됨

 : 따라서 got에는 쓰기 권한이 부여되지 않음

 

 

[ RELRO 기법 우회 ]

 1. Partial RELRO

- .init_array와 .fini_array에 대한 쓰기 권한이 제거되어 두 영역을 덮어쓰는 공격을 수행하기 어려움

- 그러나 .got.plt 영역에 대한 쓰기 권한이 존재하므로 GOT overwrite 공격 가능

 

 2. Full RELRO

- .init_array, .fini_array 뿐만 아니라 .got 영역에도 쓰기 권한이 제거

  → 라이브러리에 위치한 hook을 통해 공격 가능

   라이브러리 함수의 대표적인 hook : malloc hook, free hook

     - 원래 이 함수 포인터는 동적 메모리의 할당과 해제 과정에서 발생하는 버그를 쉽게 디버깅하기 위해 만들어짐

 

 

 * Hook Overwrite 공격 (malloc 함수 코드)

1. 시작 부분에서 __malloc_hook이 존재하는지 검사

2. 존재하면 이를 호출

3. __malloc_hook은 libc.so에서 쓰기 가능한 영역에 위치하므로, 공격자는 libc가 매핑된 주소를 알 때,

      이 변수를 조작하고 malloc을 호출하여 실행 흐름을 조작할 수 있음

 

 

[ Position-Independent Executable(PIE) ]

 : ASLR이 코드 영역에도 적용되게 해주는 기술

 : 보안성 향상을 위해 도입된 것이 아니라서 엄밀하게는 보호 기법은 아님

 

 

[ Position-Independent Code(PIC) ]

 : 재배치(RELOCATION)가 가능하도록 설계되어 있는 코드

   즉, 메모리의 어느 주소에 적재되어도 코드의 의미가 훼손되지 않는 코드

 

 

[ PIC 코드 분석 ]

pic.c 코드이다.

 

Pic가 적용된 바이너리와 아닌 바이너리의 차이를 알아보기 위해 각각 pic와 no_pic로 컴파일하였다.

두 바이너리는 printf에서 차이를 보인다고 한다.

 


먼저 no_pic의 main을 보면 0x4005a1이라는 절대 주소로 문자열을 참조하고 있다.

반면 pic의 main을 보면 문자열의 주소를 [rip+0xa2]로 참조하고 있다.

 

결론적으로 바이너리가 매핑되는 주소가 바뀌면 no_pic 코드의 0x4005a1에 있던 데이터도 함께 이동되어 제대로 실행되지 못하지만, pic의 코드는 rip를 기준으로 데이터를 상대 참조(relative addressing)하기 때문에 바이너리가 무작위 주소에 매핑되어도 제대로 실행될 수 있다.

 

[ PIE ]

 : Position-Independent Executable은 무작위 주소에 매핑되어도 실행 가능한 실행 파일을 뜻한다.

 : ASLR이 도입된 후, 실행 파일도 무작위 주소에 매핑될 수 있게 하고 싶었으나, 실행 파일의 형식을 변경하면 호환성

   문제가 발생하기 때문에, 원래 재배치가 가능했던 공유 오브젝트를 실행 파일로 사용하기로 함

 : 리눅스의 기본 실행 파일 중 하나인 /bin/ls는 공유 오브젝트 형식을 띠고 있음

 

 PIE on ASLR

   : PIE는 재배치가 가능하므로, ASLR이 적용된 시스템에서는 실행 파일도 무작위 주소에 적재됨

   : PIE가 적용되면 main 함수의 주소가 매 실행마다 바뀜

 

 우회

1) 코드 베이스 구하기

     - ASLR 환경에서 PIE가 적용된 바이너리는 실행될 때마다 다른 주소에 적재됨.

     - 이러한 이유로 코드 영역의 가젯을 사용하거나, 데이터 영역에 접근하려면 바이너리가 적재된 주소를 알아야 함

     - 이 주소를 PIE 베이스, 또는 코드 베이스라고 부름

     - 코드 베이스를 구하려면 라이브러리의 베이스 주소를 구할 때처럼 코드 영역의 임의 주소를 읽고, 그 주소에서

        오프셋을 빼야 함

2) Partial Overwrite

   - 코드 베이스를 구하기 어렵다면 반환 주소의 일부 바이트만 덮는 공격을 고려할 수 있음

   - 일반적으로 함수의 반환 주소는 호출 함수(caller)의 내부를 가리키는데,  특정 함수의 호출 관계는 정적 분석 또는

     동적 분석으로 쉽게 확인할 수 있으므로, 공격자는 반환 주소를 예측할 수 있음

     - ASLR의 특성상, 코드 영역의 주소도 하위 12비트 값은 항상 같다.

     - 따라서 사용하려는 코드 가젯의 주소가 반환 주소와 하위 한 바이트만 다르다면, 이 값만 덮어서 원하는 코드 실행

         가능

       - 그러나 두 바이트 이상이 다른 주소로 실행 흐름을 옮기고자 한다면, ASLR로 뒤섞이는 주소를 맞춰야하므로

           브루트포싱이 필요함

 

 

[ Hook Overwrite 실습 ]

 : Hooking(후킹): 운영체제가 어떤 코드를 실행하려 할 때, 이를 낚아채어 다른 코드가 실행되게 하는 것

    함수에 훅을 심어 함수 호출 모니터링하기 / 함수에 기능 추가 / 실행 흐름 변조

 - malloc과 free에 훅 설치: 소프트웨어에서 할당/해제하는 메모리 모니터링 가능

 - 더 응용하면 모든 함수의 도입 부분에 모니터링 함수를 훅으로 설치하여 어떤 소프트웨어가 실행 중에

호출하는 함수를 모두 추적(tracing)할 수 있음

 - Full RELRO가 적용되더라도 libc의 데이터 영역에는 쓰기가 가능하므로, Full RELRO를 우회할 수 있음

 

 

* 메모리 함수 훅_ malloc, free, realloc hook

 - C언어에서 메모리의 동적 할당과 해제를 담당하는 함수 : malloc, free, realloc

     각 함수는 libc.so에 구현되어 있음

 

libc에는 이 함수들의 디버깅 편의를 위해 훅 변수가 저장되어 있는데,

예를 들어, malloc 함수는 __malloc_hook 변수의 값이 NULL이 아닌지 검사하고, 아니라면 malloc을 수행하기 전에 __malloc_hook이 가리키는 함수를 먼저 실행한다.

이때, malloc의 인자는 훅 함수에 전달된다.

Free와 realloc도 같은 방식으로 각각 __free_hook, __realloc_hook이라는 훅 변수를 사용함

 

 훅의 위치와 권한

 : __malloc_hook, __free_hook, __realloc_hook도 마찬가지로 libc.so에 정의되어 있음

 

위의 사진을 보면

변수들의 오프셋은 각각 0x3ed8e8, 0x3ebc30, 0x3ebc28인데, 섹션 헤더 정보를 참조하면 libc.so의 bss 섹션에 포함됨을 알 수 있다.

 


또한 bss 섹션은 쓰기가 가능하므로 해당 변수들의 값을 조작될 수 있다.

 

'Pwnable > 개념' 카테고리의 다른 글

[Pwnable] Dreamhack STAGE 10  (0) 2022.08.26
[Pwnable] Dreamhack STAGE 8  (0) 2022.08.26
[Pwnable] Dreamhack STAGE 7  (0) 2022.08.26
[Pwnable] Dreamhack STAGE 6  (0) 2022.08.25
[Pwnable] Dreamhack STAGE 5  (0) 2022.08.25