2022. 8. 19. 04:13ㆍPWN
Ubuntu 22.04 (glibc-2.36)까지 업데이트가 되면서 tcache에 관한 취약점들을 보완하기 위해 여러코드가 추가되었다.
참고된 코드는 아래 링크에서 확인할 수 있다.
버전별로 코드가 약간씩 다르지만 가장 최신버전인 2.36으로 분석을 진행하였다.
분석에는 오류가 있을 수 있다.
https://github.com/bminor/glibc/blob/glibc-2.36/malloc/malloc.c#L3191
Safe-Linking
corCTF의 cshell2문제를 풀다가 tcache poisoning 과정에서 덮고싶은 got의 주소를 tcache로 변조하려고 하였는데 내가 넣은 got의 주소가 아닌 비슷하지만 이상한 값이 tcache에 들어가있어서 당황했었다.
최신 tcache 보호기법을 몰랐어서 문제를 해결하기까지 오래 삽질을 했다.
이는 safe linking이라는 glibc-2.32에서 pointer hijacking을 막기위해 추가된 fastbins 및 tcache 보호기법이라고 한다.
PROTECT_PTR과 REVEAL_PTR이 정의되어있다.
PROTECT_PTR은 주소끼리의 연산을 해서 값을 변조하고 REVEAL_PTR은 이를 되돌린다.
XOR연산의 특성을 이용하면 (addr ^ 진짜 주소 = 가짜 주소) 이면 (addr ^ 가짜 주소 = 진짜 주소) 이므로 원래의 진짜 주소를 다시 구할 수 있다.
tcache_put은 chunk를 free시킬 때 실행된다. free를 해서 tcache배열에 heap주소를 넣을때는 PROTECT_PTR을 통해 주소를 변조해서 넣고, 다시 할당을 해서 tcache배열 맨 위에 있는 주소에 값을 넣어야할 때는 REVEAL_PTR을 통해 복구된 주소에 값을 넣는다.
tcache_put에서 tcache->entries[tc_idx]는 해당 chunk의 e->next값을 의미한다.
따라서 PROTECT_PTR의 pos는 next의 주소이고, ptr은 next의 값이다.
REVEAL_PTR의 인자 ptr이 tcache의 *fd(next)이므로 PROTECT_PTR의 역연산이라는 것을 알 수 있다.
이렇게만 적어두니 잘 이해가 안갈 것 같아서 디버깅 캡쳐와 설명을 추가하였다.
인덱스 0,1,2번에 할당을 하고 0,1번을 순서대로 free한 결과 메모리 모습이다.
(heapinfo를 사용할 수 없는 문제라서 heap메모리를 통해 티캐시를 파악한다.)
tcache 상단에는 0x4056b0이 있다. 이는 인덱스 1번의 heap주소이다.
0x4056b0 내부에는 fd주소, 즉 next tcache의 주소가 있다.
만약 보호기법이 존재하지 않았다면 저 위치에는 0x4052a0 (인덱스 0번의 주소)가 있었을 것이다.
그러나 Safe - Linking 보호기법으로 인해 fd주소와 fd안의 데이터가 연산되어 0x4056a5라는 주소가 들어가있다.
정리하면, 새로운 chunk가 free되어 tcache가 될 때 tcache의 상단으로 오기때문에 새로운 tcache의 주소는 바뀌지 않는다.
새로운 tcache의 주소(0x4056b0)는 기존 최상단 tcache의 주소(0x4052a0)를 가리킨다.
이 때 tcache chunk를 생성하는 과정에서 next 주소를 넣어줄 때 0x4052a0을 그대로 넣지 않는다.
(&e->next) (tcache->entries[tc_idx])
0x4056b0 >>12 ^ 0x4052a0 의 결과인 0x4056a5를 넣는다. (PROTECT_PTR)
이 상태에서 다시 malloc을 해준다면, 최상단의 tcache를 꺼내야하기 때문에 next를 통해 다음번 tcache를 최상단으로 올려주어야한다.
이 과정에서 REVEAL_PTR을 실행하여 원래의 next를 찾고, 최상단 tcache를 꺼내서 malloc을 시켜주면 아까 찾은 주소를 최상단으로 올린다.
문제에 응용할때는 heapbase에서 000을 제외한 숫자를 tcache 주소와 연산한다고 봐도 무방하다.
(fastbin의 경우 libc의 main_arena에 존재하기 때문에 libc주소들로 연산한다.)
이러한 일련의 암호화 - 복호화 과정을 거쳐 tcache들을 연결한다.
이를 응용하여 실제로 문제를 풀 때는 (heapbase >> 12) ^ (overwrite할 주소)연산을 한 후 + 0x1까지 해주어야하는 경우가 있었다. (cshell2)
2022.08.19 - [CTF] - 2022 corCTF) Write-up (babypwn, cshell2)
tcache align
위 사진 중 tcache_get부분을 참고하면 (!aligned_OK (e))일 경우 "malloc(): unaligned tcache chunk dectected" 라는 에러를 반환하고 프로그램을 중단시키는 코드가 있다.
이는 malloc을 할 때 사이즈를 0x10단위로 끊어서 할당해주기때문에 주소도 0x10단위이고, 끝자리는 무조건 0이어야한다는 점을 이용한 보호기법이다.
aligned_OK 함수를 통해 끝자리가 0인지 검사한다.
tcache 함수 참고)
https://rninche01.tistory.com/entry/heap5-tcacheThread-local-Caching
'PWN' 카테고리의 다른 글
System Hacking) tcache key (0) | 2022.08.19 |
---|