최신버전 기준 작성
doubly linked list에서 청크를 연결 해제하는 과정인 unlink를 이용한 공격기법
⇒원하는 공간에 값을 쓰거나 leak할 수 있게 해주는 공격 기법이다.
<사용조건>
1. 힙 영역을 전역변수에서 관리 (힙 영역을 전역 변수같이 주소를 알고 있는 위치에 unlink 될 청크의 주소가 저장되어있어야 함)
2. 2개의 Allocated Chunk가 필요하며 한 개는 Fake Chunk를 생성할 수 있어야 함
3. 첫 번째 Chunk를 통해 두 번째 Chunk의 헤더를 조작할 수 있어야 함 (8바이트+null)
<익스 시나리오>
<원리>
우선 가장 기본 상태일때 힙 구조와 전역변수의 상황은 위와 같다.
그리고 fake chunk를 구성하고, 두 번째 청크의 메타데이터를 조작해준 모습이다.
위와 같이 구성해주는 이유는 다음과 같다.
prevsize = prev_size (p);
size += prevsize;
p = chunk_at_offset(p, -((long) prevsize));
+ if (__glibc_unlikely (chunksize(p) != prevsize))
+ malloc_printerr ("corrupted size vs. prev_size while consolidating");
(P->fd->bk != P || P->bk->fd != P) 이라는 보호기법을 우회할 수 있게 된다.
이제 두 번째 청크를 free하면 fake 청크와의 병합이 일어나고, 그 과정에서 fake chunk를 대상으로 unlink가 일어나게 된다.
unlink에는 아래와 같은 루틴이 존재한다.
static void
unlink_chunk (mstate av, mchunkptr p)
{
if (chunksize (p) != prev_size (next_chunk (p)))
malloc_printerr ("corrupted size vs. prev_size");
mchunkptr fd = p->fd;
mchunkptr bk = p->bk;
if (__builtin_expect (fd->bk != p || bk->fd != p, 0))
malloc_printerr ("corrupted double-linked list");
fd->bk = bk;
bk->fd = fd;
(위 코드에서 보이는 모든 보호기법은 이미 우회한 상태)
여기서 우리가 주목해야할 것은 마지막 두 줄이다.
일단 fd, bk는 각각 &chunk_ptr-0x18, &chunk_ptr-0x10를 의미한다.
먼저 fd->bk = bk;를 수행한다고 생각해보자.
fd→bk는 &chunk_ptr인데, 여기에 bk, 즉 &chunk_ptr-0x10를 대입한다.
따라서 chunk_ptr위치에 &chunk_ptr-0x10라는 값이 들어간 상태이다.
다음으로는 bk->fd = fd;를 수행할 차례이다.
bk→fd는 &chunk_ptr이고, 여기에 fd, 즉 &chunk_ptr-0x18를 대입한다.
따라서 최종적으로는 chunk_ptr이라는 전역변수의 위치에 &chunk_ptr-0x18주소값이 쓰이게 된다.
보통 익스 상황에서는 해당 전역변수를 대상으로 읽기, 쓰기 등이 가능한 상태일 것이므로 이제 &chunk_ptr-0x18으로의 접근이 가능하고, 이를 이용해 &chunk_ptr에 우리가 접근하고 싶은 주소 값을 쓰고, 또 이를 바탕으로 우리가 접근하고 싶은 주소에 원하는 값을 쓰면 된다. 그러면 aaw or aar이 가능하다.