mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/binary-exploitation/libc-heap/use-after-free/first-fit.
This commit is contained in:
parent
cfabaeed41
commit
918ea5ca2f
@ -4,17 +4,17 @@
|
|||||||
|
|
||||||
## **First Fit**
|
## **First Fit**
|
||||||
|
|
||||||
프로그램에서 glibc를 사용하여 메모리를 해제할 때, 다양한 "빈"이 메모리 청크를 관리하는 데 사용됩니다. 다음은 두 가지 일반적인 시나리오에 대한 간단한 설명입니다: 정렬되지 않은 빈과 패스트 빈.
|
glibc를 사용하여 프로그램에서 메모리를 해제할 때, 서로 다른 "빈"이 메모리 청크를 관리하는 데 사용됩니다. 다음은 두 가지 일반적인 시나리오에 대한 간단한 설명입니다: 정렬되지 않은 빈과 패스트 빈.
|
||||||
|
|
||||||
### Unsorted Bins
|
### Unsorted Bins
|
||||||
|
|
||||||
패스트 청크가 아닌 메모리 청크를 해제하면, 그것은 정렬되지 않은 빈으로 이동합니다. 이 빈은 새로 해제된 청크가 앞쪽(“헤드”)에 추가되는 목록처럼 작동합니다. 새로운 메모리 청크를 요청할 때, 할당자는 정렬되지 않은 빈의 뒤쪽(“테일”)에서 충분히 큰 청크를 찾습니다. 정렬되지 않은 빈의 청크가 필요한 것보다 크면, 그것은 나뉘어지고 앞부분이 반환되며 나머지 부분은 빈에 남아 있습니다.
|
패스트 청크가 아닌 메모리 청크를 해제하면, 그것은 정렬되지 않은 빈으로 이동합니다. 이 빈은 새로 해제된 청크가 앞쪽(“헤드”)에 추가되는 목록처럼 작동합니다. 새로운 메모리 청크를 요청할 때, 할당자는 정렬되지 않은 빈의 뒤쪽(“테일”)에서 충분히 큰 청크를 찾습니다. 정렬되지 않은 빈의 청크가 필요한 것보다 크면, 그것은 분할되어 앞부분이 반환되고 나머지 부분은 빈에 남아 있습니다.
|
||||||
|
|
||||||
예시:
|
예시:
|
||||||
|
|
||||||
- 300 바이트(`a`)를 할당한 다음, 250 바이트(`b`)를 할당하고, `a`를 해제한 후 다시 250 바이트(`c`)를 요청합니다.
|
- 300 바이트(`a`)를 할당한 다음, 250 바이트(`b`)를 할당하고, `a`를 해제한 후 다시 250 바이트(`c`)를 요청합니다.
|
||||||
- `a`를 해제하면, 그것은 정렬되지 않은 빈으로 이동합니다.
|
- `a`를 해제하면, 그것은 정렬되지 않은 빈으로 이동합니다.
|
||||||
- 그 후 250 바이트를 다시 요청하면, 할당자는 테일에서 `a`를 찾아 그것을 나누고 요청에 맞는 부분을 반환하며 나머지는 빈에 남깁니다.
|
- 그 후 다시 250 바이트를 요청하면, 할당자는 테일에서 `a`를 찾아 분할하고, 요청에 맞는 부분을 반환하며 나머지는 빈에 남깁니다.
|
||||||
- `c`는 이전의 `a`를 가리키며 `a`의 내용으로 채워집니다.
|
- `c`는 이전의 `a`를 가리키며 `a`의 내용으로 채워집니다.
|
||||||
```c
|
```c
|
||||||
char *a = malloc(300);
|
char *a = malloc(300);
|
||||||
@ -24,7 +24,7 @@ char *c = malloc(250);
|
|||||||
```
|
```
|
||||||
### Fastbins
|
### Fastbins
|
||||||
|
|
||||||
Fastbins은 작은 메모리 청크에 사용됩니다. 정렬되지 않은 빈과 달리, fastbins은 새로운 청크를 헤드에 추가하여 후입선출(LIFO) 동작을 생성합니다. 작은 메모리 청크를 요청하면, 할당자는 fastbin의 헤드에서 가져옵니다.
|
Fastbins은 작은 메모리 청크에 사용됩니다. 정렬되지 않은 빈과 달리, fastbins은 새로운 청크를 머리에 추가하여 후입선출(LIFO) 동작을 생성합니다. 작은 메모리 청크를 요청하면, 할당자는 fastbin의 머리에서 가져옵니다.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```c
|
```c
|
||||||
@ -55,12 +55,12 @@ glibc 2.26부터 각 스레드는 **tcache**를 유지하며, 이는 정렬되
|
|||||||
for(int i = 0; i < 7; i++) pool[i] = malloc(0x100);
|
for(int i = 0; i < 7; i++) pool[i] = malloc(0x100);
|
||||||
for(int i = 0; i < 7; i++) free(pool[i]);
|
for(int i = 0; i < 7; i++) free(pool[i]);
|
||||||
```
|
```
|
||||||
tcache가 소진되면, 이후의 free는 정렬되지 않은 빈으로 가고 고전적인 first-fit 동작(꼬리 검색, 머리 삽입)이 다시 발생할 수 있습니다.
|
tcache가 소진되면, 이후의 free는 unsorted bin으로 가고 고전적인 first-fit 동작(꼬리 검색, 머리 삽입)이 다시 발생할 수 있습니다.
|
||||||
|
|
||||||
---
|
---
|
||||||
### 🚩 first-fit을 이용한 겹치는 청크 UAF 만들기
|
### 🚩 first-fit을 이용한 겹치는 청크 UAF 만들기
|
||||||
|
|
||||||
아래의 조각(테스트는 glibc 2.38에서 수행됨)은 정렬되지 않은 빈의 분할기를 악용하여 2개의 **겹치는 포인터**를 생성하는 방법을 보여줍니다. 이는 단일 free를 write-after-free로 변환하는 강력한 원시 기능입니다.
|
아래의 조각(테스트는 glibc 2.38에서 수행됨)은 unsorted bin의 분할기를 악용하여 2개의 **겹치는 포인터**를 생성하는 방법을 보여줍니다. 이는 단일 free를 write-after-free로 변환하는 강력한 원시 기능입니다.
|
||||||
```c
|
```c
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -98,15 +98,13 @@ Exploitation recipe (common in recent CTFs):
|
|||||||
4. **다시 할당하기** – 남은 부분이 기존 사용 중인 청크와 겹침 → UAF.
|
4. **다시 할당하기** – 남은 부분이 기존 사용 중인 청크와 겹침 → UAF.
|
||||||
5. 민감한 필드(함수 포인터, FILE vtable 등)를 덮어쓰기.
|
5. 민감한 필드(함수 포인터, FILE vtable 등)를 덮어쓰기.
|
||||||
|
|
||||||
실용적인 응용 프로그램은 2024 HITCON Quals *Setjmp* 챌린지에서 이 정확한 프리미티브가 UAF에서 `__free_hook`의 완전한 제어로 피벗하는 데 사용되는 것을 찾을 수 있습니다.{{#ref}}
|
실용적인 응용 프로그램은 2024 HITCON Quals *Setjmp* 챌린지에서 이 정확한 프리미티브가 UAF에서 `__free_hook`의 전체 제어로 피벗하는 데 사용되는 것을 찾을 수 있습니다.
|
||||||
../../../../references/2024_setjmp_firstfit.md
|
|
||||||
{{#endref}}
|
|
||||||
|
|
||||||
---
|
---
|
||||||
### 🛡️ 완화 및 강화
|
### 🛡️ 완화 및 강화
|
||||||
|
|
||||||
* **안전한 링크(glibc ≥ 2.32)**는 단일 연결된 *tcache*/**fastbin** 목록만 보호합니다. 정렬되지 않은/작은/큰 빈은 여전히 원시 포인터를 저장하므로, 힙 누수를 얻을 수 있다면 첫 번째 적합 기반의 겹침이 여전히 유효합니다.
|
* **안전한 링크(glibc ≥ 2.32)**는 단일 연결된 *tcache*/**fastbin** 목록만 보호합니다. 정렬되지 않은/작은/큰 빈은 여전히 원시 포인터를 저장하므로, 힙 누수를 얻을 수 있다면 첫 번째 적합 기반의 겹침이 여전히 유효합니다.
|
||||||
* **힙 포인터 암호화 및 MTE** (ARM64)는 아직 x86-64 glibc에 영향을 미치지 않지만, `GLIBC_TUNABLES=glibc.malloc.check=3`와 같은 배포판 강화 플래그는 일관되지 않은 메타데이터에서 중단되며 단순한 PoC를 깨뜨릴 수 있습니다.
|
* **힙 포인터 암호화 및 MTE** (ARM64)는 아직 x86-64 glibc에 영향을 미치지 않지만, `GLIBC_TUNABLES=glibc.malloc.check=3`와 같은 배포 강화 플래그는 일관성 없는 메타데이터에서 중단되며 단순한 PoC를 깨뜨릴 수 있습니다.
|
||||||
* **해제 시 tcache 채우기** (2024년 glibc 2.41에 제안됨)는 정렬되지 않은 사용을 더욱 줄일 것입니다; 일반적인 익스플로잇을 개발할 때 향후 릴리스를 모니터링하세요.
|
* **해제 시 tcache 채우기** (2024년 glibc 2.41에 제안됨)는 정렬되지 않은 사용을 더욱 줄일 것입니다; 일반적인 익스플로잇을 개발할 때 향후 릴리스를 모니터링하세요.
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -116,13 +114,13 @@ Exploitation recipe (common in recent CTFs):
|
|||||||
- [**https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/**](https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/)
|
- [**https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/**](https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/)
|
||||||
- ARM64. Use after free: 사용자 객체를 생성하고, 해제한 후, 해제된 청크를 가져오는 객체를 생성하여 그에 쓸 수 있게 하여, **이전의 user->password 위치를 덮어쓰기**. 사용자를 재사용하여 **비밀번호 확인을 우회하기**
|
- ARM64. Use after free: 사용자 객체를 생성하고, 해제한 후, 해제된 청크를 가져오는 객체를 생성하여 그에 쓸 수 있게 하여, **이전의 user->password 위치를 덮어쓰기**. 사용자를 재사용하여 **비밀번호 확인을 우회하기**
|
||||||
- [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example)
|
- [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example)
|
||||||
- 프로그램은 노트를 생성할 수 있습니다. 노트는 malloc(8)에서 노트 정보를 가지고 있으며(호출할 수 있는 함수에 대한 포인터 포함) 노트 내용을 가진 다른 malloc(<size>)에 대한 포인터를 가집니다.
|
- 프로그램은 노트를 생성할 수 있습니다. 노트는 malloc(8)에서 노트 정보를 가지고 있으며(호출할 수 있는 함수에 대한 포인터 포함) 다른 malloc(<size>)에 노트의 내용을 가리키는 포인터를 가집니다.
|
||||||
- 공격은 노트 정보 크기보다 더 큰 malloc 내용을 가진 2개의 노트(note0 및 note1)를 생성한 다음, 이를 해제하여 빠른 빈(또는 tcache)으로 들어가게 하는 것입니다.
|
- 공격은 노트 정보 크기보다 더 큰 malloc 내용을 가진 2개의 노트(note0 및 note1)를 생성한 다음, 이를 해제하여 빠른 빈(또는 tcache)으로 들어가게 하는 것입니다.
|
||||||
- 그런 다음, 내용 크기가 8인 또 다른 노트(note2)를 생성합니다. 내용은 note1에 있을 것이며, 청크가 재사용되므로 함수 포인터를 win 함수로 가리키도록 수정할 수 있으며, 그런 다음 note1을 Use-After-Free하여 새로운 함수 포인터를 호출합니다.
|
- 그런 다음, 내용 크기가 8인 또 다른 노트(note2)를 생성합니다. 내용은 note1에 있을 것이며, 청크가 재사용되므로 함수 포인터를 win 함수로 가리키도록 수정할 수 있고, 그런 다음 Use-After-Free를 통해 note1을 호출하여 새로운 함수 포인터를 사용할 수 있습니다.
|
||||||
- [**https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html)
|
- [**https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html)
|
||||||
- 메모리를 할당하고 원하는 값을 쓰고, 해제한 후, 재할당할 수 있으며, 이전 데이터가 여전히 존재하므로 청크의 새로운 예상 구조에 따라 처리되어 값을 설정하거나 플래그를 얻을 수 있습니다.
|
- 메모리를 할당하고 원하는 값을 쓰고, 해제한 후, 재할당할 수 있으며, 이전 데이터가 여전히 존재하므로 청크의 새로운 예상 구조에 따라 처리되어 값을 설정하거나 플래그를 얻을 수 있습니다.
|
||||||
- [**https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html)
|
- [**https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html)
|
||||||
- 이 경우, 특정 청크에 4를 써야 하며, 이는 할당된 첫 번째 청크입니다(모든 청크를 강제로 해제한 후에도). 각 새로 할당된 청크의 배열 인덱스 번호가 저장됩니다. 그런 다음 4개의 청크(+ 처음 할당된 청크)를 할당하고, 마지막 청크에는 4가 들어 있으며, 이를 해제하고 첫 번째 청크의 재할당을 강제로 하여 마지막으로 해제된 청크를 사용하게 됩니다. 이 청크에는 4가 들어 있습니다.
|
- 이 경우 특정 청크에 4를 써야 하며, 이는 할당된 첫 번째 청크입니다(모든 청크를 강제로 해제한 후에도). 각 새로 할당된 청크의 배열 인덱스 번호가 저장됩니다. 그런 다음 4개의 청크(+ 처음 할당된 청크)를 할당하고, 마지막 청크에는 4가 들어 있으며, 이를 해제하고 첫 번째 청크의 재할당을 강제로 하여 마지막으로 해제된 청크를 사용하게 됩니다. 이 청크에는 4가 들어 있습니다.
|
||||||
- 2024 HITCON Quals Setjmp write-up (Quarkslab) – 실용적인 first-fit / 정렬되지 않은 분할 겹침 공격: <https://ctftime.org/writeup/39355>
|
- 2024 HITCON Quals Setjmp write-up (Quarkslab) – 실용적인 first-fit / 정렬되지 않은 분할 겹침 공격: <https://ctftime.org/writeup/39355>
|
||||||
- Angstrom CTF 2024 *heapify* write-up – 정렬되지 않은 빈 분할을 악용하여 libc를 누출하고 겹침을 얻기: <https://hackmd.io/@aneii11/H1S2snV40>
|
- Angstrom CTF 2024 *heapify* write-up – 정렬되지 않은 빈 분할을 악용하여 libc를 누출하고 겹침을 얻기: <https://hackmd.io/@aneii11/H1S2snV40>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user