이번에 알아볼 기법은 unsafe unlink라는 기법이다.
해당 기법을 알아보기 전에 우선 Unlink라는 것이 무엇인지부터 살펴보도록하자.
Unlink란?
fastbin을 제외한 나머지 bins(지금부터 설명하는 내용들은 fastbin을 제외하고 나머지 bins과 관련된 설명임)는 어떤 chunk를 free할 때 바로 앞 혹은 뒤에 free chunk가 존재하면 이를 병합하여 관리하는 기능이 있다.
병합 시 기존에 bin list에 등록된 chunk가 존재하고 이들은 double linked list 구조를 가지고 있으므로 chunk 병합을 수행할 때 fd, bk를 정리해주는 과정을 거치게 된다.
이것을 unlink라고 하며 한 문장으로 정리하자면 인접한 두 free chunk를 병합할 때 fd, bk에 올바른 값으로 교체해주는 작업을 의미한다.
이때, 올바른 값이 무엇인지 모르겠다면 아래 그림을 보면 된다.
위 코드를 보면 알 수 있듯이 Unlink가 수행되기 전에 2번의 if 문을 통해 검증하고 검증이 통과해야 Unlink를 수행한다.
첫 번째 if문은 chunksize(P)와 prev_size(next_chunk(P))값이 같지 않으면 false를 반환한다.
이때 next_chunk(P)의 매커니즘은 P의 주소값부터 P의 size만큼 더하여 이동한다는 점에 유의하자.
즉, free된 chunk는 다음 인접한 chunk의 prev_size값에 자신의 size 값이 들어가 있으므로 정상적인 경우 true를 반환한다.
두 번째 if문은 FD → bk와 P가 같지 않거나 BK → fd와 P가 같지 않으면 false를 반환한다.
즉, FD → bk와 BK → fd 모두 P와 동일하면 true를 반환한다.
그럼 이 2가지 if문을 어떻게 우회할 수 있을까?
Unlink 우회는 어떻게 할까?
1. 2개의 chunk를 할당
2. Fake chunk를 할당
if문을 우회하기 위해 위 사진의 좌측하단의 조건대로 값을 적어준다.
이때 주의해서 봐야할 것은 prev_size를 0x80으로 교체했다는 점인데,
병합하는 과정에서 prev_size만큼 이동하여 그 위치에 있는 chunk를 병합하기 위함임을 알 수 있다.
즉, 0x190이 free되는 시점에 병합 루틴이 돌게 되고 0x190 - 0x80(prev_size) = 0x110 의 chunk를 대상으로 병합을 하게 된다는 것이다.
(bin list에 등록된 chunk 하나하나를 확인하는 것이 아님)
3. chunk2를 해제
[Chunk2]를 free하면서 P비트를 확인하고 0x0 이면 바로 위 chunk가 free chunk임을 알 수 있다.
바로 위 chunk와 병합을 하기 위해 unlink 과정이 수행되어야 하는데 이 unlink 과정을 수행하는 대상 chunk가 [Chunk1]이 된다.
[Chunk1]으로 이동하는 방법은 내가 현재 free한 chunk([Chunk2])를 대상으로 prev_size 값만큼 주소값에서 빼게 된다.
즉, 0x190 - 0x80 = 0x110 의 chunk에 unlink 과정을 수행하게 되는 것이다.
아래는 if 문을 어떻게 우회하는지 명확히 설명해주는 글이니 참고하길 바란다.
1) chunk size 검증
chunksize(FAKE) != prev_size(next_chunk(FAKE))
chunksize(FAKE) : 0x0
prev_size(next_chunk(FAKE)) : 0x0
이므로 첫 번째 if문은 우회가 가능하다.
이때, FAKE의 다음 chunk, next_chunk(FAKE) 를 구하는 방법은 FAKE의 size만큼 주소값을 이동해서 알아내게 된다.
즉, 0x110 + 0x0 = 0x110 이므로 다음 chunk가 자기 자신인 것처럼 속여 prev_size(next_chunk(FAKE))의 값이 0x0이 나온 것이다.
2) fd, bk 검증

동일한 위치를 가르키게 되므로 아래 조건을 만족하게 된다.
FD → bk (FAKE → fd → bk) : 0x110
BK → fd (FAKE → bk → fd) : 0x110
4. if문 우회 후
이때 먼저 FD → bk = BK (FAKE → fd → bk = FAKE → bk) 과정이 수행되긴 한다.
이는 코드를 참고하면 이해가 될 것 이다.
참고로 해당 방법은 패치가 되었으므로 glib 2.3.2 이하의 버전에서만 가능함을 밝힌다.
'Systemhacking > Base info' 카테고리의 다른 글
small bin attack (0) | 2023.06.04 |
---|---|
unsorted bin attack (0) | 2023.06.02 |
Fastbin Double Free (0) | 2021.04.04 |
Heap Base (0) | 2021.04.03 |
What is GOT & PLT (0) | 2021.01.24 |
댓글