상세 컨텐츠

본문 제목

[Heap Exploitation] unsafe unlink

SYSTEM HACKING/Exploit Tech

by koharin 2020. 1. 5. 15:59

본문

728x90
반응형

how2heap의 unsafe_unlink.c와 Lazenca 문서를 보고 공부했다.

 

Conditions

 

1. 공격자에 의해 생성된 heap 영역이 전역 변수와 같이 주소를 예상할 수 있는 영역에서 관리되어야 한다.

2. 공격자에 의해 크기가 0x80 이상의 heap 영역이 할당될 수 있어야 한다.

 

Exploit plan

 

1. global 변수 chunk0_ptr 선언

 

이 포인터를 원하는 메모리 주소로 옮기고 이 포인터를 이용해 값을 적는 것이 목표

 

2. smallChunk 이상 크기의 chunk 2개 할당. 

- 0x80 크기의 청크 2개 할당 : 첫 번째 chunk는 전역변수에 저장한다.

 

실제 chunk 크기는 헤더(0x10) 포함 0x90

 

3. 첫 번째 chunk 안에 fakeChunk 1개 만든다.

 

unlink 취약점을 이용해 unlink 매크로를 호출해서 fakeChunk와 free된 chunk1을 병합하기 위해 fakeChunk를 만든다.

 

fakeChunk는 &chunk0_ptr + 0x10 (chunk0_ptr[0]) 에 만든다. 

chunk 구조는

chunk0_ptr[0] : 이전 청크가 free됐다면 PREV_CHUNK_SIZE, 이전 청크 사용 중이면 사용자 data

chunk0_ptr[1] : chunk_size (현재 청크 크기)

chunk0_ptr[2] : free 됐다면 fd, 아니면 사용자 data

chunk0_ptr[3] : free 됐다면 bk, 아니면 사용자 data

 

1) free 된 것처럼 보이는 fakeChunk를 만들어야 하므로 fd와 bk를 설정해야 한다.

fd = &chunk0_ptr - 0x18, bk = &chunk0_ptr - 0x10

 

unlink P->fd->bk != P || P->bk->fd != P 조건 우회 가능:

fd = &전역변수 - 0x18, bk = &전역변수 - 0x10

으로 설정 시, P->fd->bk = (&전역변수 - 0x18) + 0x18 으로 &전역변수가 되므로 P와 같다.

또 P->bk->fd = (&전역변수 - 0x10) + 0x10으로 &전역변수가 되서 이 또한 P와 같아서 위의 조건을 우회할 수 있다.

 

2) size 검증 우회 : P->size == next_chunk->prev_size 이어야 함

fakeChunk 내 현재 chunk size 가지는 곳은 chunk0_ptr[1]이고, 이 값과 next_chunk(여기서 chunk1_ptr, 현재 chunk 주소 + size) 값이 같아야 한다.

 

 

&chunk0_ptr[1] = sizeof(size_t) (size_t = 8)

 

으로 하면, &chunk+0x8은 chunk0_ptr[1]이고, next_chunk->prev_size와 같으므로 우회 가능

 

4. 2번째 heap 영역의 header 값 변경 -> 포인터로 주소에 접근

첫 번째 청크가 해제된 것처럼 prev_inuse 비트를 없앤다. => size = 0x91 - 0x1 = 0x90 

chunk1_hdr[1] &= ~1;

 

fake_chunk가 인접 청크처럼 보이도록 prev_size 수정 => prev_size = 0x90 - 0x10 = 0x80

chunk1_hdr[0] = 0x80;

 

 

병합(consolidate) 시 이전 청크 주소 찾기 위해 이 prev_size 정보 이용해서 계산하는데 (현재 청크 주소 + 이전 청크 주소) 값을 unlink 매크로 주소 인자 P로 전달한다.

첫 번째 청크보다 0x10 큰 위치부터 fakeChunk를 만들었기 때문에 사이즈를 0x80으로 줌 (두 번째 청크 주소 + 0x80 위치가 fakeChunk 주소이기 때문)

 

5. 두 번째 청크 free

 

unlink 과정에

fd->bk = bk;

bk->fd = fd;

과정이 존재하는데 현재 fd->bk 와 bk->fd는 global 변수 주소인 chunk0_ptr이다.

따라서 chunk0_ptr에 fd로 설정한 주소(&전역변수 + 0x18) 값, 전역변수[3] 이 들어간다.

전역변수[3]으로 값 변경 가능

 

 

 

728x90
반응형

관련글 더보기