_int_malloc과 _int_free는 개발자의 실수, 악의적인 행위 등으로 힙이 정상적으로 동작하지 않는 것을 방지하기 위해 검증 코드가 존재한다.
검증 코드를 이해하고 있다면 익스플로잇을 할 때 이를 우회하여 공격할 수 있다.
_int_malloc과 _int_free 코드를 보면서 어떠한 검증이 있는지 확인해보자.
malloc(): memory corruption (fast)
#define fastbin_index(sz) \
((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
idx = fastbin_index (nb);
if (victim != 0)
{
if (__builtin_expect (fastbin_index (chunksize (victim)) != idx, 0))
{
errstr = "malloc(): memory corruption (fast)";
errout:
malloc_printerr (check_action, errstr, chunk2mem (victim), av);
return NULL;
}
}
_int_malloc에서 fastbin 크기의 힙이 할당될 때 호출되는 검증 코드이다.
할당하려는 fastbin의 크기와 할당될 영역의 크기를 구한 후 두 크기가 같은 bin에 속하는지 검증한다.
같은 bin에 속하는 크기라면 정상적으로 할당될 것이고 아니라면, malloc(): memory corruption (fast) 에러를 출력하고 비정상 종료를 한다.
m_error1.c
/*
Fastbin
gcc -o m_error1 m_error1.c
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
int main()
{
uint64_t *ptr, *ptr2;
ptr = malloc(0x20);
ptr2 = malloc(0x20);
free(ptr);
free(ptr2);
fprintf(stderr, "ptr2 fd: %p: %p\n", ptr2, ptr2);
*(uint64_t *)ptr2 = *(uint64_t *)ptr2 + 0x100;
fprintf(stderr, "ptr2 fd: %p: %p\n", ptr2, ptr2);
malloc(0x20);
malloc(0x20);
}
m_error1.c는 ptr2의 FD를 힙 청크가 존재하지 않는 영역의 주소로 조작해 검증 에러를 발생시키는 코드이다.
메모리의 상태는 다음과 같다.
해제된 ptr2의 FD를 올바르지 않은 0x602100 주소로 조작된 것을 확인할 수 있다.
0x062100 주소는 같은 bin의 크기를 가지고 있지 않기 때문에 에러가 발생한다.
malloc(): memory corruption
while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
{
bck = victim->bk;
if (__builtin_expect (victim->size <= 2 * SIZE_SZ, 0)
|| __builtin_expect (victim->size > av->system_mem, 0))
malloc_printerr (check_action, "malloc(): memory corruption",
chunk2mem (victim), av);
unsorted bin 힙의 BK가 main_arena의 unsorted bin의 주소인지 확인한다.
다른 값일 때, 할당하는 힙의 크기가 2 * SIZE_SZ 보다 작거나 av->system_mem 보다 크면 에러를 출력하고 비정상 종료를 한다.
m_error2.c
// gcc -o m_error2 m_error2.c
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
int main()
{
uint64_t *ptr, *ptr2, *ptr3;
ptr = malloc(0x100);
ptr2 = malloc(0x100);
free(ptr);
fprintf(stderr, "BK: %p\n", ptr[1]);
ptr[1] += 0x40;
fprintf(stderr, "Corrupted BK: %p\n", ptr[1]);
malloc(0x21000);
}
m_error2.c 코드는 바로 위에서 언급한 memory corruption 에러를 발생시키는 코드이다.
메모리의 모습이다.
unsorted bin의 BK를 다른 값으로 조작하고 av->system_mem 보다 큰 값을 할당하였다.
unsorted bin의 BK가 small bin의 주소를 가리키고 있기 때문에 에러가 발생한다.
'Pwnable > Techniques' 카테고리의 다른 글
Double Free Bug (0) | 2021.02.23 |
---|---|
_int_free (0) | 2021.02.22 |
ptmalloc2 allocator (0) | 2021.02.21 |
_IO_FILE vtable check (0) | 2021.02.06 |
_IO_FILE (0) | 2021.02.03 |
댓글