haehet

tcache_perthread_struct overwriting 본문

Pwnable

tcache_perthread_struct overwriting

haehet 2026. 1. 26. 16:52

 이번 글에서는 원하는 곳에 tcache를 맘대로 받을 수 있는 tcache_perthread_struct overwrintg애 대해서 정리 해보겠다. (기법 이름은 사실 찾아도 잘 안나와서 내가 임의로 붙였다.)

 

1. tcache의 구조 

tcache는 스레드 별로 빠르게 할당을 해주기 위해 만들어진 목적에 맞게 malloc_state가 아닌 다른 구조체에서 관리된다. 그 구조체는 tcache_perthread_struct이다. 

static __thread tcache_perthread_struct *tcache = NULL;
typedef struct tcache_perthread_struct
{
  uint16_t counts[TCACHE_MAX_BINS];
  tcache_entry *entries[TCACHE_MAX_BINS];
} tcache_perthread_struct;

 다음과 같이 간단하게 tcache 별로 counts, entries pointer를 가지고 있다. 또한 이 구조체를 가리키는 tcache 변수는 fsbase(TLS) 근처에 저장되어 있다.

 

 

그럼 tcache_perthread_struct 구조체는 어디에 있을까? 이 질문에 대한 답은 tcache가 초기화 되는 곳에서 알 수 있다.

tcache_init(void)
{
  mstate ar_ptr;
  void *victim = 0;
  const size_t bytes = sizeof (tcache_perthread_struct);

  if (tcache_shutting_down)
    return;

  arena_get (ar_ptr, bytes);
  victim = _int_malloc (ar_ptr, bytes);
  if (!victim && ar_ptr != NULL)
    {
      ar_ptr = arena_get_retry (ar_ptr, bytes);
      victim = _int_malloc (ar_ptr, bytes);
    }

 

tcache 객체는 _int_malloc함수를 통해 초기화 된다. 즉 tcache_perthread_struct는 힙에 할당된다. 보통 우리가 heap을 보았을 때 제일 위에 있는 0x290짜리 chunk가 tcache_perthread_struct이다.

 

다음 청크가 tcache_perthread_struct이다.

 

2. tcache_perthread_struct overwriting

그렇다면 해당 청크를 덮으면 어떤 일이 발생할까? 한번 libc_base로 덮고 결과를 보자.

덮기전
덮은 후

 다음과 같이 아예 tcache의 구조가 망가진 걸 볼 수 있다. 이 상태에서 할당을 받으면 libc_base에 쓰려다가 sisgev가 난다. 이 주소를 우리가 원하는 주소로 바꿀 수 있다면 원하는 주소에 할당이 가능하다. 또한 내가 원하는 주소를 tcache의 fd에 남기면 tcache_perthread_struct가 해당 체인을 이어 주면서 해당 주소에 있는 내용을 자신의 entry에 넣는다. 이를 이용하면 leak도 가능하다. 

 

 

 

 

reference:

https://elixir.bootlin.com/glibc/glibc-2.39/source/malloc/malloc.c

'Pwnable' 카테고리의 다른 글

MIPS Architecture Exploitation  (0) 2026.05.01
FSOP 정리  (0) 2025.11.08
heap exploit 정리  (0) 2025.11.05
side channel attack(with assembly)  (0) 2025.10.02
프로그램 시작, 종료 과정 및 관련 취약점 분석  (0) 2025.08.23