House of Lore - Malloc Maleficarum 의 확장된 공격
이 PoC 는 glibc 의 smallbin corruption 에 대해서도 다룬다.
이것은 glibc malloc 에서 동작하는 체크를 우회하기 위한 업그레이드 버전이다.
ubuntu 14.04.4 - 32bit - glibc-2.23 환경에서 테스트 되었다.
가장 먼저 stack_buffer_1 과 stack_buffer_2 의 주소 값들을 초기화한다.
그리고, victim chunk 를 100byte 크기만큼 할당한다.
victim : 0x804c008
victim_chunk 포인터 변수에 victim - 2 의 주소를 넣는다.
stack_buffer_1 : 0xbffff6c0
stack_buffer_2 : 0xbffff6b4
stack 에 fake chunk 를 만들어준다. small bin corrupted 체크를 우회하기 위해 fwd pointer 를 victim_chunk 로 설정한다.
bk pointer 를 stack_buffer_2 로 설정한다. 그리고 fwd pointer 는 stack_buffer_1 을 가리켜야 한다.
이렇게 설정하게 되면 bck = victim->bk 체크를 우회할 수 있다.
free 함수 진행 중에 top chunk 와의 병합을 피하기 위해서 large chunk 를 하나 할당한다.
large chunk : 0x804c070
victim(0x804c008) 을 free 하고 그것은 unsorted bin 에 삽입될 것이다.
unsorted bin 안의 victim's fwd 와 bk 포인터들은 nil..
victim->fwd : 0xb7fc0450
victim->bk : 0xb7fc0450
이제 unsorted bin 또는 small bin 에 영향을 받지 않는 청크를 malloc 으로 할당하자.
이는 victim(0x804c008) 은 smallbin 의 맨 앞쪽에 삽입될 것이다.
p2 : 0x804c460
victim->fwd : 0xb7fc04b0
victim->bk : 0xb7fc04b0
victim chunk 는 정리되어지고 fwd 와 bk 포인터들은 업데이트 되었다.
이제 victim->bk pointer 를 stack_buffer_1 의 주소로 덮어써서 취약점을 에뮬레이팅 한다.
이제 처음 free 되었던 chunk 의 size 만큼 할당한다. 이는 덮어써진 victim chunk 를 return 하고 bin->bk 에 victim->bk 포인터가 들어간다.
결과적으로 bk 포인터를 조작하여 한번 더 malloc 을 했을 때 glibc 가 bin->bk 에 있는 chunk 를 리턴하게 된다.
The fwd pointer of stack_buffer_2 has changed after the last malloc to 0xb7fc04b0
p4 is 0xbffff6c8 and should be on the stack!
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
문서를 보면서 따라했지만 조금 헷갈려서 내가 이해한 내용 정리.. (잘못 이해했다면 알려주시길..)
1. small bin 크기의 chunk 할당. -> top chunk 와의 병합을 피하기 위해 large chunk 하나 더 할당.
2. bck->fd != victim 을 우회하기 위해서 stack 에 fake chunk 설정해야함.
3. 이 fake chunk 가 어떻게 bck->fd != victim 을 우회할 수 있는지 그림을 통해 보자.
현재 p3 = malloc(100); 을 하기 바로 직전의 메모리 모습이다.
우리가 이전에 free 했던 chunk 와 같은 크기의 small bin chunk 를 할당할 때,
bck = victim->bk;
if (__glibc_unlikely(bck->fd != victim)) {
위와 같은 검증 과정을 거치게 된다. 이 때 victim : 0x0804c000 이고, victim->bk 는 우리가 overwrite 했던 stack_buffer_1(0xbffff6c0) 의 주소이다. 즉 bck = 0xbffff6c0 이 되고, bck->fd == 0xbffff6c0 + 0x8 과 동일하다.
위의 그림에서 0xbffff6c0 + 0x8 의 값은 0x0804c000 이고, bck->fd == victim 은 같으므로 검증을 우회한다.
즉, stack_buffer_1[2] = victim_chunk 를 넣은 이유는 이러한 검증 과정 우회를 위한 것이다.
4. 정상적으로 위의 검증을 우회하면
...
bin->bk = bck;
...
malloc 이 정상적으로 수행이 되고 이전에 free 했던 영역을 반환 받는다. 그리고 bin->bk 에 0xbffff6c0 값이 들어가게 되고, 마지막 malloc 은 glibc malloc 을 속여 bin->bk 에 삽입된 위치의 chunk 를 반환해야 한다.
즉, void *p4 = malloc(100); 을 수행하면서 p4 :0xbffff6c8 을 반환받는다.
'system' 카테고리의 다른 글
[how2heap translation] house_of_einherjar.c (0) | 2017.06.26 |
---|---|
[how2heap translation] overlapping_chunk.c (0) | 2017.06.26 |
[how2heap translation] poison_null_byte.c (0) | 2017.06.19 |
Disabling Memory Protection on Linux (0) | 2017.05.05 |
[how2heap translation] house_of_force.c (0) | 2017.05.03 |